-3

I am creating an app center and I need to read from the property file to retrieve the app name and shortcut and this is the info I retrieve.

Format for properties file: apps=chrome#youtube#eclipse#controlpanel

controlpanelpath=blahblah

I can retrieve this info but I need to add buttons with how many apps there are. For example, I add an app then when I restart the app it will display as a button.

    import java.io.File;
     import java.io.FileInputStream;
     import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
     import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
 import java.util.Properties;

   import org.omg.CORBA.portable.InputStream;

   public class appmanager {
   public static String iconpath, path, name;

     public static Properties prop = new Properties();
     public static String result = "";
     public static String filename = "apps.properties";
       public static String appdata = System.getenv("APPDATA");
     public static String configpath = appdata + "\\" + filename;
     public static File properties = new File(configpath);
   public static OutputStream output = null;

     public static String apps[];
     public static String raw_apps;

    public static void gather() throws IOException{

    output = new FileOutputStream(configpath);
    raw_apps = prop.getProperty("apps");
    apps=raw_apps.split(",");
    //Add app path with the name in apps array



    //add button to Jframe 'hud'



    output.close();

    }


public static void retrieve() throws IOException{

    if(properties.exists()){
    create();


    }
    else{


        gather();




    }





}

public static void send(){

}
public static void add(){
    iconpath=appdetails.file;
    path=MainGui.file;
}
public static void create() throws IOException{

    System.out.println(configpath);

    output = new FileOutputStream(configpath);




    output.close();

        }
          }

The main app center jframe is in another class and it is called "hud".

BTW I only need the adding buttons by how many apps there are part! Thanks

silentcallz
  • 101
  • 4
  • 14
  • 1
    What have you tried? What code have you written so far? What problems did you encounter? – Jan Dörrenhaus Nov 18 '15 at 00:09
  • I only added a jframe in another class and a get properties code. I can get properties just dont know what to do with it – silentcallz Nov 18 '15 at 00:11
  • The point is: Show us what you have done so far. We will gladly help you debug your code, or figure out your problems. – Jan Dörrenhaus Nov 18 '15 at 00:16
  • Create a factory method which takes the information from your configuration file and creates a new `JButton` based on the properties – MadProgrammer Nov 18 '15 at 00:43
  • can you write some code to demonstrate and sorry this is my first post! I am between advanced and beginners. I am familiar with Swing and files but not much other. – silentcallz Nov 18 '15 at 00:47

1 Answers1

3

An Object Oriented approach:

The following approach utilizes a JSON config file. The file is parsed, using Google's GSON library, and the information in the configuration file is what the application uses to construct the buttons.

This has been tested and verified to work. You may need to remove or change the application paths for your application to function correctly.

Note: You will need a dependency management system i.e. Maven or Gradle to pull in GSON or you could download a jar and link it manually.

Screenshot

Screenshot

Structure

This is the skeleton structure for the application.

> AppLauncher/
  > src/
    > app/
      > component/
        - AppButton.java
      > config/
        > dto/
          - AppConfig.java
          - RootConfig.java
     > view/
       - AppDashboard.java
    > resources/
      - appConfig.json
    - AppLauncher.java

Classes and Files

AppLauncher

This is the application launcher which starts the application after reading the config file.

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import app.config.dto.RootConfig;
import app.config.reader.ConfigReader;
import app.view.AppDashboard;

public class AppLauncher {
    public static final String APP_TITLE = "App Launcher";

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame(APP_TITLE);
                RootConfig config = ConfigReader.read("/resources/appConfig.json");
                AppDashboard dashboard = new AppDashboard(config);

                System.out.println(config);

                frame.setContentPane(dashboard);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

AppDashboard

This view holds the buttons for each of the applications defined in the config.

package app.view;

import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

import app.component.AppButton;
import app.config.dto.AppConfig;
import app.config.dto.RootConfig;

public class AppDashboard extends JPanel {
    private static final long serialVersionUID = -3885872923055669204L;

    private RootConfig config;
    private List<AppButton> buttons;

    public AppDashboard(RootConfig config) {
        super(new FlowLayout());

        this.config = config;

        buttons = new ArrayList<AppButton>();

        for (AppConfig appConfig : config.getApplications()) {
            buttons.add(new AppButton(appConfig));
        }

        createChildren();
    }

