简体   繁体   中英

How do I invoke Objective-C methods on SWT objects?

I'd like to use a Java application to display text in the system tray / task bar on OS X in a native way. I'd like to do this by invoking setTitle on the NSStatusItem (like in this example ). I've never accessed the underlying native libraries in SWT, and I'm having trouble with it.

Someone on this thread demonstrated how to invoke an Objective-C method to change a property of a window in SWT (the full-screen button). Here is his/her code:

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());
}

So I suppose this would result in this Objective-C code:

[window setCollectionBehaviour:1<<7];

Now I'd like to do the same for an SWT TrayItem . The goal is to get the equivalent of this Objective-C code:

[statusItem setTitle:@"Status"];

But I'm getting the following exception:

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)

I'm not sure what this means. I marked the line where the exception is thrown. What other issues could I run into while attempting this? Here is my code:

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 ();

        }

    }

}

Edit: Thanks Eugene for solving this problem, but the text is still not showing up on the status bar, so I asked another question here .

Tray item is not a control. You need to look for a Cocoa handle in that class hierarchy.

Judging from sources the Cocoa handle is stored in "item" field and it is instance of NSStatusItem.

Unfortunately, I can't test it atm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM