2012-09-20 2 views
1

Je le scénario suivant: 1. Je créat un JFrame Jframe dans une classe « FrontEnd.java » la mise en œuvre ActionListener. Puis-je ajouter une Canvas3D objet à son ContentPane, et juste après, j'ajoute un JMenuBar avec quelques JMenus et un couple JMenuItems chacun. 2. Puis j'ai une classe RendererClass.java que j'utilise pour rendre des sphères dans l'objet Canvas3D. Donc, depuis FrontEnd, en cliquant sur l'un des JMenuItems, je gère l'événement et depuis la méthode actionPerformed (ActionEvent ae) j'appelle RendererClass (jFrame) et j'obtiens l'objet jFrame du côté du Renderer, et donc le Canvas3D à peindre des sphères en elle. Donc, je les peins dans leurs positions initiales. 3. Ensuite, je mets à jour les coordonnées des sphères dans une boucle placée dans FrontEnd, qui appelle "updateCoordinates()" qui se trouve dans RendererClass. C'est une boucle lourde qui peut durer jusqu'à une minute. Lors de la mise à jour des coordonnées de la sphère, je montre comment elles sont mises à jour dans le Canvas3D (à chaque itération, les coordonnées ne varient que légèrement) - ceci est fait par updateCoordinates() dans RendererClass. Le problème est, alors que dans la boucle, qui a été appelé à partir de la méthode actionPerformed (...), je ne peux pas interagir avec le jFrame, pas l'événement le ferme. C'est en fait l'écoute, parce que quand la boucle se termine, si je clique alors que dans la boucle sur "X" (Fermer la fenêtre), alors la fenêtre se ferme. De plus, si j'ai essayé de faire pivoter mon appareil photo sur le Canvas3D, il ne mettra pas à jour la rotation jusqu'à ce que la boucle soit terminée. Remarquez que dans la boucle, je vois mes sphères bouger. En outre, les boutons cessent de répondre et ne répondent plus - les menus déroulants JMenuItems semblent se placer sous Canvas3D et deviennent inaccessibles.JFrame ne répond pas à des événements lors de la manipulation d'un autre événement

Voici le code:

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 
} 

Ainsi, la question est simple ... Pourquoi la fenêtre JFrame bloqué et ne répond plus aux événements? Et pourquoi, après la fin de la boucle, les événements passés sont-ils soudainement gérés? Et enfin, comment implémenteriez-vous une telle fonctionnalité (avoir un JFrame créé dans une classe, et le passer à un autre classeur pour qu'il puisse mettre les choses dans un Canvas3D à l'intérieur ... de sorte que pendant la boucle, je puisse interagir avec le Canvas3D?

Merci à l'avance.

Répondre

2

la fenêtre JFrame cesse de répondre aux événements que vous exécutez la tâche de traitement lourd dans l'interface utilisateur ou Event Dispatch Thread.

la solution est de lancer cette ressource lourde tâche dans son propre fil. Dans Swing il y a une classe connue comme SwingWorker qui va gérer ce type de travail potentiellement chronophage.

Pour votre application ici, vous pouvez créer une très simple de mise en œuvre SwingWorker au niveau de la classe comme ceci:

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

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

et appelez:

worker.execute(); 

dans votre ActionListener à exécuter.

+0

Merci. Je vais vérifier ça ce soir! – Azurlake

Questions connexes