JLabel通过setText更改值,但不在屏幕上更新

时间:2014-11-08 21:04:21

标签: java swing jlabel

好吧,我现在已经处理了一段代码,差不多2天了,无法解决问题。

渴望行为

以下代码应该以aprox的间隙逐个显示10个字符串(下一个替换前一个字符串)。 200毫秒。

Q1 Q2 Q3 ......等到q10

当用户按下ENTER键时,此显示顺序开始。

反思行为

屏幕等待aprox。按下后2秒,然后显示q10。

更多信息

  1. 标签stringText在执行期间(我通过写入控制台找到)更改了值,但屏幕上没有更新(JFrame)。
  2. 标签通过按钮上的点击事件更改值,其他所有内容保持相同(尽可能多)。
  3. 计时器是通过一个循环 - 这可能不是大多数人喜欢的,但让我们暂时忘记它。
  4. 方法displayQuestion(int number)有一些不必要的行。我把它们都放了,因为我不确定它会起作用。实际上,没有任何效果!
  5. 代码

    package sush4;
    
    import java.util.Date;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Sush4 {
    
        // Timer control variables
        static long holdTimeWord = 200L;
        static long elapsedTime = 0L;
    
        // Counter for Strings displayed
        static int i = 0;
    
        // Strings in use
        static String[] questionStack = {"q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10"};
    
        // UI: String display variables
        static JLabel stringText;
        static JFrame mainWindow;
    
        // Key binding action object
        private static Action userKeyCommand;
    
        /// Display the question
        private static void displayQuestion(int number) {
            mainWindow.remove(stringText);
            stringText.setText(questionStack[number]);
            mainWindow.add(stringText);
            mainWindow.setVisible(true);
            mainWindow.revalidate();
            mainWindow.repaint();
        }
    
        private static void q120(){
    
            //// Initiate the text
            for(i = 0; i < questionStack.length; i++) {
    
                displayQuestion(i);
    
                //// And wait for Word hold time
                long startTime = System.currentTimeMillis();
                elapsedTime = 0L;
                // Now wait for event to happen
                while ( (elapsedTime < holdTimeWord) ) {
                    elapsedTime = (new Date()).getTime() - startTime;
                }
            }
        }
    
        Sush4() {
    
            //// Create the Window
            mainWindow = new JFrame("Sush");
            mainWindow.setSize(700, 500);
            mainWindow.setLayout(new FlowLayout());
    
            //// And add key bindings for user events
            userKeyCommand = new UserKeyCommand();
            JRootPane rootPane = mainWindow.getRootPane();
            rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ENTER"), "doEnterAction");
            rootPane.getActionMap().put("doEnterAction", userKeyCommand);
    
            // Terminate the program when the user closes the application.
            mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            mainWindow.setResizable(false);
    
            //// Add the text label
            stringText = new JLabel("Random Text");
            mainWindow.add(stringText);
    
            //// Finally, display the frame.
            mainWindow.setVisible(true);
        }
    
        static class UserKeyCommand extends AbstractAction {
            public void actionPerformed( ActionEvent tf ) {
                q120();
            } 
        } 
    
        public static void main(String[] args) {
    
            // Create the frame on the event dispatching thread.
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new Sush4();
                }
            });
        }
    }
    

1 个答案:

答案 0 :(得分:3)

  

计时器是通过一个循环 - 这可能不是大多数人喜欢的,但暂时忘记它。

实际上,我们不能忘记这个循环,因为这是造成麻烦的原因。请参阅,单击按钮时调用q120()方法:

static class UserKeyCommand extends AbstractAction {
    @Override // don't forget @Override annotation
    public void actionPerformed( ActionEvent tf ) {
        q120();
    } 
} 

这意味着此代码在Event Dispatch Thread (EDT)的上下文中执行。这是一个单一且特殊的线程,其中必须创建/更新Swing组件并且必须执行事件处理(即:动作事件)。如果我们在此线程中有一个循环等待某些条件继续,我们将阻止EDT并且GUI无法重新绘制自己,直到线程被解锁。

对于重复性任务(例如问题中的任务),请考虑使用Swing Timer。对于具有中期结果的繁重任务,请考虑使用SwingWorker代替。