2015-09-05 13 views
6

Tôi đang sử dụng phiên bản SWT hiện tại để xây dựng các ứng dụng của mình và tôi muốn chạy nó dưới Mac OS X (Yosemite).
Vấn đề của tôi hiện tại là tôi không thể chụp được các nhấp chuột vào các mục menu "Giới thiệu", "Tùy chọn" và "Thoát" được tự động thêm vào ứng dụng của tôi.
Tôi đã tìm kiếm rất nhiều và tìm thấy lớp học sau có vẻ rất hữu ích đối với tôi http://www.transparentech.com/files/CocoaUIEnhancer.java.Chụp, tùy chọn và thoát các mục menu

Và đó là mã của tôi để khởi tạo nó:

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) { 
    } 
    } 
} 

tôi có thể biên dịch nó mà không có bất kỳ lỗi nào nhưng nếu tôi bắt đầu chương trình sau đó tôi sẽ nhận được ngoại lệ sau đây:

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) 

Đây có thể là một lỗi trong các thư viện gốc nhưng tôi không thể tìm ra!

Trả lời

8

Tôi đã không sử dụng CocoaUIEnhancer chút nào vì nó cũng gây ra sự cố.

Vì vậy, đây là những gì tôi đã kết thúc làm trong các ứng dụng của tôi:

/** 
* 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); 
} 

Chỉ cần gọi nó với SWT.ID_PREFERENCES, SWT.ID_ABOUTSWT.ID_QUIT tương ứng. Tay trong tên mục menu dự phòng, dự phòng Menu và số thực tế Listener bạn muốn thêm vào mục menu.

Vì vậy, ví dụ:

addMenuItem("Quit", myMenu, new Listener() 
{ 
    @Override 
    public void handleEvent(Event event) 
    { 
     // Close database connection for example 
    } 
}, SWT.ID_QUIT); 
+0

Một giải pháp hoàn hảo - đơn giản và dễ hiểu! Các mục menu cũng có thể được đổi tên. Nhưng những gì về mục "SWT"? Làm thế nào để thay đổi văn bản của nó? Display.setAppName không hoạt động đối với tôi do một số lý do không xác định. Có cách nào khác để làm điều đó không? –

+0

Sai lầm của tôi. Display.setAppName() hoạt động tốt. Tôi chỉ không nên làm bất cứ điều gì với màn hình trước khi tôi gọi setAppName(). Nó phải là dòng đầu tiên trong mã của tôi. –

+0

@ m.vokhm Yeah, tôi vừa mới đăng bài đó. Vui mừng nó làm việc cho bạn bây giờ. – Baz

2

Nó trông như thế này các actionProc

int actionProc(int id, int sel, int arg0) 

trong CocoaUIEnhancer lẽ nhu cầu sử dụng long hơn int cho các đối số để làm việc với 64 bit SWT.

+0

Đó là một ý tưởng tốt nhưng tiếc là nó không giúp đỡ. Tôi đã thay đổi các tham số id, sel, arg0 từ int thành long nhưng ngoại lệ vẫn như cũ và stacktrace cũng giống nhau. – altralaser

2

Bạn cần phải sửa đổi CocoaUIEnhancer.java, để làm cho nó làm việc với các ứng dụng SWT tinh khiết như mô tả trong this tutorial:

  • Sửa đổi phương pháp getProductName() để trả về một String khi không có sản phẩm được tìm thấy (thay vì null)
  • Bó mã trong hookWorkbenchListener() trong một try-catch (IllegalStateException e) chặn
  • Bó mã trong modifyShells() trong một try-catch (IllegalStateException e) chặn
  • Thêm một số mã để các phương pháp actionProc (...), để đưa lên một Về-Dialog và Preferences-Dialog (vì chúng ta không sử dụng lệnh):
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(); 
    } 


    // ... 

Cuối cùng, chúng ta thêm dòng sau vào phương pháp main() của chúng tôi:

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

đang trích dẫn.

Các vấn đề liên quan