Приложение с одним экземпляром JavaFX

Попытка сделать так, чтобы когда пользователь «закрывает» программу, нажимая все кнопки выхода, чтобы значок в трее больше не отображался.

Я вызвал Platform.setImplicitExit(false); поэтому программа все еще работает в фоновом режиме.

Я пытаюсь узнать, как это сделать, когда пользователь повторно щелкает файлы .exe, которые запускают банку, вместо запуска новой программы он повторно показывает ту, которая работает в фоновом режиме.

 Platform.setImplicitExit(false);

person Community    schedule 09.12.2016    source источник
comment
Я использовал jsmooth для создания .exe   -  person    schedule 09.12.2016


Ответы (1)


Это основано на решении в сообщении блога: Java Single Instance Application< /а>.

В решении используется «Техника сокетов»:

С помощью этой техники мы начинаем прослушивать порт, только один процесс может прослушивать сокет, поэтому после того, как первый экземпляр нашего приложения привязывается к сокету, другие экземпляры получат BindException, что означает, что мы уже запущены.

Минусы этого подхода в том, что некоторые антивирусные сканеры выдают предупреждение, когда приложение начинает прослушивать сокет, в зависимости от вашей пользовательской базы это может быть неправильно интерпретировано. Вы должны выбрать номер порта, который обычно не используется и является большим, иначе вы даже не запустите ни одного экземпляра своего приложения.

В примере мы создали уникальный идентификатор экземпляра для экземпляра приложения и записали некоторые параметры.

уникальный

  • Свернуть сворачивает окно.
  • Скрыть скрывает его (поэтому оно не отображается как свернутое, но приложение продолжает работать).
  • Выход завершает процесс подачи заявки.

Кнопка закрытия ОС в окне закроет окно приложения, но процесс приложения продолжит работу в фоновом режиме (поэтому он действует так же, как кнопка «Скрыть»).

Когда вы запускаете экземпляр приложения, он открывает сокет и слушает его.

Когда вы пытаетесь запустить другой экземпляр приложения, он попытается привязаться к слушающему сокету. Если он не может выполнить привязку, то он знает, что на этом сокете уже запущен экземпляр приложения. Если обнаружен другой экземпляр, через сокет в существующий экземпляр отправляется сообщение, в результате чего существующий экземпляр показывает или разворачивает себя и пытается вывести свою сцену на передний план.

Пожалуйста, не злоупотребляйте этим, есть много программ, которые прячутся в фоновом режиме, что мне не нравится.

import javafx.application.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;

public class SingleInstanceApp extends Application {

    private static final int SINGLE_INSTANCE_LISTENER_PORT = 9999;
    private static final String SINGLE_INSTANCE_FOCUS_MESSAGE = "focus";

    private static final String instanceId = UUID.randomUUID().toString();

    // We define a pause before focusing on an existing instance
    // because sometimes the command line or window launching the instance
    // might take focus back after the second instance execution complete
    // so we introduce a slight delay before focusing on the original window
    // so that the original window can retain focus.
    private static final int FOCUS_REQUEST_PAUSE_MILLIS = 500;

    private Stage stage;

    public void init() {
        CountDownLatch instanceCheckLatch = new CountDownLatch(1);

        Thread instanceListener = new Thread(() -> {
            try (ServerSocket serverSocket = new ServerSocket(SINGLE_INSTANCE_LISTENER_PORT, 10)) {
                instanceCheckLatch.countDown();

                while (true) {
                    try (
                            Socket clientSocket = serverSocket.accept();
                            BufferedReader in = new BufferedReader(
                                    new InputStreamReader(clientSocket.getInputStream()))
                    ) {
                        String input = in.readLine();
                        System.out.println("Received single instance listener message: " + input);
                        if (input.startsWith(SINGLE_INSTANCE_FOCUS_MESSAGE) && stage != null) {
                            Thread.sleep(FOCUS_REQUEST_PAUSE_MILLIS);
                            Platform.runLater(() -> {
                                System.out.println("To front " + instanceId);
                                stage.setIconified(false);
                                stage.show();
                                stage.toFront();
                            });
                        }
                    } catch (IOException e) {
                        System.out.println("Single instance listener unable to process focus message from client");
                        e.printStackTrace();
                    }
                }
            } catch(java.net.BindException b) {
                System.out.println("SingleInstanceApp already running");

                try (
                        Socket clientSocket = new Socket(InetAddress.getLocalHost(), SINGLE_INSTANCE_LISTENER_PORT);
                        PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()))
                ) {
                    System.out.println("Requesting existing app to focus");
                    out.println(SINGLE_INSTANCE_FOCUS_MESSAGE + " requested by " + instanceId);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                System.out.println("Aborting execution for instance " + instanceId);
                Platform.exit();
            } catch(Exception e) {
                System.out.println(e.toString());
            } finally {
                instanceCheckLatch.countDown();
            }
        }, "instance-listener");
        instanceListener.setDaemon(true);
        instanceListener.start();

        try {
            instanceCheckLatch.await();
        } catch (InterruptedException e) {
            Thread.interrupted();
        }
    }

    public void stop() {
        System.out.println("Exiting instance " + instanceId);
    }

    @Override
    public void start(Stage stage) throws Exception{
        this.stage = stage;

        System.out.println("Starting instance " + instanceId);

        Platform.setImplicitExit(false);

        Button minimize = new Button("Minimize");
        minimize.setOnAction(event -> stage.setIconified(true));

        Button hide = new Button("Hide");
        hide.setOnAction(event -> stage.hide());

        Button exit = new Button("Exit");
        exit.setOnAction(event -> Platform.exit());

        Label instance = new Label(instanceId);

        Pane layout = new VBox(10, instance, new HBox(10, minimize, hide, exit));
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
person jewelsea    schedule 09.12.2016