Java-Programm nur einmal starten: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
K
K
Zeile 74: Zeile 74:
 
}
 
}
 
</code=java>
 
</code=java>
Der Code der Anwendung ist schon für den nächsten Schritt vorbereitet, so dass in den folgenden Schritten weniger verwirrende Code-Änderungen durchgeführt werden müssen. [[Datei:Demo-Frame_01.png|200px|thumb|left|Die Ausgabe: ein leerer JFrame]]
+
Der Code der Anwendung ist schon für den nächsten Schritt vorbereitet, so dass in den folgenden Schritten weniger verwirrende Code-Änderungen durchgeführt werden müssen. [[Datei:Demo-Frame_01.png|300px|thumb|left|Die Ausgabe: ein leerer JFrame]]
  
Wir erzeugen also einen leeren {{JAPI|JFrame}}. In Zeile 8 schalten wir das Standardverhalten des JFrames beim Beenden (Klick auf den Schließen-Button des Fensters) aus. Damit der JFrame geschlossen werden kann, implementieren wir anschließend (Zeile 9 bis Zeile 13) einen {{JAPI|WindowListener}}, der für die Beendigung des Programms sorgt. Man könnte das auch auch einfacher lösen, in dem man in Zeile 8 <code>frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);</code> schreiben würde. Aber wie erwähnt wird bereits ein später benötigtes Verhalten hier implementiert.
+
Wir erzeugen also einen leeren {{JAPI|JFrame}}.<br>
In Zeile 15 fügen wir das in Zeile 21 bis Zeile 25 definierte {{JAPI|JPanel}} in dem JFrame ein. Das JPanel sorgt hier erst mal nur für die Größe des JFrames bei der Ausgabe auf dem Bildschirm. Später werden wir noch Code für das JPanel hinzufügen, der die Demo anschaulicher machen wird.
+
In Zeile 8 schalten wir das Standardverhalten des JFrames beim Beenden (Klick auf den Schließen-Button des Fensters) aus. Damit der JFrame geschlossen werden kann, implementieren wir anschließend (Zeile 9 bis Zeile 13) einen {{JAPI|WindowListener}}, der für die Beendigung des Programms sorgt. Man könnte das auch auch einfacher lösen, in dem man in Zeile 8 <code>frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);</code> schreiben würde. Aber wie erwähnt wird bereits ein später benötigtes Verhalten hier implementiert.<br>
 +
In Zeile 15 fügen wir das in Zeile 21 bis Zeile 25 definierte {{JAPI|JPanel}} in dem JFrame ein. Das JPanel sorgt hier erst mal nur für die Größe des JFrames bei der Ausgabe auf dem Bildschirm. Später werden wir noch Code für das JPanel hinzufügen, der die Demo anschaulicher machen wird.<br>
 
In Zeile 17 legen wir fest, dass die JVM unser Fenster dort auf dem Bildschirm positionieren wird, wie es den Regeln des Host-Systems zur Ausgabe von neuen Fenstern auf dem Bildschirm entspricht.
 
In Zeile 17 legen wir fest, dass die JVM unser Fenster dort auf dem Bildschirm positionieren wird, wie es den Regeln des Host-Systems zur Ausgabe von neuen Fenstern auf dem Bildschirm entspricht.

Version vom 1. April 2017, 12:17 Uhr

Baustelle.png Dieser Beitrag wird derzeit noch bearbeitet. Der Text ist deshalb unvollständig und kann Fehler oder ungeprüfte Aussagen enthalten.

Unter bestimmten Umständen kann es gewünscht sein, dass nur eine aktive Instanz eines Programms auf einem Rechner ausführbar ist. Sollte das Programm ein weiteres Mal aufgerufen werden, soll die gerade aktive, unsichtbare Instanz des Programms in den Fokus des Bedieners geholt werden. Es stellt sich also die Frage, wie kann überprüft werden, ob ein Programm schon läuft und dann das zweite Starten verhindert werden.

Im Web sind einige interessante Vorschläge zu finden, die beschreiben, wie man ein Java-Programm so programmiert, dass nur eine aktive Instanz im Arbeitsspeicher zugelassen wird, man also ein Java-Programm nur "einmal" ausführen kann.

Möglichkeiten zur Lösung gibt es. Hier einige Ansätze:

  • eine Lock-Datei
  • einen Port sperren
  • Client/Server-Anwendung
  • eine Kombination aus alle dem.

