由于我不熟悉JNI-C和JNF,我只能让JNI类部分执行.到目前为止,我try 的方法如下:
这里是Open.java,它是一个更重要的Java Swing应用程序的MCV,它配得上一个更好看、功能更强大的打开文件对话框,而不是不合理的java.awt.FileDialog
或丑陋而功能不佳的javax.swing.JFileChooser
.
import java.awt.event.*;
import javax.swing.*;
public class Open extends JFrame {
public Open () {
getContentPane().add(new JButton(new AbstractAction() {
public void actionPerformed (ActionEvent e) {
try {
NativeOpenFileDialog.run();
} catch (Throwable ex) {
System.err.println(ex.getMessage());
}
}
}));
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() { new Open(); }
});
}
}
以下是NativeOpenFileDialog.Java
import javax.swing.*;
public class NativeOpenFileDialog {
static {
System.loadLibrary("natopndlg");
};
public static native void run ();
public static void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() { NativeOpenFileDialog.run(); }
});
}
}
以下是NativeOpenFileDialog.m
#import <Cocoa/Cocoa.h>
#include <jni.h>
#include "NativeOpenFileDialog.h"
JNIEXPORT void JNICALL Java_NativeOpenFileDialog_run (JNIEnv *thisEnv, jclass jcls) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:YES];
[panel setAllowsMultipleSelection:YES];
if ([panel runModal] != NSModalResponseOK)
NSLog(@"User did not press OK");
[pool release];
}
下面是Makefile(我使用的是Xcode15.2):
SDK = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
Open.class: Open.java NativeOpenFileDialog.java NativeOpenFileDialog.m
javac -h . NativeOpenFileDialog.java
javac Open.java
gcc -dynamiclib -o libnatopndlg.dylib -framework Cocoa -isysroot $(SDK) -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/darwin -fobjc-exceptions -std=c99 NativeOpenFileDialog.m
这是我在执行make
次后的执行方式.
java Open
单击该按钮会引发例外情况:
NSInternalInconsistencyException', reason: 'NSWindow should only be instantiated on the main thread!
知道面板应该在UI线程上打开,这是可以理解的.我相信我要做的就是确保NSOpenPanel创建的窗口是JFrame的子窗口,并在UI线程上打开.我认为这至少意味着我必须执行Java函数才能获得JFrame的NSWindow.