Question

J'ai une application Java qui met une icône dans le Systray avec un menu de clic droit. Lorsque je l'exécute à partir de l'IDE (NetBeans), cela fonctionne correctement. Mais lorsque je le construit et que je fais l'exécution du fichier JAR, il met l'icône dans le systray mais lorsque je clique avec le bouton droit dessus, il n'a pas de menu contextuel.

Voici un code. Toute aide appréciée. J'ai vérifié la version de la plate-forme et la version console de Java et elles semblent toutes deux être les mêmes.

package abaxis;

import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class Systray
{
    private TrayIcon trayIcon = null;
private Image databaseimage;
private Image databaseDisconnectedImage;
public PopupMenu popup;
private ActionListener exitListener;
private ActionListener settingsListener;
private ActionListener connectListener;
private ActionListener disconnectListener;
private static Systray instance;
private static Abaxis abaxis = null;

private SystemTray tray;

private MenuItem connectItem;
private MenuItem settingsItem; 
private MenuItem exitItem;
private MenuItem disconnectItem;

public Systray() 
{
    // create a action listener to listen for default action executed on the tray icon
    exitListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) 
        {
            System.exit(0);
        }
    };
    settingsListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) 
        {
            //New Jframe.
            JFrame settingsJFrame = new AbaxisSettingsForm();
            settingsJFrame.setVisible(true);
        }
    };
    connectListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) 
        {
            //Start the application.
            abaxis.connect();
            setConnectedItems();
        }
    };
    disconnectListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) 
        {
            //Discconect the application.
            abaxis.disconnect();
            setDisconnectedItems();
        }
    };
}

public static Systray getSystray()
{
    if(instance == null)
    {
        instance = new Systray();
        instance.init();
    }
    return instance;
}

public void init()
{
    // get the SystemTray instance
    tray = SystemTray.getSystemTray();
    // load Images
        databaseimage = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/database.png"));
        databaseDisconnectedImage = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/database_delete.png"));
    // create a popup menu
    this.popup = new PopupMenu();

    // create menu item for the default action
    connectItem = new MenuItem("Connect");
    connectItem.addActionListener(connectListener);
    settingsItem = new MenuItem("Settings");
    settingsItem.addActionListener(settingsListener);
    exitItem = new MenuItem("Exit");
    exitItem.addActionListener(exitListener);
    disconnectItem = new MenuItem("Disconnect");
    disconnectItem.addActionListener(disconnectListener);       

    // set the TrayIcon properties
    //trayIcon.addActionListener(exitListener);
    // construct a TrayIcon
    trayIcon = new TrayIcon( databaseimage, "Abaxis", this.popup );
    // add the tray image
    try 
    {
        tray.add(trayIcon);
    } 
    catch (AWTException e) 
    {
        System.err.println(e);
    }

    try 
    {
        abaxis = Abaxis.start();
    } 
    catch (Exception e)
    {
        System.out.println(e.getMessage());
    }

    if(abaxis.isConnected())
    {
        //Set all the stuff if its connected.
        setConnectedItems();
    } 
    else
    {
        //Set all the stuff if its disconnected.
        setDisconnectedItems();
    }
}

private void setConnectedItems()
{
    this.popup.removeAll();
    this.popup.add(disconnectItem);
    this.popup.add(settingsItem);
    this.popup.add(exitItem);
    this.updateImage(databaseimage);

}

private void setDisconnectedItems()
{
    this.popup.removeAll();
    this.popup.add(connectItem);
    this.popup.add(settingsItem);
    this.popup.add(exitItem);
    this.updateImage(databaseDisconnectedImage);
}

public void updateImage(Image x)
{
    if (this.trayIcon != null) 
    {
         this.trayIcon.setImage(x);
    }
}

}

Merci, j'ai réussi à constater que c'était un problème avec un pot manquant. Mais le fichier JAR semble être dans le dossier lib. Je ne sais donc pas pourquoi il a un essai. Trace de la pile:

java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver
    Exception in thread "main" java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.loadLibrary0(Unknown Source)
    at java.lang.System.loadLibrary(Unknown Source)
    at gnu.io.CommPortIdentifier.<clinit>(CommPortIdentifier.java:123)
    at abaxis.Abaxis.connectToBloodMachine(Abaxis.java:114)
    at abaxis.Abaxis.connect(Abaxis.java:90)
    at abaxis.Abaxis.init(Abaxis.java:76)
    at abaxis.Abaxis.start(Abaxis.java:53)
    at abaxis.Systray.init(Systray.java:141)
    at abaxis.Systray.getSystray(Systray.java:88)
    at abaxis.Abaxis.main(Abaxis.java:279)
Était-ce utile?

La solution

RXTX fonctionne avec des pilotes qui dépendent du système d'exploitation qu'il fonctionne. Ces pilotes sont fournis avec la bibliothèque RXTX et ils sont:

  • librxtxSerial.so et librxtxParallel.so pour Linux.
  • librxtxSerial.dll et librxtxParallel.dll Pour les fenêtres.
  • librxtxSerial.jnilib pour Mac

Ce lien a les instructions pour installer correctement ces pilotes et cette question: java.lang.unsatisfiedlinkerror: pas de rxxxserial dans java.library.path a plusieurs solutions de contournement pour résoudre ce type d'exception.

Cependant, tous supposent que vous avez accès à% java_home% chemin ou que vous savez où se trouvent les pilotes, ce qui est bien si vous travaillez sur votre ordinateur, mais ce n'est pas OK si vous devez distribuer votre application. Si tel est le cas, copiez simplement les fichiers du pilote dans le même dossier où votre jar est placé. Vous devez voir quelque chose comme ça pour savoir que cela fonctionne correctement:

Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7

Mise à jour

Récemment, j'ai remarqué que Linux n'inclut pas le répertoire de travail actuel dans java.library.path propriété. Par conséquent si vous ajoutez simplement librxtxSerial.so dans le dossier d'applications que vous obtenez toujours UnsatisfiedLinkError. Encore une fois, vous pouvez définir cette propriété lorsque vous exécutez l'application via la ligne de commande comme ceci:

java -jar -Djava.library.path=/path/to/lib

Ou vous pouvez utiliser une approche hacky expliquée ici: Définition "java.library.path". Cette approche est dangereuse et je ne le recommande pas si vous avez accès à la mise en œuvre d'une autre solution de contournement, mais j'ai essayé cela et cela fonctionne:

String javaLibraryPath = System.getProperty("java.library.path");

if(!javaLibraryPath.contains(File.pathSeparator + "." + File.pathSeparator)){

    StringBuilder sb = new StringBuilder(javaLibraryPath).append(File.pathSeparator).append(".");
    // The line above appends "." (current directory) to the library path
    // Of course 'rxtxSerial.so' must be placed in the current directory

    System.setProperty("java.library.path", sb.toString());

    try {
        Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
        sysPathsField.setAccessible(true);
        sysPathsField.set(null, null);// Setting this field to null will force a reevaluation of 
                                      // the library path as soon as loadLibrary() is called

    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
        ex.printStackTrace();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top