再次,请帮助我! 在下面的代码中,我想通过按下按钮并在Label中键入计时器线程来开始。每次按下按钮都应该开始一个新线程并在每个标签上标记它。但不幸的是,为每个标签编写了相同的计时器。你能帮助我们做对吗?如果你能告诉我这个错误,我的意思是什么?
public class TimerThreads implements ActionListener{
JFrame jFrame = new JFrame();
JLabel[] labels;
int second = 0;
int minute = 0;
String s = "";
String m = "";
int l = 0;
public TimerThreads(){
JLabel one = new JLabel();
JLabel two = new JLabel();
JLabel three = new JLabel();
JLabel four = new JLabel();
labels = new JLabel[]{one, two, three, four};
jFrame.setLayout(new GridLayout(0, 2, 5, 5));
jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JButton start = new JButton("Start");
start.addActionListener(this);
JButton stop = new JButton("Stop");
stop.addActionListener(this);
jFrame.add(start);
jFrame.add(stop);
jFrame.setVisible(true);
jFrame.pack();
}
public static void main(String[] args) {
new TimerThreads();
}
@Override
public void actionPerformed(ActionEvent e) {
String select = e.getActionCommand();
switch(select){
case "Start":
jFrame.add(labels[l]);
jFrame.revalidate();
jFrame.repaint();
TimerThread t = new TimerThread(labels[l]);
t.start();
l++;
break;
case "Stop":
//
break;
}
}
class TimerThread extends Thread{
JLabel jLabel;
public TimerThread(JLabel jLabel) {
this.jLabel = jLabel;
}
@Override
public void run() {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
second++;
if(String.valueOf(second).length() == 1){
s = "0";
}
else{
s = "";
}
if(second == 60){
second = 0;
s = "0";
minute++;
}
if(String.valueOf(minute).length() == 1){
m = "0";
}
jLabel.setText(m + String.valueOf(minute) + ":" + s + String.valueOf(second));
}
},0, 1000);
}
}
}
答案 0 :(得分:2)
您的错误的原因在于:
public class TimerThreads implements ActionListener {
JFrame jFrame = new JFrame();
JLabel[] labels;
// ***** these fields below
int second = 0;
int minute = 0;
String s = "";
String m = "";
// ***** these fields above
int l = 0;
这四个字段是类的实例字段,并由您创建的每个TimerTask实例共享,因此所有字段都将显示相同的确切时间。
解决方案是将这些字段设置为嵌套类的本地字段:
public class TimerThreads implements ActionListener {
JFrame jFrame = new JFrame();
JLabel[] labels;
// int second = 0;
// int minute = 0;
// String s = "";
// String m = "";
int l = 0;
public TimerThreads() {
//.....
}
// ....
class TimerThread extends Thread {
JLabel jLabel;
public TimerThread(JLabel jLabel) {
this.jLabel = jLabel;
}
@Override
public void run() {
java.util.Timer timer = new java.util.Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// ***** add these fields here
int second = 0;
int minute = 0;
String s = "";
String m = "";
说完这个之后,当你使用Swing Timer或者javax.swing.Timer时,你使用了错误的Timer,一个java.util.Timer,你就会得到有风险的代码。这非常重要,因为后一个Timer与Swing事件模型配合良好,可以防止线程冲突。请查看Swing Timer Tutorial
其他问题:如果用户需要运行4个以上的线程,则使用固定大小的数组会导致索引超出范围的风险。请改用ArrayList。