2

我想使用 Java 应用程序以本机方式在 OS X 的系统托盘/任务栏中显示文本。我想通过调用(就像在这个例子setTitle中一样)来做到这一点。我从未访问过 SWT 中的底层本机库,而且我遇到了麻烦。NSStatusItem

该线程上的某个人演示了如何调用 Objective-C 方法来更改 SWT 中窗口的属性(全屏按钮)。这是他/她的代码:

Field field = Control.class.getDeclaredField("view");
Object /*NSView*/ view = field.get(rShell);

if (view != null)
{
    Class<?> c = Class.forName("org.eclipse.swt.internal.cocoa.NSView");
    Object /*NSWindow*/ window = c.getDeclaredMethod("window").invoke(view);

    c = Class.forName("org.eclipse.swt.internal.cocoa.NSWindow");
    Method setCollectionBehavior = c.getDeclaredMethod(
        "setCollectionBehavior", JVM.is64bit() ? long.class : int.class);
    setCollectionBehavior.invoke(window, getFullScreenMask());
}

所以我想这会导致这个Objective-C代码:

[window setCollectionBehaviour:1<<7];

现在我想对 SWT 做同样的事情TrayItem。目标是获得与此 Objective-C 代码等效的代码:

[statusItem setTitle:@"Status"];

但我得到以下异常:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set org.eclipse.swt.internal.cocoa.NSView field org.eclipse.swt.widgets.Control.view to org.eclipse.swt.widgets.TrayItem
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
    at java.lang.reflect.Field.get(Field.java:358)
    at com.teez.status.MainStatus.main(MainStatus.java:35)

我不确定这意味着什么。我标记了引发异常的行。尝试此操作时我还会遇到哪些其他问题?这是我的代码:

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;

public class MainStatus {

    public static void main(String[] args) throws Exception {
        Display display = new Display();
        Shell shell = new Shell(display);
        Tray tray = display.getSystemTray();


        if (tray != null) {
            TrayItem item = new TrayItem(tray, SWT.NONE);

            Field field = Control.class.getDeclaredField("view");
            Object /*NSView*/ view = field.get(item); //Exception thrown here

            if (view != null)
            {
                Class<?> c = Class.forName("org.eclipse.swt.internal.cocoa.NSView");
                Object /*NSWindow*/ window = c.getDeclaredMethod("window").invoke(view);

                c = Class.forName("org.eclipse.swt.internal.cocoa.NSStatusItem");


                Method setCollectionBehavior = c.getDeclaredMethod("setTitle", long.class);

                setCollectionBehavior.invoke(window, "Desired title");
            }

            while (!shell.isDisposed ()) {
                if (!display.readAndDispatch ()) display.sleep ();
            }
            display.dispose ();

        }

    }

}

编辑:感谢尤金解决了这个问题,但文本仍然没有出现在状态栏上,所以我在这里问了另一个问题。

4

1 回答 1

1

托盘项不是控件。您需要在该类层次结构中查找 Cocoa 句柄。

来源来看, Cocoa 句柄存储在“item”字段中,它是 NSStatusItem 的实例。

不幸的是,我无法在 atm 测试它。

于 2012-12-28T20:04:26.983 回答