Swing GUI 不更新

Posted

技术标签:

【中文标题】Swing GUI 不更新【英文标题】:Swing GUI not updating 【发布时间】:2012-05-05 14:26:37 【问题描述】:

我正在编写一个应用程序,它可以读取音频,分析这些数据,然后实时显示结果。目前,我正在使用 SwingWorker 运行启动后台分析的循环,并在每次分析完成时调用循环内的 SwingUtilities.invokeLater 方法来更新 GUI 组件。目前,GUI 似乎在随机更新,有时根本不更新。

以下代码显示了我是如何尝试完成此任务的。 TunerListener 是 JPanel 子类的内部类。 PrevNote、nextNote、frequency、light 变量都是我要更新的 JPanel 子类中的组件:

private class TunerListener implements ActionListener 
    private boolean firstUpdate = true;
    private boolean executing = false;
    private TunerWorker tunerWorker = null;

    private final class TunerWorker extends SwingWorker<Void, Void> 

        @Override
        protected Void doInBackground() 
            while (!this.isCancelled()) 

                // Audio analysis in worker thread
                model.update(firstUpdate);

                // Update components in EDT
                if (!this.isCancelled()) 
                    SwingUtilities.invokeLater(new Runnable() 
                        @Override
                        public void run() 
                            prevNote.setText(model.getPrev());
                            currentNote.setText(model.getNote());
                            nextNote.setText(model.getNext());
                            frequency.setText("Frequency: "
                                    + model.getFrequency());
                            switch (model.getOffset()) 
                                case -2:
                                    light_2.setIcon(onRed);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case -1:
                                    light_2.setIcon(off);
                                    light_1.setIcon(onRed);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case 0:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(onGreen);
                                    light1.setIcon(off);
                                    light2.setIcon(off);
                                    break;
                                case 1:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(onRed);
                                    light2.setIcon(off);
                                    break;
                                case 2:
                                    light_2.setIcon(off);
                                    light_1.setIcon(off);
                                    light0.setIcon(offBig);
                                    light1.setIcon(off);
                                    light2.setIcon(onRed);
                                    break;
                            
                            firstUpdate = false;
                        
                    );
                

            

            return null;
        

        @Override
        protected void done() 
        

    ;

    @Override
    public void actionPerformed(ActionEvent ae) 

        if (ae.getActionCommand().equals("tune")) 
            if (!executing) 
                executing = true;
                firstUpdate = true;
                tune.setText("Stop Tuning");
                tunerWorker = new TunerWorker();
                tunerWorker.execute();
             else 
                tune.setText("Start Tuning");
                executing = false;
                tunerWorker.cancel(true);
            
        

    

编辑 我注意到,当我使用调试器时,有时我会告诉我找不到源,并且在调试窗口中它会显示有关 FutureTask$Sync.innerRun 的信息。这会缩小范围吗?

【问题讨论】:

您是否尝试过 GUI 组件或框架的 validate() 和 repaint() 方法? 我认为您不需要将代码放入 SwingUtilities.invokeLater(...) thingy,这是 SwingWorker。此外,因为在我看来,您尝试更新的内容都是String(如果我没记错的话),那么您可以简单地调用publish(),这反过来又会调用process(...),如果总是在EDT .我猜你的SwingWorker&lt;Void, String&gt; 的第二个参数应该是String 而不是Void 为了更好的帮助,请尽快使用SSCCE编辑您的问题 【参考方案1】:

作为替代方案,使用javax.swing.Timer 的实例(图示为here)开始停止播放选定的Note,显示为@987654322 @。 play() 方法提供了一个异步操作的 SourceDataLineenum Note 使得构造 JComboBox 变得特别容易。

final JComboBox combo = new JComboBox();
for (Note note : Note.values()) 
    combo.addItem(note);

combo.addActionListener(new ActionListener() 

    @Override
    public void actionPerformed(ActionEvent e) 
        System.out.println(combo.getSelectedItem());
    
);
this.add(combo);

【讨论】:

以上是关于Swing GUI 不更新的主要内容,如果未能解决你的问题,请参考以下文章

Swing GUI 客户端侦听器未响应远程 RMI 属性的更新

强制 Java 刷新 Java Swing GUI

线程限制/swingworkers

Swing GUI 中 validate()、revalidate() 和 invalidate() 之间的区别

使用 invokeLater 后 Swing UI 不更新

Swing:不使用 EDT 创建 GUI 是不是安全? [复制]