2014-08-28 80 views
0

我在處理多個框架時隱藏組件未正確放置時出現問題。當框架不可見時,Java不處理對話框

總之,我不能處置一個父母是隱藏框架的模式對話框。

例如:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import java.util.*; 

public class MultipleFrameTest { 
    public static void main(String[] args) { 
     TestFrame test = new TestFrame(); 
     FrameTester tester = new FrameTester(test); 

     tester.setVisible(true); 
    } 

    private static class TestFrame extends JFrame { 
     JDialog dialog; 
     java.util.Timer timer; 

     public TestFrame() { 
      super("Test Frame"); 

      this.dialog = null; 
      this.timer = new java.util.Timer("Frame Timer"); 

      fillFrame(); 
      pack(); 
     } 

     private void fillFrame() { 
      JButton dialogButton = new JButton("Launch Model Dialog"); 
      dialogButton.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        JOptionPane pane = new JOptionPane("Wait for 2 seconds", 
         JOptionPane.QUESTION_MESSAGE, 
         JOptionPane.OK_CANCEL_OPTION); 
        dialog = pane.createDialog(TestFrame.this, "Question"); 

        timer.schedule(new TimerTask() { 
         public void run() { 
          SwingUtilities.invokeLater(new Runnable() { 
           public void run() { 
            TestFrame.this.setVisible(false); 

            if (dialog != null) { 
             dialog.setVisible(false); 
             dialog.dispose(); 
             dialog = null; 
            } 
           } 
          }); 
         } 
        }, 2 * 1000); 

        dialog.setVisible(true); 
       } 
      }); 

      JPanel panel = new JPanel(); 
      panel.add(dialogButton); 

      add(panel); 
     } 
    }  

    private static class FrameTester extends JFrame { 
     JFrame frame; 

     public FrameTester(JFrame frame) { 
      super("Frame Tester"); 

      this.frame = frame; 

      fillFrame(); 
      pack(); 
     } 

     private void fillFrame() { 
      JButton toggleButton = new JButton("Toggle Frame Visibility"); 
      toggleButton.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent event) { 
        frame.setVisible(!frame.isVisible()); 
       } 
      }); 

      JPanel panel = new JPanel(); 
      panel.add(toggleButton); 

      add(panel); 
     } 
    } 
} 

要運行這個例子:

  1. 點擊 「切換幀可見性」 按鈕。這將顯示TestFrame
  2. 點擊「Launch Modal Dialog」按鈕。這會彈出一個JOptionPane
  3. 等待2秒鐘,TimerTask隱藏TestFramedispose()JOptionPane
  4. 單擊「切換框架可視性按鈕」。 TestFrame將變爲可見,並且將看到JOptionPane被附加。

我知道我可以通過配置JOptionPane隱藏TestFrame之前解決這個問題:

- TestFrame.this.setVisible(false); 

    if (dialog != null) { 
    dialog.setVisible(false); 
    dialog.dispose(); 
    dialog = null; 
    } 

+ TestFrame.this.setVisible(false); 

有誰知道爲什麼發生這種情況?我期望模態對話框即使在處置時處於隱藏狀態也不會消失。

+3

另請參見[*使用多個JFrames,好/壞實踐?*](http://stackoverflow.com/q/9554636/230513)。 – trashgod 2014-08-28 21:35:10

回答

3

雖然你應該真的考慮垃圾評論The Use of Multiple JFrames, Good/Bad Practice?,下面是你爲什麼看到這種行爲的解釋。

發生這種情況是因爲您在對話框之前隱藏了擁有窗口。當做這樣的事情時,擁有的對話框被標記爲showWithParent,並且幀上的下一個setVisible(true)調用將自動觸發顯示擁有的對話框,因爲該標誌。正如您在問題中所述,避免這種情況的唯一方法是首先隱藏擁有的對話框,然後隱藏擁有的窗口。

這裏是Window.hide()方法的提取物:

synchronized(ownedWindowList) { 
     for (int i = 0; i < ownedWindowList.size(); i++) { 
      Window child = ownedWindowList.elementAt(i).get(); 
      if ((child != null) && child.visible) { 
       child.hide(); 
       child.showWithParent = true; // See here the flag set to true 
      } 
     } 
    } 

和這裏的Window.show()方法的相應的提取物:

 for (int i = 0; i < ownedWindowList.size(); i++) { 
      Window child = ownedWindowList.elementAt(i).get(); 
      if ((child != null) && child.showWithParent) { // Here theh flag is checked 
       child.show(); 
       child.showWithParent = false; // flag is then reset 
      }  // endif 
     } 

順便說一句,而不是使用這種複雜的定時器/ TimerTask的/ invokeLater的結構,你可以使用javax.swing.Timer(與setRepeats(false))。 Swing定時器始終在事件分派線程上運行。

+0

感謝您的信息! – 2014-08-29 15:52:00