2016-01-06 16 views
0

作爲this post的繼承,我遇到了導致我的計算機崩潰的無限循環。或者,並非如此:它似乎會導致Java窗口(JFrame)不斷聚焦/無限化地進行圖標化和標準化。因此不要嘗試像那樣運行代碼。該程序不會讓你關閉它,你也不能通過任務管理器來關閉它。JFrame中的無限消失 - 再現循環java

我已經給出了一個完整的代碼示例,您可以運行 - 正如通常所建議的那樣。由於它是實際程序的簡化版本,因此某些代碼可能看起來多餘(特別是中間的方法)。重要的方法是:最頂層(構造函數)和最後兩個。我猜測構造函數和/或方法有問題。

正如托馬斯指出的here,我把所有代碼放在構造函數的Runnable塊中,但我想我在那裏做了錯誤。

重要的是,在實際的程序,這個類沒有一個主要方法,但我調用類從另一個類,像這樣:

if(getInstance() == null) { 
    initOverview(0); 
} 

最後兩個窗口偵聽器被設置成使當用戶重新打開該窗口時,其內容被更新。

我一直在調查the documentation,但我無法弄清楚我的錯誤在哪裏。我是否使用Runnable示例錯誤?或者是因爲Window Listener和setExtendedState(以確保窗口的「打開」)相互觸發?如果是這樣,我怎麼解決這個問題?

另一個警告:不要執行這個代碼,它會讓你的電腦翻出

import javax.swing.*; 
import java.awt.Color; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.lang.reflect.InvocationTargetException; 
import java.awt.BorderLayout; 
import java.awt.GridLayout; 

public class OverviewTest extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private static OverviewTest instance = null; 

    private static JLabel labelTextOverview; 
    private static JTabbedPane tabbedPane; 
    private static JPanel mapPane; 

    private OverviewTest() { 
     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       public void run() { 
        setTitle("Game - Overview"); 
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
        setResizable(true); 
        setBounds(100, 100, 960, 720); 

        JPanel contentPane = new JPanel(); 
        setContentPane(contentPane); 
        contentPane.setLayout(new BorderLayout(0, 0)); 

        tabbedPane = new JTabbedPane(JTabbedPane.TOP); 

        contentPane.add(tabbedPane); 

        /* TAB 1: Entity Overview */ 
        labelTextOverview = new JLabel(); 
        labelTextOverview.setText(entityOverviewHTML()); 

        JScrollPane scrollPaneEntityOverview = new JScrollPane(labelTextOverview); 

        tabbedPane.addTab("Entity overview", null, scrollPaneEntityOverview, null); 

        /* TAB 2: Map */ 
        mapPane = new JPanel(); 
        mapPane.setLayout(new GridLayout(6, 6, 2, 2)); 
        fillMap(); 

        tabbedPane.addTab("Map", null, mapPane, null); 

        /* TAB 3: Rules */ 
        JLabel labelRules = new JLabel(); 
        labelRules.setText(rulesHTML()); 

        JScrollPane scrollPaneRules = new JScrollPane(labelRules); 

        tabbedPane.addTab("Rules", null, scrollPaneRules, null); 

        // Immediately show window on creation 
        setVisible(true); 
        setExtendedState(JFrame.ICONIFIED); 
        setExtendedState(JFrame.NORMAL); 

        // Add window listener so that contents get refreshed on window active/focus 
        addWindowListener(new WindowAdapter() { 
         @Override 
         public void windowClosing(WindowEvent e) { 
          setVisible(false); 
         } 
         @Override 
         public void windowActivated(WindowEvent e){ 
          refresh(tabbedPane.getSelectedIndex()); 
         } 
         @Override 
         public void windowDeiconified(WindowEvent e){ 
          refresh(tabbedPane.getSelectedIndex()); 
         } 
        }); 
       } 
      }); 
     } catch (InvocationTargetException | InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    public static void main(String[] args) { 
     if(getInstance() == null) { 
      initOverview(0); 
     } 
    } 
    private String rulesHTML() { 
     StringBuilder sbRules = new StringBuilder(); 

     sbRules.append("<html><body style='padding: 12px;'>"); 

     sbRules.append("<h2>Some text for Rules</h2>"); 
     sbRules.append("<h3>Lorem ipsum</h3>"); 

     sbRules.append("</body></html>"); 

     return sbRules.toString(); 
    } 

    private static void fillMap() { 
     mapPane.removeAll(); 
     for (int i = 0; i < 36; i++) { 
      JLabel textTile = new JLabel(fillTile(i)); 
      JScrollPane tile = new JScrollPane(textTile); 

      tile.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
      mapPane.add(tile); 
     } 
    } 
    private static String fillTile(int i) { 
     StringBuilder sbTile = new StringBuilder(); 

     sbTile.append("<html>"); 
     sbTile.append("some text"); 
     sbTile.append("</html>"); 

     return sbTile.toString(); 
    } 

    /** 
    * Reset UI components to system default 
    */ 
    public static void initOverview(int index) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } 
     catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { 
      System.err.println(e); 
     } 
     instance = new OverviewTest(); 
     tabbedPane.setSelectedIndex(index); 
    } 

    public static OverviewTest getInstance() { 
     return instance; 
    } 

    private static String entityOverviewHTML() { 
     StringBuilder sb = new StringBuilder(); 

     sb.append("<html><body style='padding: 12px;'>"); 

     sb.append("<h2>Some text for Rules</h2>"); 
     sb.append("<h3>Lorem ipsum</h3>"); 

     // Normally a loop that runs over getEntityInfo(); 
     sb.append(getEntityInfo()); 
     sb.append("</body></html>"); 

     return sb.toString(); 
    } 

    private static StringBuilder getEntityInfo() { 
     StringBuilder sbInfo = new StringBuilder(); 

     sbInfo.append("this is not a drill, but a test");   

     return sbInfo; 
    } 

    private static void bringToFront() { 
     getInstance().setVisible(true); 
     getInstance().setExtendedState(JFrame.ICONIFIED); 
     getInstance().setExtendedState(JFrame.NORMAL); 
    } 

    public static void refresh(int index) { 
     labelTextOverview.setText(entityOverviewHTML()); 
     fillMap(); 
     tabbedPane.setSelectedIndex(index); 
     getInstance().repaint(); 
     bringToFront(); 
    } 
} 

回答

2

我不完全知道爲什麼要調用兩個

getInstance().setExtendedState(JFrame.ICONIFIED); 
    getInstance().setExtendedState(JFrame.NORMAL); 

,但如果你刪除第一個,即簡單:

getInstance().setExtendedState(JFrame.NORMAL); 

然後它只是打開一次窗口,沒有你描述的無限循環。

您的代碼會導致無限循環的原因是,它最大限度地減少,然後unminimizes幀,這導致在windowActivated方法正在運行:這個調用refresh方法,該方法調用bringToFront方法,其最小化和unminimizes框架等。


要真正實現窗口前,下面的工作對我來說,基於this question

private static void bringToFront() {                
    getInstance().setVisible(true);                
    getInstance().setExtendedState(JFrame.NORMAL);            
    getInstance().toFront();                  
    getInstance().repaint();                  
} 
+0

嗯,我想我看到了這對SO某處,但我似乎無法找到位置。你知道爲什麼會發生這種情況嗎? –

+0

編輯來解釋爲什麼發生無限循環。 –

+0

我現在明白爲什麼。首先進行圖標化,然後正常化,確保窗口在前面處於打開狀態並處於活動狀態。現在,在你的調整中,窗口是激活的(它在任務欄中閃爍),但它不在前面。如果這個功能可以保留,這將是很好的。 –