捕获关于、首选项和退出菜单项
Capture about, preferences and quit menu items
我正在使用当前版本的 SWT 构建我的应用程序,我想 运行 它在 Mac OS X (Yosemite) 下。
我现在的问题是,我无法捕获自动添加到我的应用程序中的 "About"、"Preferences" 和 "Quit" 菜单项的点击。
我已经搜索了很多并找到了以下 class 这对我来说似乎很有帮助 http://www.transparentech.com/files/CocoaUIEnhancer.java.
这是我初始化它的代码:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class Test {
private Display display;
private Shell shell;
public Test(Display display) {
this.display = display;
initUI();
}
public void open() {
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
private void initUI() {
shell = new Shell(display);
shell.setSize(808, 599);
shell.setText("Test");
AboutHandler aboutHandler = new AboutHandler();
PreferencesHandler preferencesHandler = new PreferencesHandler();
QuitHandler quitHandler = new QuitHandler();
CocoaUIEnhancer uienhancer = new CocoaUIEnhancer("Test");
uienhancer.hookApplicationMenu(display, quitHandler, aboutHandler, preferencesHandler);
}
private class AboutHandler implements Listener {
public void handleEvent(Event e) {
}
}
private class PreferencesHandler implements Listener {
public void handleEvent(Event e) {
}
}
private class QuitHandler implements Listener {
public void handleEvent(Event e) {
}
}
}
我可以毫无错误地编译它,但是如果我启动程序,我将得到以下异常:
Exception in thread "main" java.lang.NoSuchMethodError: actionProc
at org.eclipse.swt.internal.Callback.bind(Native Method)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at CocoaUIEnhancer.initialize(CocoaUIEnhancer.java:124)
at CocoaUIEnhancer.hookApplicationMenu(CocoaUIEnhancer.java:92)
at Test.initUI(Test.java:50)
at Test.<init>(Test.java:18)
这可能是本地库中的一个错误,但我无法弄清楚!
看起来像这样 actionProc
int actionProc( int id, int sel, int arg0 )
in CocoaUIEnhancer
可能需要使用 long
而不是 int
来使参数与 64 位 SWT 一起工作。
您需要修改 CocoaUIEnhancer.java,使其与 this tutorial 中所述的纯 SWT 应用程序一起工作:
- Modify the getProductName() method to return a String when no product is found (instead of null)
- Wrap the code in hookWorkbenchListener() in a try-catch (IllegalStateException e) block
- Wrap the code in modifyShells() in a try-catch (IllegalStateException e) block
- Add some code to the actionProc(...) method, to bring up an About-Dialog and Preferences-Dialog (since we aren’t using commands):
static long actionProc(long id, long sel, long arg0) throws Exception {
// ...
else if (sel == sel_preferencesMenuItemSelected_) {
showPreferences();
} else if (sel == sel_aboutMenuItemSelected_) {
showAbout();
}
return 0;
}
private static void showAbout() {
MessageDialog.openInformation(null, "About...",
"Replace with a proper about text / dialog");
}
private static void showPreferences() {
System.out.println("Preferences...");
PreferenceManager manager = new PreferenceManager();
PreferenceDialog dialog = new PreferenceDialog(null, manager);
dialog.open();
}
// ...
Finally, we add the following lines to our main() method:
public static final String APP_NAME = "MyApp";
public static void main(String[] args) {
//in your case change the Test constructor
Display.setAppName(APP_NAME);
Display display = Display.getDefault();
//insert in initUI method call the earlysetup
if (SWT.getPlatform().equals("cocoa")) {
new CocoaUIEnhancer().earlyStartup();
}
Shell shell = new Shell(display);
shell.setText(APP_NAME);
...
}
引用代码。
我根本没有使用 CocoaUIEnhancer
,因为它也引起了问题。
所以这就是我最终在我的应用程序中所做的事情:
/**
* Convenience method that takes care of special menu items (About, Preferences, Quit)
*
* @param name The name of the menu item
* @param parent The parent {@link Menu}
* @param listener The {@link Listener} to add to the item
* @param id The <code>SWT.ID_*</code> id
*/
private void addMenuItem(String name, Menu parent, Listener listener, int id)
{
if (OSUtils.isMac())
{
Menu systemMenu = Display.getDefault().getSystemMenu();
for (MenuItem systemItem : systemMenu.getItems())
{
if (systemItem.getID() == id)
{
systemItem.addListener(SWT.Selection, listener);
return;
}
}
}
/* We get here if we're not running on a Mac, or if we're running on a Mac, but the menu item with the given id hasn't been found */
MenuItem item = new MenuItem(parent, SWT.NONE);
item.setText(name);
item.addListener(SWT.Selection, listener);
}
分别用SWT.ID_PREFERENCES
、SWT.ID_ABOUT
、SWT.ID_QUIT
调用即可。提交后备菜单项名称、后备 Menu
和您要添加到菜单项的实际 Listener
。
例如:
addMenuItem("Quit", myMenu, new Listener()
{
@Override
public void handleEvent(Event event)
{
// Close database connection for example
}
}, SWT.ID_QUIT);
Baz 的解决方案非常有效!如果您不想导入 OSUtils 只是为了测试您是否在 Mac 上,请改用:
System.getProperty("os.name").contentEquals("Mac OS X")
我正在使用当前版本的 SWT 构建我的应用程序,我想 运行 它在 Mac OS X (Yosemite) 下。
我现在的问题是,我无法捕获自动添加到我的应用程序中的 "About"、"Preferences" 和 "Quit" 菜单项的点击。
我已经搜索了很多并找到了以下 class 这对我来说似乎很有帮助 http://www.transparentech.com/files/CocoaUIEnhancer.java.
这是我初始化它的代码:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class Test {
private Display display;
private Shell shell;
public Test(Display display) {
this.display = display;
initUI();
}
public void open() {
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
private void initUI() {
shell = new Shell(display);
shell.setSize(808, 599);
shell.setText("Test");
AboutHandler aboutHandler = new AboutHandler();
PreferencesHandler preferencesHandler = new PreferencesHandler();
QuitHandler quitHandler = new QuitHandler();
CocoaUIEnhancer uienhancer = new CocoaUIEnhancer("Test");
uienhancer.hookApplicationMenu(display, quitHandler, aboutHandler, preferencesHandler);
}
private class AboutHandler implements Listener {
public void handleEvent(Event e) {
}
}
private class PreferencesHandler implements Listener {
public void handleEvent(Event e) {
}
}
private class QuitHandler implements Listener {
public void handleEvent(Event e) {
}
}
}
我可以毫无错误地编译它,但是如果我启动程序,我将得到以下异常:
Exception in thread "main" java.lang.NoSuchMethodError: actionProc
at org.eclipse.swt.internal.Callback.bind(Native Method)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at org.eclipse.swt.internal.Callback.<init>(Unknown Source)
at CocoaUIEnhancer.initialize(CocoaUIEnhancer.java:124)
at CocoaUIEnhancer.hookApplicationMenu(CocoaUIEnhancer.java:92)
at Test.initUI(Test.java:50)
at Test.<init>(Test.java:18)
这可能是本地库中的一个错误,但我无法弄清楚!
看起来像这样 actionProc
int actionProc( int id, int sel, int arg0 )
in CocoaUIEnhancer
可能需要使用 long
而不是 int
来使参数与 64 位 SWT 一起工作。
您需要修改 CocoaUIEnhancer.java,使其与 this tutorial 中所述的纯 SWT 应用程序一起工作:
- Modify the getProductName() method to return a String when no product is found (instead of null)
- Wrap the code in hookWorkbenchListener() in a try-catch (IllegalStateException e) block
- Wrap the code in modifyShells() in a try-catch (IllegalStateException e) block
- Add some code to the actionProc(...) method, to bring up an About-Dialog and Preferences-Dialog (since we aren’t using commands):
static long actionProc(long id, long sel, long arg0) throws Exception {
// ...
else if (sel == sel_preferencesMenuItemSelected_) {
showPreferences();
} else if (sel == sel_aboutMenuItemSelected_) {
showAbout();
}
return 0;
}
private static void showAbout() {
MessageDialog.openInformation(null, "About...",
"Replace with a proper about text / dialog");
}
private static void showPreferences() {
System.out.println("Preferences...");
PreferenceManager manager = new PreferenceManager();
PreferenceDialog dialog = new PreferenceDialog(null, manager);
dialog.open();
}
// ...
Finally, we add the following lines to our main() method:
public static final String APP_NAME = "MyApp";
public static void main(String[] args) {
//in your case change the Test constructor
Display.setAppName(APP_NAME);
Display display = Display.getDefault();
//insert in initUI method call the earlysetup
if (SWT.getPlatform().equals("cocoa")) {
new CocoaUIEnhancer().earlyStartup();
}
Shell shell = new Shell(display);
shell.setText(APP_NAME);
...
}
引用代码。
我根本没有使用 CocoaUIEnhancer
,因为它也引起了问题。
所以这就是我最终在我的应用程序中所做的事情:
/**
* Convenience method that takes care of special menu items (About, Preferences, Quit)
*
* @param name The name of the menu item
* @param parent The parent {@link Menu}
* @param listener The {@link Listener} to add to the item
* @param id The <code>SWT.ID_*</code> id
*/
private void addMenuItem(String name, Menu parent, Listener listener, int id)
{
if (OSUtils.isMac())
{
Menu systemMenu = Display.getDefault().getSystemMenu();
for (MenuItem systemItem : systemMenu.getItems())
{
if (systemItem.getID() == id)
{
systemItem.addListener(SWT.Selection, listener);
return;
}
}
}
/* We get here if we're not running on a Mac, or if we're running on a Mac, but the menu item with the given id hasn't been found */
MenuItem item = new MenuItem(parent, SWT.NONE);
item.setText(name);
item.addListener(SWT.Selection, listener);
}
分别用SWT.ID_PREFERENCES
、SWT.ID_ABOUT
、SWT.ID_QUIT
调用即可。提交后备菜单项名称、后备 Menu
和您要添加到菜单项的实际 Listener
。
例如:
addMenuItem("Quit", myMenu, new Listener()
{
@Override
public void handleEvent(Event event)
{
// Close database connection for example
}
}, SWT.ID_QUIT);
Baz 的解决方案非常有效!如果您不想导入 OSUtils 只是为了测试您是否在 Mac 上,请改用:
System.getProperty("os.name").contentEquals("Mac OS X")