【问题标题】:Infinite disappear-reappear loop in JFrame javaJFrame java中的无限消失-重新出现循环
【发布时间】:2016-01-06 11:36:32
【问题描述】:

作为this post 的后续,我遇到了一个无限循环,导致我的计算机崩溃。或者,不完全是:它似乎导致 Java 窗口 (JFrame) 不断获得焦点/图标化和无限标准化。因此不要尝试按原样运行代码。该程序不允许您关闭它,您也不能通过任务管理器这样做。

我已经给出了一个完整的代码示例,您可以按照通常的建议运行它。由于它是实际程序的精简版本,因此某些代码可能看起来是多余的(尤其是中间的方法)。重要的方法是:最顶层(构造函数)和最后两个。我猜构造函数和/或 refresh 方法出了点问题。

正如 Thomas 指出的 here,我将构造函数中的所有代码都放在了一个 Runnable 块中,但我想我在那里做错了。

重要的是,在实际程序中,这个类没有main方法,但我从另一个类中调用该类,如下所示:

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();
    }
}

【问题讨论】:

    标签: java swing infinite-loop windowlistener


    【解决方案1】:

    我不完全确定你为什么同时调用这两个

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

    但如果你删除第一个,即简单地说:

        getInstance().setExtendedState(JFrame.NORMAL);
    

    然后它只打开一次窗口,没有你描述的无限循环。

    您的代码导致无限循环的原因是它最小化然后取消最小化帧,这导致 windowActivated 方法正在运行:这会调用 refresh 方法,该方法会调用 bringToFront 方法,从而最小化并最小化框架等。


    要真正将窗口放在前面,以下对我有用,基于this question

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

    【讨论】:

    • 嗯,我以为我在某处看到过这个,但我似乎找不到在哪里。不过,你知道为什么会这样吗?
    • 编辑解释了为什么会发生无限循环。
    • 我现在明白为什么了。通过首先图标化然后规范化,您可以确保窗口在前面打开并处于活动状态。现在,通过您的调整,窗口处于活动状态(它在任务栏中“闪烁”),但它不在前面。如果这个功能可以保留,那就太好了。
    • 我尝试了票数最高的答案和您的答案,但it doesn't seem to work for me。哦,好吧,如果我想不通,我会再发一个帖子。我想知道,您使用的是什么版本的 Windows 和/或 Java?
    • @AndyTurner 我刚刚看到你的原始评论。哈哈。
    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 2012-01-24
    • 1970-01-01
    相关资源
    最近更新 更多