Jede der Lösungen bietet Vorteile, wie auch Nachteile in der Praxis. In unserem Artikel Java-Anwendung nur einmal ausführen - Java-Blog-Buch wurden die wichtigsten beschrieben.

Demnach ist einer der größten Nachteile beim Einsatz von Lockdateien, dass man mit einer bereits gestarteten Anwendung nicht kommunizieren kann. Man kann die laufende Instanz bspw. nicht sichtbar machen, wenn sie gerade verdeckt ist. Das Gleiche trifft auf die Port-Sperrung zu. Client-/Server-Anwendungen sind meist etwas komplexer, können aber derartige Probleme lösen.

Eine bisher nicht besprochene Lösung wird im Folgenden beschrieben. Eine Lösung mit Hilfe der seit dem JDK 1.0 mitgelieferten Java-Bibliothek für verteilte Anwendungen - RMI. Sie besticht durch ihre Einfachheit gegenüber einer Client-/Server-Anwendung und einem Maximum an Vorteilen.

RMI - eine Einführung

Um die in diesem Artikel besprochene Lösung zu programmieren, werden keine RMI-Kenntnisse vorausgesetzt, sie werden aber beim Verstehen des Codes und der Vorgehensweise helfen, so dass später die Programmierung in eigenen Programmen leichter fällt.

Daher empfehlen wir, bevor wir weiter machen, den kurz und knapp gehaltenen Einführungsartikel (RMI minimal) zu studieren.

Schritt für Schritt zum Start-Limit

Beginnen wir also nun, eine kleine Demo-Anwendung zu programmieren, mit dem Ziel, dass diese nur einmal gestartet werden kann. Weitere Starts werden nur die bereits aktive Anwendung in den Fokus des Benutzers holen. Wenn man es genau nimmt, wird zwar eine Weitere Instanz der Anwendung gestartet werden können, jedoch nach der Kommunikation mit der bereits laufenden Instanz sofort wieder beendet.

Ein einfaches Fenster

Zunächst möchten wir eine einfache Anwendung erzeugen, die wir dann im weiteren Schritt mit den gewünschten Funktionen ausbauen. <code=java> import java.awt.*; import java.awt.event.*; import javax.swing.*;

public class DemoFrame {

  public DemoFrame() {
     JFrame frame = new JFrame("Demo-Frame");
     frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
     frame.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
           frame.dispose();
        }
     });
     frame.add(createMainPanel());
     frame.pack();
     frame.setLocationByPlatform(true);
     frame.setVisible(true);
  }
  private JPanel createMainPanel() {
     JPanel panel = new JPanel(new BorderLayout());
     panel.setPreferredSize(new Dimension(600, 400));
     return panel;
  }
  public static void main(String[] args) {
     try {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

     }
     catch(Exception ex) {

System.out.println(ex);

     }
     SwingUtilities.invokeLater(new Runnable() {
        public void run() {
           new DemoFrame();
        }
     });
  }

} </code=java>

Der Code der Anwendung ist schon für den nächsten Schritt vorbereitet, so dass in den folgenden Schritten weniger verwirrende Code-Änderungen durchgeführt werden müssen.

Die Ausgabe: ein leerer JFrame

Wir erzeugen also einen leeren JFrame.
In Zeile 8 schalten wir das Standardverhalten des JFrames beim Beenden (Klick auf den Schließen-Button des Fensters) aus. Damit der JFrame geschlossen werden kann, implementieren wir anschließend (Zeile 9 bis Zeile 13) einen WindowListener, der für die Beendigung des Programms sorgt. Man könnte das auch auch einfacher lösen, in dem man in Zeile 8 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); schreiben würde. Aber wie erwähnt wird bereits ein später benötigtes Verhalten hier implementiert.
In Zeile 15 fügen wir das in Zeile 21 bis Zeile 25 definierte JPanel in dem JFrame ein. Das JPanel sorgt hier erst mal nur für die Größe des JFrames bei der Ausgabe auf dem Bildschirm. Später werden wir noch Code für das JPanel hinzufügen, der die Demo anschaulicher machen wird.
In Zeile 17 legen wir fest, dass die JVM unser Fenster dort auf dem Bildschirm positionieren wird, wie es den Regeln des Host-Systems zur Ausgabe von neuen Fenstern auf dem Bildschirm entspricht.