由于我不熟悉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.

推荐答案

您可以使用DISPATCH_ASYNC()和DISPATCH_SYNC()在UI线程上执行操作.NSObject还包括将在主线程上执行 Select 器的方法performSelectorOnMainThread:withObject:waitUntilDone:.

这是使用Java Objective-c桥的要点,它执行类似如下的操作:

https://gist.github.com/anonymous/3966989

对于您的特定问题,您可以将方法体包装在DISPATCH_ASYNC中

JNIEXPORT void JNICALL Java_NativeOpenFileDialog_run (JNIEnv *thisEnv, jclass jcls) {
dispatch_async(dispatch_get_main_queue(), ^{
  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];
});

}

当然,这只会打开对话框而不会对用户 Select 的文件执行任何操作,因此您需要在此基础上进行构建.

Java相关问答推荐

当列顺序更改时,Table View列列表的Change. wasPermanted()总是返回假

那么比较似乎不是词典学的,尽管doctor 这么说

如何在Android上获取来电信息

上下文初始化期间遇到异常-使用Java配置配置HibernateTemplate Bean时

如何从错误通道回复网关,使其不会挂起

GetChildren().emoveAll()不会删除 node

%This内置函数示例

使用正则表达式从字符串中提取多个值

没有使用Lombok生成的参数

在macOS上读取文件会导致FileNotFound,即使文件存在(并且具有权限)

IntelliJ IDEA依赖项工具窗口丢失

每次我需要时创建和关闭数据库连接会有什么效果吗?

我该如何为我的类编写getter和setter方法?

无法在Java中获取ElastiCache的AWS CloudWatch指标

无限递归Java问题

如何使JOOQ渐变脚本不重新创建表未更改的类?

javax.crypto-密码对象-提供者服务是如何工作的?

Java中计算大n和k值模10^9+7的二项式系数的乘法公式输出错误值

为什么child-pom会创建一个新版本

从 Java 17 切换回 Java 8 后出现的问题