我想以大约300毫秒的恒定速率更新JLabel。目前我使用以下代码部分来执行此操作:
class setLabel {
PdfHandler PdfHandling = new PdfHandler(pdfName);//as the name implies, this object is to handle pdf's
Iterator<String> textIterator=PdfHandling.getPageStringList(pageNr).iterator();//extracting text from a pdf word by word
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
centerLabel.setText(textIterator.next());//update the JLabel cenetrLabel with the next string in the textIterator
}
};
public void startTask(){
new javax.swing.Timer(rate, task).start();
}
}
问题是使用此代码会导致JLabel(centerLabel)的非常量更新。这意味着两个“新”标签之间的时间不是恒定的(您可以用裸眼看到)并且由于更新之间的时间太短,似乎会跳过一些字符串。我已经尝试了几个不同的东西,比如使用invokeLater或sheduledExecutorService,但似乎都有同样的问题。我的问题是,如果这是正确的方法,如果使用JLabel方法完成这项任务从一开始就是一个坏主意?如果是这样,那么以平滑可控的方式(有点像视频)一个接一个地显示字符串的好方法。
非常感谢,任何帮助和建议都表示赞赏。
修改
我尝试使用以下代码而不是Iterator,但我不知道这是否更快:
class stringBuffer {
private ArrayList<String> buf;
private final int size;
private int index;
stringBuffer(ArrayList<String> list){
buf = list;
size = buf.size();
}
public String getNext(){
if(index < size){
return buf.get(index++);
} else {
return null;
}
}
}
问题仍然存在,所以我试图立即访问该列表
centerLabel.setText(list.get(index++));
但这仍然没有解决问题。
第二次编辑:
这是一个演示问题的可运行示例:
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.BorderLayout;
class JLabelTest {
public static void main(String[] args){
BuildGui gui = new BuildGui();
}
}
class BuildGui {
JFrame topLevelFrame;
JLabel centerLabel;
JButton startButton;
BuildGui(){
initFrame();
addElements();
addActionListeners();
}
public void initFrame(){
topLevelFrame = new JFrame("JFrame");
topLevelFrame.setBounds(200, 200, 400, 200);
topLevelFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
topLevelFrame.setVisible(true);
}
public void addElements(){
centerLabel = new JLabel("Center");
startButton = new JButton("Start");
centerLabel.setHorizontalAlignment(JLabel.CENTER);
centerLabel.setVerticalAlignment(JLabel.CENTER);
topLevelFrame.add(startButton, BorderLayout.SOUTH);
topLevelFrame.add(centerLabel,BorderLayout.CENTER);
}
public void addActionListeners(){
startButton.addActionListener( new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
new setLabel().startTask();
startButton.setEnabled(false);
}
});
}
class setLabel {
private final String[] stringArray = {"one","two","one","two","one","two","one","two"};//just something to display
private final int size = stringArray.length;
private final ArrayList<String> list = new ArrayList<String>(Arrays.asList(stringArray));
private int index = 0;
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
centerLabel.setText(list.get(index++));
if(index >= size) index = 0;
}
};
public void startTask(){
new javax.swing.Timer(300, task).start();
}
}
}
第三次编辑
我被告知上一个例子有几个问题。所以我试着解决它们,我希望这个例子更好
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.EventQueue;
class JLabelTest2 extends JFrame {
JLabel centerLabel;
JButton startButton;
public static void main(String[] args){
EventQueue.invokeLater(() -> {
JLabelTest2 gui = new JLabelTest2();
gui.setVisible(true);
});
}
JLabelTest2(){
initUI();
}
public void initUI(){
setBounds(200, 200, 400, 200);
centerLabel = new JLabel("Center");
startButton = new JButton("Start");
centerLabel.setHorizontalAlignment(JLabel.CENTER);
centerLabel.setVerticalAlignment(JLabel.CENTER);
getContentPane().add(startButton, BorderLayout.SOUTH);
getContentPane().add(centerLabel,BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
startButton.addActionListener( new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
new setLabel().startTask();
startButton.setEnabled(false);
}
});
pack();
}
class setLabel {
private final String[] stringArray = {"one","two","one","two","one","two","one","two"};
private final int size = stringArray.length;
private final ArrayList<String> list = new ArrayList<String>(Arrays.asList(stringArray));
private int index = 0;
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
centerLabel.setText(list.get(index++));
if(index >= size) index = 0;
}
};
public void startTask(){
new javax.swing.Timer(300, task).start();
}
}
}
但不知怎的,我的机器上仍然存在问题。我没有运行很多,即使我关闭所有正在运行的程序,问题也不会改变。在我看不到的代码中是否还有一些问题?
第4次修改
添加centerLabel.repaint()并未更改行为。我仍然看到标签发生变化但频率不稳定。环境信息:
操作系统:Ubuntu 14.04 LTS,64位
处理器:Intel Core™i5-2430M CPU @ 2.40GHz×4
记忆:5,7 GiB
Java信息:
java版“1.8.0_102”
Java(TM)SE运行时环境(版本1.8.0_102-b14)
Java HotSpot(TM)64位服务器VM(版本25.102-b14,混合模式)