0

I'm building an application, and the biggest problem that I'm having is the reopening of the application.

I can launch my application just fine. It creates the main window. I'm also using the setDefaultCloseOperation(HIDE_ON_CLOSE) I have also tried DISPOSE_ON_CLOSE but they both have the same effect. So when I close it the window closes out. However, when I click on the icon in my dock the window won't open back up.

I want the application to open up like Safari does, you can close out of safari but it still runs in the background and when you click on the icon in your dash it makes a new window if you don't have any open already.

halfer
  • 19,824
  • 17
  • 99
  • 186
BlankXai
  • 5
  • 2
  • Based on question, I would suggest that the JVM is still running after the window(s) are closed, using both `HIDE_ON_CLOSE` and `DISPOSE_ON_CLOSE` can do this (assuming that there is at least one non-daemon thread still running). In this situation there really isn't a way to get the window(s) to reappear, as you can link into any functionality that would tell you that the user has "clicked" on the dock item - although there "might" be away to do it under MacOS, but since it's platform specific I'm not sure it would be a solution – MadProgrammer Jan 29 '18 at 20:37

3 Answers3

0

To minimize instead of close, use JFrame.DO_NOTHING_ON_CLOSE and handle the close request

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
    public void windowClosing(WindowEvent e)
    {
        frame.setExtendedState(JFrame.ICONIFIED);
    }
});

This will minimize the frame, then the user can click the icon on the taskbar to restore

phflack
  • 2,729
  • 1
  • 9
  • 21
  • While this does technically work, it doesn't really do the job that I'm hopping to get accomplished. This might be the best option so far, but I would like to find a different way to do this. But thank you very much it does work technically. – BlankXai Jan 29 '18 at 21:54
  • @BlankXai Are you trying to make the GUI actually close? If so, wouldn't that remove the icon from the taskbar? – phflack Jan 29 '18 at 22:03
  • I'm not trying to make it close I'm trying to get it to run in the background like safari does, but if they wanted to view it then they would just click on the icon in the dock and then the window that's generated first would pop up. – BlankXai Jan 29 '18 at 22:08
  • You might be able to do this with a visual client which gets closed/launched each time, and a local server that remains running – phflack Jan 29 '18 at 22:18
  • I don't understand what you mean – BlankXai Jan 29 '18 at 22:27
  • @BlankXai Clarified as another answer – phflack Jan 31 '18 at 17:34
0

As described, it sounds like you will want two processes, one to render and one to process data

  • Client (render)
    • Needs to connect to the server
      • If the server is not running, start the server and connect
        • Server should be started as a service, background process, or could run on another machine (in the example I ran it as a background process)
    • Display data received from the server
    • Sends commands from the user to the server
  • Server (process)
    • Will not close unless instructed to
    • Accepts connections from clients
      • If only one client at a time is allowed, reject new connections until client disconnects
      • If running locally to the client, the port should only accept local connects
    • Sends data to the client to be displayed
    • Receives commands from the client

To demonstrate this, I put together some sample code

Compile both in the same folder and run TestClient