    protected void createChildren() {
        for (AppButton button : buttons) {
            this.add(button);
        }
    }
}

AppButton

This is the application button which has a text label and a launch action when the button is triggered. This can be extended to render the icon of the application.

package app.component;

import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JButton;

import app.config.dto.AppConfig;

public class AppButton extends JButton {
    private static final long serialVersionUID = -730609116042003884L;

    private AppConfig config;

    public AppButton(AppConfig config) {
        super();

        this.config = config;

        setAction(new AbstractAction(config.getName()) {
            private static final long serialVersionUID = -2999563123610952893L;

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    launch();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });
    }

    private String[] procArguments() {
        List<String> commands = config.getArguments();

        commands.add(0, config.getPath());

        return commands.toArray(new String[commands.size()]);
    }

    /**
     * @see http://stackoverflow.com/questions/13991007/execute-external-program-in-java
     */
    public void launch() throws IOException {
        String[] args = procArguments();
        Process process = new ProcessBuilder(args).start();
        InputStream is = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;

        System.out.printf("Output of running %s is:", Arrays.toString(args));

        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }
}

ConfigReader

This handles reading the JSON config file and marshaling it into a java DTO (data transfer object) which will be used by the application's components.

package app.config.reader;

import java.io.InputStreamReader;

import com.google.gson.Gson;

import app.config.dto.RootConfig;

public class ConfigReader {
    private static ClassLoader loader = ConfigReader.class.getClassLoader();

    public static RootConfig read(String filename) {
        return new Gson().fromJson(getInputStream(filename), RootConfig.class);
    }

    private static InputStreamReader getInputStream(String filename) {
        return new InputStreamReader(loader.getResourceAsStream(filename));
    }
}

RootConfig

This it the root of the config which holds the application configurations.

package app.config.dto;

import java.util.List;

public class RootConfig {
    private List<AppConfig> applications;

    public List<AppConfig> getApplications() {
        return applications;
    }

    public void setApplications(List<AppConfig> applications) {
        this.applications = applications;
    }

    @Override
    public String toString() {
        return "RootConfig [applications=" + applications + "]";
    }
}

AppConfig

This is an application configuration describing the application.

package app.config.dto;

import java.util.List;

public class AppConfig {
    private String name;
    private String path;
    private List<String> arguments;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public List<String> getArguments() {
        return arguments;
    }

    public void setArguments(List<String> arguments) {
        this.arguments = arguments;
    }

    @Override
    public String toString() {
        return "AppConfig [name=" + name + ", path=" + path + ", arguments=" + arguments + "]";
    }
}

appConfig.json

This is the configuration file which will be read by the application to create the buttons.

{
    "applications" : [
        {
            "name" : "Chrome",
            "path" : "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
            "arguments" : []
        }, {
            "name" : "Eclipse",
            "path" : "C:/Eclipse/current/eclipse.exe",
            "arguments" : []
        }, {
            "name" : "Control Panel",
            "path" : "C:/Windows/System32/control.exe",
            "arguments" : []
        }
    ]
}

pom.xml Dependencies

These are Maven dependencies which are required for the program to parse the JSON file. You may use another parsing library such as Jackson or JsonLib.

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.4</version>
    </dependency>
</dependencies>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • are there alternatives? – silentcallz Nov 18 '15 at 01:43
  • keep in mind that i use properties files and need as less code as possible – silentcallz Nov 18 '15 at 01:45
  • Why should your configuration be a property file and why must your code be as small ass possible? Java is an OOP language. I broke down the components into their own classes for a reason (separation of concerns). JSON is far more readable and alterable. These reasons are why I chose this approach. I will consider your approach. – Mr. Polywhirl Nov 18 '15 at 01:53
  • i need to add apps dynammically and the path cannot be hardcopied in code – silentcallz Nov 18 '15 at 01:53
  • The path is not hard-copied... it's in the config? I am not sure what you mean? – Mr. Polywhirl Nov 18 '15 at 01:57
  • or I can use array length then use for loop to find all the paths then add buttons with button blah = new Button(); Action listener then add to frame – silentcallz Nov 18 '15 at 01:59
  • In your post you said that "[you] can retrieve this info", so the provided config is not necessary for your use case. All you need to do is send the information you have acquired from your config and send it over to your button class. **Note:** My example is more *general* and may not work *exactly* as you would wish, but it helps satisfy others who have similar issues, that you have, with dynamically creating components in a Swing application. – Mr. Polywhirl Nov 18 '15 at 02:04