作为继承这个帖子我运行到一个无限循环,导致我的电脑死机。或者,不是很好:它似乎导致Java窗口(JFrame)不断获得焦点/获得图标化和无限地规范化。因此, 请勿尝试按原样运行代码 。该程序不允许您关闭它,也不能通过任务管理器关闭它。
我已经给出了一个完整的代码示例,您可以运行它- 正如通常所建议的那样。由于它是实际程序的简化版本,因此某些代码似乎是多余的(尤其是中间的方法)。重要的方法是:最顶层的(构造函数)和最后两个。我猜构造器和/或refresh方法出了问题。
refresh
正如托马斯指出,在这里,我把所有的代码在构造函数中的一个Runnable块,但我想我做错了那里。
重要的是,在实际程序中,此类没有main方法,但是我从另一个Class调用了Class,如下所示:
if(getInstance() == null) { initOverview(0); }
设置最后两个窗口侦听器,以便在用户重新打开窗口时更新其内容。
我一直在研究文档,但是我不知道我的错误在哪里。我使用Runnable示例错误吗?还是由于窗口侦听器和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(); } }
我不确定您为什么同时调用这两种方法
getInstance().setExtendedState(JFrame.ICONIFIED); getInstance().setExtendedState(JFrame.NORMAL);
但是如果您删除第一个,即简单地:
getInstance().setExtendedState(JFrame.NORMAL);
那么它只打开一次窗口,没有您描述的无限循环。
您的代码导致无限循环的原因是,它使框架最小化然后再最小化,这导致windowActivated方法运行:这调用refresh方法,后者又调用bringToFront方法,使框架最小化和最小化等。
windowActivated
bringToFront
实际将窗口置于最前面,基于这个问题,以下内容对我有用:
private static void bringToFront() { getInstance().setVisible(true); getInstance().setExtendedState(JFrame.NORMAL); getInstance().toFront(); getInstance().repaint(); }