【发布时间】:2015-07-12 16:59:01
【问题描述】:
感谢您的帮助。我是一个新手,正在尝试一些非常简单的事情。 我想要一个带有每隔几秒钟更改一次的文本(JLabel)的窗口(面板)。整个应用程序运行良好,除了正在更新的 JLabel(文本确实更改),但它没有显示在窗口(面板)上。即使我有检查点告诉我 JLabel 的文本正在更新和更改,该窗口从头到尾保持相同的文本。我到处寻找相同的问题并找到了一些 cmets,但没有任何帮助。有人说是 ActionListener,但是当我摆脱它时,它并没有什么不同。有人说线程中的循环不会让 JLabel 刷新,所以我尝试使用 JLabel 并且它的更新位于单独的线程上,但这也不起作用。我唯一没有尝试过的是使用 swingWorker (不太清楚如何)。线程尝试使用具有可运行方法的线程类。同样,这种方式一切正常,除了 JLabel 没有重新绘制自己。
这是没有线程的代码。这一切都在一个类中。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.*;
public class SWUI extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel panel;
JLabel label;
private Font font;
//Set up the interface. SWUI is working perfectly
SWUI() {
System.out.println("run started"); //just to check that the method gets called.
panel = new JPanel();
panel.setLayout(new BorderLayout(1, 1));
panel.setPreferredSize(new Dimension(1000, 400));
panel.setBackground(Color.white);
getContentPane().add(panel);
label = new JLabel("Ready"); //These four statements are working
label.setHorizontalAlignment(JLabel.CENTER);
font = new Font("Comic Sans MS", Font.PLAIN, 70);
label.setFont(font);
panel.add(label, BorderLayout.CENTER);
System.out.println("run done and draw to start");
label.setText("label is updatable"); //Checks that the whole method gets done and that the label is indeed able to get updated. It works.
}
// draw() mostly sets the Frame up, names it, sets closing behavior. It's working.
public void draw() {
System.out.println("draw started"); //To check that the method is getting invoked.
SWUI frame = new SWUI();
frame.setTitle("Sight Words Rock");
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
frame.addWindowListener(l);
frame.pack();
frame.setVisible(true);
System.out.println("draw done"); //To check that the whole method went through. It's all working.
}
//Should change the label to 4 sentences every 1 second. The text of the label does change, but it doesn't show on the interface (panel).
private void updateLabel(String word){
label.setText(word);
//label.revalidate(); //I tried these three statements one at a time and both together and they made no difference.
//label.updateUI();
//label.repaint();
System.out.println("The label now is: "+ label.getText()); //This confirms that the setText() is indeed changing the text
// of the label, but it doesn't show on the interface.
}
//Main gets the draw() started to initiate the interface and gets the sentences changed and sent to updateLabel() every second.
public static void main(String args[])
throws InterruptedException {
SWUI ui = new SWUI();
ui.draw();
String importantInfo[] = {
"Mares eat oats",
"Dogs eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
for (int i = 0;
i < importantInfo.length;
i++) {
//Pause for 1 second
Thread.sleep(1000);
//Print a message
System.out.println(importantInfo[i]);
ui.label.setText(importantInfo[i]);
ui.updateLabel(importantInfo[i]);
}
}
//This will come later once I figure how to fix the label. Someone else suggested that the problem were the listeners not letting the thread
// do the repainting(), but I tried getting rid of the "implements ActionListener" and the actionPerformed methods and it didn't make a
// difference. It still didn't work.
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
【问题讨论】:
-
那么你从哪个线程调用
setText?请记住,Swing 组件的所有更新都必须在 EDT 上进行,如果您需要从另一个线程触发更新,请使用SwingUtilities.invokeLater。 -
1) 使用逻辑一致的形式缩进代码行和块。缩进是为了让代码流更容易理解! 2) 曾经只需要源代码中的一个空白行。
{之后或}之前的空行通常也是多余的。