JFrame 中的无限消失-重新出现循环 java
Infinite disappear-reappear loop in JFrame java
作为 的继承,我 运行 进入了一个导致我的计算机崩溃的无限循环。或者,嗯,不完全是:它似乎导致 Java window (JFrame) 不断地 focus/getting 图标化和规范化。因此,不要尝试 运行 代码原样 。该程序不允许您关闭它,您也不能通过任务管理器关闭它。
我已经给出了一个完整的代码示例,您可以 运行 - 正如通常建议的那样。由于它是实际程序的精简版,一些代码可能看起来是多余的(尤其是中间的方法)。重要的方法是:最顶层的(构造函数)和最后两个。我猜构造函数 and/or refresh
方法出了问题。
正如 Thomas 所指出的 ,我将构造函数中的所有代码都放在一个 Runnable 块中,但我想我在那里做错了。
重要的是,在实际程序中,这个 class 没有 main 方法,但我从另一个 Class 调用 Class,像这样:
if(getInstance() == null) {
initOverview(0);
}
设置最后两个 window 侦听器,以便在用户重新打开 window 时更新其内容。
我一直在调查 the documentation,但我无法弄清楚我的错误在哪里。我是否使用了 Runnable 示例错误?还是因为WindowListener和setExtendedState(保证window的"opening")互相触发?如果是这样,我该如何解决?
另一个警告:不要执行此代码,它会使您的计算机崩溃
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);
然后它只打开 window 一次,没有你描述的无限循环。
您的代码导致无限循环的原因是它最小化然后取消最小化帧,这导致 windowActivated
方法为 运行:这会调用 refresh
方法,它调用 bringToFront
方法,该方法最小化和取消最小化框架等
为了真正将 window 置于最前面,以下对我有用,基于 this question:
private static void bringToFront() {
getInstance().setVisible(true);
getInstance().setExtendedState(JFrame.NORMAL);
getInstance().toFront();
getInstance().repaint();
}
作为
我已经给出了一个完整的代码示例,您可以 运行 - 正如通常建议的那样。由于它是实际程序的精简版,一些代码可能看起来是多余的(尤其是中间的方法)。重要的方法是:最顶层的(构造函数)和最后两个。我猜构造函数 and/or refresh
方法出了问题。
正如 Thomas 所指出的
重要的是,在实际程序中,这个 class 没有 main 方法,但我从另一个 Class 调用 Class,像这样:
if(getInstance() == null) {
initOverview(0);
}
设置最后两个 window 侦听器,以便在用户重新打开 window 时更新其内容。
我一直在调查 the documentation,但我无法弄清楚我的错误在哪里。我是否使用了 Runnable 示例错误?还是因为WindowListener和setExtendedState(保证window的"opening")互相触发?如果是这样,我该如何解决?
另一个警告:不要执行此代码,它会使您的计算机崩溃
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);
然后它只打开 window 一次,没有你描述的无限循环。
您的代码导致无限循环的原因是它最小化然后取消最小化帧,这导致 windowActivated
方法为 运行:这会调用 refresh
方法,它调用 bringToFront
方法,该方法最小化和取消最小化框架等
为了真正将 window 置于最前面,以下对我有用,基于 this question:
private static void bringToFront() {
getInstance().setVisible(true);
getInstance().setExtendedState(JFrame.NORMAL);
getInstance().toFront();
getInstance().repaint();
}