【问题标题】:Swing application freezesSwing 应用程序冻结
【发布时间】:2016-02-10 12:56:26
【问题描述】:

我对 AWT/Swing 编程很陌生,所以我看不到问题所在。 当事件被调用时,窗口甚至在移除组件之前就冻结了,我必须手动关闭它。

那么,这段代码有什么问题?

@Override
public void actionPerformed(ActionEvent event) 
{
    if(((JButton)event.getSource()).getName() == "start")
    {
        for(Component c : QuizShow.frame.getContentPane().getComponents())
        {
            if(c.getName() == "wrapper")
            {
                final JPanel wrapper = (JPanel) c;

                SwingUtilities.invokeLater
                (
                    new Runnable()
                    {
                        public void run() {
                                wrapper.removeAll();
                                QuizPanel qp = new MainQuizPanel();
                                qp.setup();
                                wrapper.add(qp);
                        }
                    }
                );

                break;
            }
        }
    }

    System.out.println(event.getSource());      
}

编辑: 这是 qp.setup() 无效:

public void setup()
{
    for(int i = 0; i < 6; i++)
    {
        for(int j = 0; j < 6; j++)
        {
            questions[i*6+j] = new JButton();
            questions[i*6+j].setText(""+i*10);;
            add(questions[i*6+j]);
        }
    }   
}

这是 main(String[] args) 类:

SwingUtilities.invokeLater
    (
        new Runnable()
        {
            public void run() {
                frame = new QuizShowFrame("Quiz Show");
                frame.setSize(800, 600);
                frame.setResizable(false);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocation(100, 100);
                frame.setVisible(true);
            }               
        }
    );  

还有 QuizShowFrame 类:

public class QuizShowFrame extends JFrame
{
private static final long serialVersionUID = 1L;

public QuizPanel introPanel = new Intro();

public JPanel p = new JPanel();

public QuizShowFrame(String name) 
{
    super(name);

    this.setLayout(new BorderLayout());

    Container c = this.getContentPane();

    p.setBorder(new EmptyBorder(5,5,5,5));
    p.setName("wrapper");
    p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
    c.add(p);

    p.add(introPanel);

    try
    {
        introPanel.setup();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}
}

最后是 Intro 类:

public void setup()
{
    //...skipped JTextPanes...

    JButton gameStart = new JButton("Start the quiz show");
    gameStart.setName("start");

    try {
        gameStart.addActionListener(Listener.class.newInstance());
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

    add(gameStart);
}

【问题讨论】:

  • 你这里有某种永无止境的递归吗?
  • 你有没有通过单步执行代码进行调试?
  • 附带问题,不要这样做:if(c.getName() == "wrapper")。使用 equals 或 equalsIgnoreCase。至于您的主要问题,您正在某处踩踏 Swing 事件线程,根据发布的代码 sn-p 很难说。创建并发布您的minimal reproducible example。请注意,这不是完整的代码转储——请阅读链接。
  • actionPerformed() 中,您已经在 EDT 上运行。在 EDT 上调用所有 Swing 事件。所以没有必要使用SwingUtilities.invokeLater()。只需在 EDT 上做所有这些事情。

标签: java swing awt


【解决方案1】:

我明白了:

@Override
public void actionPerformed(final ActionEvent e) 
{
    if(((JButton)e.getSource()).getName().equals("start"))
    {
        for(final Component c : QuizShow.frame.getContentPane().getComponents())
        {
            if(c.getName().equals("wrapper"))
            {
                ((JPanel) c).removeAll();
                c.repaint();
                QuizPanel qp = new MainQuizPanel();
                ((JPanel) c).add(qp);
                qp.setup();
                c.validate();

                break;
            }
        }
    }           
}

This helped me. 似乎 .validate() 解决了它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2015-05-09
    • 2013-09-26
    • 2014-09-29
    相关资源
    最近更新 更多