启动应用时,使用缩放桌面在Mac上挂起。与Swing& SWT

时间:2013-06-18 15:20:12

标签: java macos swing swt swt-awt

我在Mac上(用10.6.4,10.7.5和10.8.2进行测试)我的桌面放大了。在午餐我的Java应用程序同时使用Swing和SWT时,窗口正在开启时冻结。使用SWT网页上提供的代码段337(此处为link)也可以重现此问题。

package org.eclipse.swt.snippets;

/*
 * SWT_AWT example snippet: launch SWT from AWT and keep both active
 * 
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 */

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;

public class Snippet337 {

public static void main(String args[]) {
    final Display display = new Display();

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            JFrame mainFrame = new JFrame("Main Window");
            mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel mainPanel = new JPanel();
            mainPanel.setLayout(new FlowLayout());
            JButton launchBrowserButton = new JButton("Launch Browser");
            launchBrowserButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    JFrame childFrame = new JFrame();
                    final Canvas canvas = new Canvas();
                    childFrame.setSize(850, 650);
                    childFrame.getContentPane().add(canvas);
                    childFrame.setVisible(true);
                    display.asyncExec(new Runnable() {
                        public void run() {
                            Shell shell = SWT_AWT.new_Shell(display, canvas);
                            shell.setSize(800, 600);
                            Browser browser = new Browser(shell, SWT.NONE);
                            browser.setLayoutData(new GridData(GridData.FILL_BOTH));
                            browser.setSize(800, 600);
                            browser.setUrl("http://www.eclipse.org");
                            shell.open();
                        }
                    });
                }
            });

            mainPanel.add(new JTextField("a JTextField"));
            mainPanel.add(launchBrowserButton);
            mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
            mainFrame.pack();
            mainFrame.setVisible(true);
        }
    });
    display.addListener(SWT.Close, new Listener() {
        public void handleEvent(Event event) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    Frame[] frames = JFrame.getFrames();
                    for (int i = 0; i < frames.length; i++) {
                        frames[i].dispose();
                    }
                }
            });
        }
    });
    while (!display.isDisposed()) {
        if (!display.readAndDispatch()) display.sleep();
    }
}

}

如果桌面没有缩放,应用程序就可以正常运行,没有问题。

阻塞事件派发线程的堆栈如下所示:

CWindow._setVisible(long, boolean, boolean, int, boolean, int, int, boolean) line: not available [native method]    
CFrame.setVisible(boolean) line: 111    
CFrame(CComponent).show() line: 219 
JFrame(Component).show() line: 1530 
JFrame(Window).show() line: 871 
JFrame(Component).show(boolean) line: 1563  
JFrame(Component).setVisible(boolean) line: 1515    
JFrame(Window).setVisible(boolean) line: 841

有没有人知道如何解决这个问题?感谢。

编辑 - 替代方法1

如果我将setVisible包含在asyncExec中并且不使用SWT_AWT shell而是使用这样的普通shell:

....
display.asyncExec(new Runnable() {
   @Override
   public void run() {
      mainFrame.pack();
      mainFrame.setVisible(true);
   });
....
launchBrowserButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
      display.asyncExec(new Runnable() {
         public void run() {
            Shell shell = new Shell(display);
            shell.setSize(800, 600);
            Browser browser = new Browser(shell, SWT.NONE);
            ...
         }
      });
   }
});

它似乎适用于这个简单的例子,但在我的应用程序中仍然挂起在EDQ中调度的某个事件,因此不是解决方案....

替代方法2

如果我将EventQueue替换为在Thread0中调度事件,它也适用于小例子,它也成功地盯着我的复杂应用程序,但后来还有一些其他随机错误来自此队列替换

...
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
eventQueue.push(new MyEDQ());
...
class MyEQD extends EventQueue {
   @Override
   protected void dispatchEvent( AWTEvent arg0) {
      final AWTEvent event = arg0;
      A.display.asyncExec(new Runnable() {
         @Override
         public void run() {
            MyEQD.super.dispatchEvent(event);           }
         });
      }
   }
}
...

所以还有人对如何更优雅地解决Thread0和EventDispatchThread之间的同步问题有任何想法,所以我不会遇到其他问题吗?

0 个答案:

没有答案