Dri*_*mux 8 java kde system-tray gnome-shell
我需要你的帮助:我正在研究一个小的Java应用程序(Java版本7),它必须最小化到系统托盘中.
我正在使用Class SystemTray,使用SystemTray.isSupported(),然后
SystemTray systemTray = SystemTray.getSystemTray();
ImageIcon icon = new javax.swing.ImageIcon(getClass().getResource("icon.png"));
Run Code Online (Sandbox Code Playgroud)
[...]
systemTray.add(trayIcon);
Run Code Online (Sandbox Code Playgroud)
(当然有弹出窗口)
在Windows上,它运行良好.在XFCE,Xubuntu,没问题,图标正在使用弹出窗口.但是在KDE和Gnome shell上......它不起作用.
(Qt:4.8.6工具等离子:4.11.12)
SystemTray.isSupported()= true,当程序到达该行时:systemTray.add(trayIcon); 捕获异常:
托盘进程中出错:java.awt.AWTException:无法显示TrayIcon.
因此,图标是白色的,当用户点击它时不起作用,没有弹出窗口.
SystemTray.isSupported()= true,图标位于底部的通知区域,但鼠标事件不起作用...
为了解决这些问题,我认为SWT可能是一个好主意.但是当我实现它(上一个版本)时,我收到了这个警告:
警告**:无法连接到辅助功能总线:无法连接到socket/tmp/[...]
它不起作用......编辑:不再了,我可以用外部类修复SWT的问题.警告不是由SWT引起的,而是环境系统引起的(我和终端中的其他应用程序有相同的警告).
那么现在,我该怎么办?我想用&检查环境系统,然后启用或禁用系统托盘,如果它是KDE或Gnome 3 ...但是这个解决方案不是很好,因为它是多平台的本地解决方案(在操作系统的功能中我的意思),而不是全局解决方案(适用于所有操作系统的一种方法)......System.getenv("XDG_CURRENT_DESKTOP")
System.getenv("GDMSESSION")
那么,其他想法呢?我不知道......有没有办法将嵌入式JWindow定义到系统托盘中?
我自己也遇到过这个问题,我记得我在用合法的解决方案解决这个问题时遇到了困难。我追踪到问题是对 TrayIcon.addNotify() 方法的调用随机失败。我似乎记得这是因为内部的竞争条件,对 X11 系统的调用需要很长时间才能完成,因此 java 端放弃了。
但如果你有一台带有像样显卡的忍者电脑,你可能永远不会遇到这种情况,这可能就是它尚未修复的原因。我的开发机器速度很慢,所以大约 50% 的时间我都会遇到这种情况。
我确实一起破解了一个快速而肮脏的解决方案,其中涉及尝试重复调用 addNotify(在每次尝试之间暂停)直到成功(或失败了最大次数)。不幸的是,执行此操作的唯一方法是通过反射,因为 addNotify 方法是包私有的。
代码如下:
public class HackyLinuxTrayIconInitialiser extends SwingWorker<Void, TrayIcon> {
private static final int MAX_ADD_ATTEMPTS = 4;
private static final long ADD_ICON_DELAY = 200;
private static final long ADD_FAILED_DELAY = 1000;
private TrayIcon[] icons;
public HackyLinuxTrayIconInitialiser(TrayIcon... ic) {
icons = ic;
}
@Override
protected Void doInBackground() {
try {
Method addNotify = TrayIcon.class.getDeclaredMethod("addNotify", (Class<?>[]) null);
addNotify.setAccessible(true);
for (TrayIcon icon : icons) {
for (int attempt = 1; attempt < MAX_ADD_ATTEMPTS; attempt++) {
try {
addNotify.invoke(icon, (Object[]) null);
publish(icon);
pause(ADD_ICON_DELAY);
break;
} catch (NullPointerException | IllegalAccessException | IllegalArgumentException e) {
System.err.println("Failed to add icon. Giving up.");
e.printStackTrace();
break;
} catch (InvocationTargetException e) {
System.err.println("Failed to add icon, attempt " + attempt);
pause(ADD_FAILED_DELAY);
}
}
}
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException e1) {
Log.err(e1);
}
return null;
}
private void pause(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e1) {
Log.err(e1);
}
}
@Override
protected void process(List<TrayIcon> icons) {
for (TrayIcon icon : icons) {
try {
tray.add(icon);
} catch (AWTException e) {
Log.err(e);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它,只需调用:
if (<OS is Linux>) {
new HackyLinuxTrayIconInitialiser(ticon, micon, licon).execute();
} else {
try {
tray.add(ticon);
tray.add(micon);
tray.add(licon);
} catch (AWTException e) {
Log.err(e);
}
}
Run Code Online (Sandbox Code Playgroud)
我似乎记得当时我不能继续调用 SystemTray.add(icon) 因为如果我这样做的话,这会在系统托盘上留下“幽灵”托盘图标。
希望这可以帮助。
归档时间: |
|
查看次数: |
1711 次 |
最近记录: |