TestClient.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestClient
{
    public static void main(String[] args) throws Exception
    {
        Socket socket = null;
        try
        {
            System.out.println("Connecting to backend");
            socket = new Socket("localhost", 28000); //check if backend is running
        }
        catch(IOException e) //backend isn't running
        {
            System.out.println("Backend isn't running");
            System.out.println("Starting backend");
            Runtime.getRuntime().exec("cmd /c java TestServer"); //start the backend
            for(int i = 0; i < 10; i++) //attempt to connect
            {
                Thread.sleep(500);
                System.out.println("Attempting connection " + i);
                try
                {
                    socket = new Socket("localhost", 28000);
                    break;
                }
                catch(IOException ex){}
            }
        }

        if(socket == null)
        {
            System.err.println("Could not start/connect to the backend");
            System.exit(1);
        }

        System.out.println("Connected");
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String line = reader.readLine();
        System.out.println("read " + line);
        if(line.equals("refused")) //already a client connected
        {
            System.err.println("Already a client connected to the backend");
            System.exit(1);
        }

        //set up the GUI
        JFrame frame = new JFrame("TestClient");
        frame.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        JLabel label = new JLabel(line);
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 4;
        frame.add(label, c);

        String[] buttonLabels = {"A", "B", "Quit"};
        ActionListener listener = new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.out.println(e.getActionCommand());
                try
                {
                    switch(e.getActionCommand())
                    {
                        case "A":
                            writer.write("A");
                            writer.newLine();
                            writer.flush();
                            break;
                        case "B":
                            writer.write("B");
                            writer.newLine();
                            writer.flush();
                            break;
                        case "Quit":
                            writer.write("Quit");
                            writer.newLine();
                            writer.flush();
                            System.exit(0);
                            break;
                    }
                }
                catch(IOException ex)
                {
                    ex.printStackTrace();
                    System.exit(1);
                }
            }
        };

        c.gridy = 1;
        c.gridx = GridBagConstraints.RELATIVE;
        c.gridwidth = 1;
        for(String s : buttonLabels)
        {
            JButton button = new JButton(s);
            button.addActionListener(listener);
            frame.add(button, c);
        }

        //start a thread to listen to the server
        new Thread(new Runnable()
        {
            public void run()
            {
                try
                {
                    for(String line = reader.readLine(); line != null; line = reader.readLine())
                        label.setText(line);
                }
                catch(IOException e)
                {
                    System.out.println("Lost connection with server (probably server closed)");
                    e.printStackTrace();
                    System.exit(0);
                }
            }
        }).start();

        //display the gui
        System.out.println("Displaying");
        frame.pack();
        frame.setResizable(false);
        frame.setLocationByPlatform(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

TestServer.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class TestServer
{
    private static boolean multipleClients = true;
    private static List<Client> clients = new ArrayList<Client>();

    public static void main(String[] args) throws Exception
    {
        System.out.println("did the thing");
        ServerSocket ss = new ServerSocket(28000, 0, InetAddress.getByName(null));
        int[] index = {0}; //array so threads can access
        char[] data = {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'};

        //start accepting connections
        new Thread(new Runnable()
        {
            public void run()
            {
                while(true)
                {
                    try
                    {
                        Client c = new Client(ss.accept());
                        if(multipleClients || clients.isEmpty())
                        {
                            System.out.println("writing " + new String(data));
                            c.write(displayData(data, index[0])); //write initial data
                            synchronized(clients)
                            {
                                clients.add(c);
                            }
                        }
                        else
                            c.write("refused");
                    }
                    catch(IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        //read and write to clients
        String msg = null;
        while(true)
        {
            //read changes
            synchronized(clients)
            {
                for(Client c : clients)
                    if((msg = c.read()) != null)
                    {
                        switch(msg)
                        {
                            case "A":
                                data[index[0]++] = 'A';
                                break;
                            case "B":
                                data[index[0]++] = 'B';
                                break;
                            case "Quit":
                                System.exit(0);
                                break;
                        }
                        index[0] %= data.length;
                        for(Client C : clients)
                            C.write(displayData(data, index[0]));
                    }
            }
            Thread.sleep(50);
        }
    }

    private static String displayData(char[] data, int i)
    {
        return "<html>" + new String(data, 0, i) + "<u>" + data[i] + "</u>" + new String(data, i + 1, data.length - i - 1) + "</html>";
    }

    private static class Client
    {
        private BufferedReader reader;
        private BufferedWriter writer;
        private Queue<String> readBuffer;
        private Client me;

        public Client(Socket s) throws IOException
        {
            reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
            writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            readBuffer = new LinkedList<String>();
            me = this;

            new Thread(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        for(String line = reader.readLine(); line != null; line = reader.readLine())
                            readBuffer.add(line);
                    }
                    catch(IOException e)
                    {
                        System.out.println("Client disconnected");
                        e.printStackTrace();
                        synchronized(clients)
                        {
                            clients.remove(me); //remove(this) attempts to remove runnable from clients
                        }
                        System.out.println("removed " + clients.isEmpty());
                    }
                }
            }).start();
        }

        public String read()
        {
            return readBuffer.poll();
        }

        public void write(String s)
        {
            try
            {
                writer.write(s);
                writer.newLine();
                writer.flush();
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
phflack
  • 2,729
  • 1
  • 9
  • 21
-1
  1. You can set your frame as HIDE_ON_CLOSE when you click 'X' button in your window

  2. You need create a code similar like this:

  3. Check that we have 2 buttons with different actions (One of this is to set visible the frame after close it) try {

         Main_view frame = new Main_view();
         frame.setVisible(true);
    
         if (SystemTray.isSupported()) {
    
             SystemTray tray = SystemTray.getSystemTray();
             TrayIcon trayIcon = null;
    
             //Listener for exit button
             ActionListener ExitListener = new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
              };
    
              //Listener for display button
              ActionListener DisplayListener = new ActionListener() {
                 public void actionPerformed(ActionEvent e) {
                     frame.setVisible(true);
                 }
              };
    
               //Menu when you right click the icon
               PopupMenu popup = new PopupMenu();
    
               //Buttons to show
               MenuItem displayButton = new MenuItem("Display");
               MenuItem exitButton = new MenuItem("Exit");
    
               //add the previous actions made it
               exitButton.addActionListener(ExitListener);
               displayButton.addActionListener(DisplayListener);
    
               //add to the popup
               popup.add(displayButton);
               popup.add(exitButton);
    
               // URL: MyProject/src/MyGUI/check.png 
               // Small icon on secondary taskbar
               Image image= ImageIO.read(getClass().getResource("/MyGUI/check.png"));
               trayIcon = new TrayIcon(image, "App name", popup);
               trayIcon.setImageAutoSize(true);
    
    
               trayIcon.addActionListener(DisplayListener);
               trayIcon.addActionListener(ExitListener);
    
               try {
                    tray.add(trayIcon);
    
                   } catch (AWTException e) {
    
                          System.err.println(e);
                      }
                      // ...
                  } else {
                      // disable tray option in your application or
                      // perform other actions
                  }
    

Results

enter image description here

Heterocigoto
  • 183
  • 2
  • 11