我有一个Java应用程序,它通过右键菜单在系统托盘中放置一个图标。当我从IDE(NetBeans)运行它时,它可以正常工作。但是当我构建它并运行JAR文件时,它会将图标放在系统托盘中,但是当我右键单击它时,它没有上下文菜单。
这是一些代码。任何帮助赞赏。我检查了平台版本和Java的控制台版本,它们看起来都是一样的。
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);
}
}
}
谢谢我设法发现这是一个缺少jar的问题。但是jar文件似乎在lib文件夹中。所以我不知道为什么它有一个边缘。 Stacktrace:
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)
答案 0 :(得分:1)
RXTX适用于依赖于其运行的操作系统的驱动程序。这些驱动程序随附RXTX库,它们是:
librxtxSerial.so
和librxtxParallel.so
。librxtxSerial.dll
和librxtxParallel.dll
。librxtxSerial.jnilib
适用于Mac This link有正确安装这些驱动程序的说明和这个问题:java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path有几种解决此类异常的解决方法。
但是,所有这些都假设您可以访问%JAVA_HOME%路径,或者您知道驱动程序所在的位置,如果您正在使用计算机,那就没问题,但如果您需要分发应用程序则不行。如果是这种情况,只需将驱动程序文件复制到放置jar
的同一文件夹中。你必须看到这样的东西才能知道它正常工作:
Stable Library ========================================= Native lib Version = RXTX-2.1-7 Java lib Version = RXTX-2.1-7
最近我注意到Linux不包含java.library.path
属性中的当前工作目录。因此,如果您只是将librxtxSerial.so
添加到app文件夹中,您仍会获得UnsatisfiedLinkError
。再次,您可以通过命令行运行应用程序时设置此属性,如下所示:
java -jar -Djava.library.path=/path/to/lib
或者你可以使用这里解释的hacky方法:Setting "java.library.path" programmatically。这种方法是不安全的,如果您有权实施另一种解决方法,我不建议使用它,但我已经尝试过这种方法并且有效:
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();
}
}