1

我有以下场景: 1. 我在实现ActionListener的“FrontEnd.java”类中创建了一个JFrame jFrame 。然后我将一个Canvas3D对象添加到它的ContentPane,然后,我添加一个JMenuBar ,每个 JMenuBar有几个JMenu和几个JMenuItems。2. 然后我有一个RendererClass.java类,用于将球体渲染到 Canvas3D 对象中。因此,从FrontEnd,单击其中一个 JMenuItems,我处理事件并从actionPerformed(ActionEvent ae) 方法我调用 RendererClass(jFrame) 并从渲染器端获取 jFrame 对象,因此 Canvas3D 在其中绘制球体。所以,我把它们画在它们的初始位置。3. 然后,我在 FrontEnd中的一个循环中更新球体的坐标,该循环调用 RendererClass 中的“updateCoordinates()”。这是一个可能持续长达一分钟的沉重循环。在更新球体的坐标时,我展示了它们是如何在 Canvas3D 中更新的(在每次迭代中,坐标仅略有不同)——这是由 RendererClass 中的 updateCoordinates() 完成的。

问题是,在从 actionPerformed(...) 方法调用的循环中,我无法与 jFrame 交互,而不是事件关闭它。它实际上是在听,因为当循环结束时,如果我在循环中单击“X”(关闭窗口),那么窗口就会关闭。此外,如果我尝试在 Canvas3D 上旋转我的相机,在循环完成之前它不会更新旋转。请注意,在循环中,我看到我的球体在移动。此外,按钮停止响应并且不再响应 - 下拉 JMenuItems 似乎位于 Canvas3D 下方并且无法访问。

这是代码:

public class FrontEnd implements ActionListener {

    /**
     * The main Window and menus
     */
    private static JFrame jFrame = null;
    private JMenuBar jMenuBar;
    private JMenu fileMenu;
    private JMenu editMenu;
    private JMenu aboutMenu;

    private JMenuItem openAction;
    private JMenuItem exitAction;
    private JMenuItem renderAction;
    private JMenuItem aboutAction;

    /**
     * The renderer
     */
    private RendererClass renderer = null;

    /**
     * Constructor
     *
     */
    public FrontEnd() {

        jFrame = new JFrame("The Main Window");
        jFrame.getContentPane().add(new     Canvas3D(SimpleUniverse.getPreferredConfiguration()));

        jFrame.setPreferredSize(new Dimension(800, 600));
        jFrame.setResizable(false);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        /**
         * Menus
         */
        jMenuBar = new JMenuBar();
        jFrame.setJMenuBar(jMenuBar);

        //Dropdown menus
        fileMenu = new JMenu("File");
        editMenu = new JMenu("Edit");
        aboutMenu = new JMenu("About");
        jMenuBar.add(fileMenu);
        jMenuBar.add(editMenu);
        jMenuBar.add(aboutMenu);

        //Create and add simple menu item to one of the drop down menu
        openAction = new JMenuItem("Open");
        openAction.setMnemonic('O');
        exitAction = new JMenuItem("Exit");
        exitAction.setMnemonic('x');
        renderAction = new JMenuItem("Render All");
        renderAction.setMnemonic('R');
        aboutAction = new JMenuItem("About");
        aboutAction.setMnemonic('A');

        fileMenu.add(openAction);
        fileMenu.add(exitAction);
        editMenu.add(renderAction);
        aboutMenu.add(aboutAction);

        //Event Listeners
        openAction.addActionListener(this);
        exitAction.addActionListener(this);
        renderAction.addActionListener(this);
        aboutAction.addActionListener(this);

        // Configure the JFrame
        jFrame.setResizable(false);

        jFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent winEvent) {
                System.exit(0);
            }
        });

        jFrame.setSize(820,620);
        jFrame.setVisible(true);
        jFrame.pack();

    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == renderAction) {
            doHeavyLoop();
        }
    }

    public void doHeavyLoop() {
        renderer = new RendererClass(jFrame);
        for (int i=0; i<100000; i++) {
            try {
                    Thread.sleep(1);
                } catch (InterruptedException ie) {
                    System.out.println("Baaad MF.");
                }
                    renderer.updateCoordinates();
            }
        }
    }
}


/**
 * The RenedererClass class
 */
public static JFrame jFrame;
public SimpleUniverse universe;
public BrachGroup branchGroup;
public static PickCanvas pickCanvas;    

public RendererClass(JFrame frame) {

    jFrame = frame;
    jFrame.update(jFrame.getGraphics());

    theCanvas = (Canvas3D) jFrame.getContentPane().getComponent(0);
    theCanvas.addMouseListener(this);
    //STUFF HERE... CREATE AND ADD SPHERES TO THE BRANCHGROUP
    // Add the brachgroup to the Universe.
    universe.addBranchGraph(branchGroup);

    //The following three lines enable navigation through the scene using the mouse.
    OrbitBehavior ob = new OrbitBehavior(theCanvas);
    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE));
    universe.getViewingPlatform().setViewPlatformBehavior(ob);

    //Now make it pickable for picking spheres
    pickCanvas = new PickCanvas(theCanvas, branchGroup);
    pickCanvas.setMode(PickCanvas.GEOMETRY);
    pickCanvas.setTolerance(0.0f);
}

public void updateCoordinates() {
    // Irrelevant... just set Translations transforms to the spheres
}

所以,问题很简单……为什么 JFrame 窗口会卡住并停止响应事件?而且,为什么在循环结束后,过去的事件都突然被处理了?最后但并非最不重要的一点是,您将如何实现这样的功能(在一个类中创建一个 JFrame,并将其传递给其他类,以便他们可以将内容放入其中的 Canvas3D ......这样在循环时,我可以与画布3D?

提前致谢。

4

1 回答 1

2

当您在 UI 或Event Dispatch ThreadJFrame中运行繁重的处理任务时,窗口会停止响应事件。

解决方案是在自己的线程中运行这个资源繁重的任务。在 Swing 中有一个称为SwingWorker的类,它将处理这种可能耗时的工作。

SwingWorker对于您的应用程序,您可以在类级别创建一个非常简单的实现,如下所示:

SwingWorker worker = new SwingWorker<Void, Void>() {

   @Override
   protected Void doInBackground() throws Exception {
      doHeavyLoop();
      return null;
   }
};

并致电:

worker.execute();

在你ActionListener执行。

于 2012-09-25T01:08:59.870 回答