JFrame Java中的无限消失-重新出现循环 [英] Infinite disappear-reappear loop in JFrame java

查看:164
本文介绍了JFrame Java中的无限消失-重新出现循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为对

As a succession to this post I'm running into an infinite loop that causes my computer to crash. Or, well, not quite: it seems to cause the Java window (JFrame) to keep getting focus/getting iconified and normalized infinitely. As such do not try to run the code as is. The program won't allow you to shut it down, nor can you do so via task manager.

我已经给出了一个完整的代码示例,您可以运行该程序-通常建议这样做.由于它是实际程序的简化版本,因此某些代码似乎是多余的(尤其是中间的方法).重要的方法是:最顶层的(构造函数)和最后两个.我猜测构造函数和/或refresh方法出了问题.

I have given a complete code example, that you can run - as is often advised. As it's a stripped-down version of an actual program, some code may seem redundant (especially the methods in the middle). The methods that are of importance are: the topmost (the constructor), and the two last ones. I'm guessing something is going wrong with the constructor and/or the refresh method.

正如Thomas指出的那样

As Thomas pointed out here, I put all the code in the constructor in a Runnable block, but I guess I did something wrong there.

重要的是,在实际程序中,此类没有main方法,但是我从另一个Class调用了Class,就像这样:

Of importance is that in the real program, this class doesn't have a main method but I call the Class from another Class, like so:

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

设置最后两个窗口侦听器,以便在用户重新打开窗口时更新其内容.

The two last window listeners are set so that when a user re-opens the window, its contents are updated.

我一直在研究文档,但我不知道我的错误在哪里.我使用Runnable示例错误吗?还是由于窗口侦听器和setExtendedState(以确保窗口的打开")相互触发?如果是这样,我该如何解决?

I've been looking into the documentation, but I can't figure out where my error is. Am I using the Runnable example wrong? Or is it because of the Window Listener and the setExtendedState (to ensure the "opening" of the window) that trigger each other? If so, how could I solve this?

另一个警告:请勿执行此代码,否则将使您的计算机掉线

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

推荐答案

我不确定为什么要同时调用这两者

I'm not entirely sure why you are invoking both

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

但是如果您删除第一个,即简单地:

but if you remove the first, i.e. simply:

    getInstance().setExtendedState(JFrame.NORMAL);

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

then it just opens the window once, without the infinite looping you describe.

您的代码导致无限循环的原因是它使帧最小化,然后使帧最小化,从而导致运行windowActivated方法:这调用了refresh方法,该方法又调用了bringToFront方法,该方法最小化了并最小化框架等.

The reason your code causes an infinite loop is that it minimizes and then unminimizes the frame, which results in the windowActivated method being run: this invokes the refresh method, which invokes the bringToFront method, which minimizes and unminimizes the frame etc.

要真正将窗口置于最前面,以下内容根据

To actually bring the window to the front, the following works for me, based upon this question:

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

这篇关于JFrame Java中的无限消失-重新出现循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