1

次のシナリオがあります。1。ActionListenerを実装する「FrontEnd.java」クラスにJFramejFrame作成します。次に、Canvas3DオブジェクトをそのContentPaneに追加し、その直後に、いくつかのJMenuといくつかのJMenuItemをそれぞれ含むJMenuBarを追加します。2.次に、球をCanvas3Dオブジェクトにレンダリングするために使用するRendererClass.javaクラスがあります。したがって、フロントエンドから、 JMenuItemの1つをクリックして、イベントを処理し、actionPerformedから実行します。(ActionEvent ae)メソッドRendererClass(jFrame)を呼び出し、レンダラー側からjFrameオブジェクトを取得するため、Canvas3Dで球をペイントします。だから、私はそれらを初期の位置にペイントします。3.次に、 RendererClassにある「updateCoordinates()」を呼び出すFrontEndにあるループで球の座標を更新します。これは、最大1分間続く可能性のある重いループです。球の座標を更新している間、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を1つのクラスで作成し、それを他のクラスに渡して、Canvas3D内に配置できるようにします...ループ中に対話できるようにします) Canvas3D?

前もって感謝します。

4

1 に答える 1

2

UIまたはイベントディスパッチスレッドJFrameで重い処理タスクを実行していると、ウィンドウはイベントへの応答を停止します。

解決策は、このリソースを大量に消費するタスクを独自のスレッドで実行することです。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 に答える