Java 第二个变量忽略第一个
Java second variable dismisses first one
我要做的是制作一个小图形用户界面,当单击 button
时,它会开始显示 threads
的进度条;但是,我们必须使用实现 Runnable interface
的内部 class 来完成它,并且在 class 的构造函数中,它需要一个 String
和一个 JProgressBar
目的。然后在主构造函数中,我们应该实例化 2 个 JProgressBar
对象,然后使用这些 JProgressBars
.
创建 2 个内部 class 对象
只有我的第二个 JProgressBar
使用 thread
更新。我知道我的第二个 JProgressBar
基本上覆盖了我的第一个,但我不知道我将如何解决这个问题,因为如果我尝试将内部 class 的构造函数更改为设置 2 JProgressBar
属性等于构造函数的参数,那么第一个 JProgessBar
就完全从 GUI 中消失了。这是我的代码,感谢任何可以提供帮助的人。
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Lab4Part2 {
//Attributes
private JFrame frame;
private String progress;
private JProgressBar jpb;
//Constructor
public Lab4Part2() {
//Create frame with specified grid layout
frame = new JFrame();
GridLayout grid = new GridLayout(0,1);
frame.setLayout(grid);
JButton jbClick = new JButton("Let's start this show");
frame.add(jbClick);
//Add in JProgressBars and create Inner Class objects with them
JProgressBar jpb1 = new JProgressBar();
JProgressBar jpb2 = new JProgressBar();
InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);
//Anonymous class for the button's action listener
jbClick.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Thread t1 = new Thread(bar1);
Thread t2 = new Thread(bar2);
t1.start();
t2.start();
}
});
//Adds inner object to frame
frame.add(bar1);
frame.add(bar2);
//Packing and stuff
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//Inner class
class InnerProgress extends JPanel implements Runnable {
//Constructor
public InnerProgress(String pbar, JProgressBar jpBar) {
jpBar.setMinimum(0);
jpBar.setMaximum(80);
jpBar.setStringPainted(true);
progress = pbar;
jpb = jpBar;
JLabel label = new JLabel(pbar);
add(label);
add(jpBar);
}
//Thread action
public void run() {
System.out.println("We are running " + Thread.currentThread().getName());
for(int i = 1; i<= 80; i++) {
try {
Thread.currentThread().sleep((long)Math.random()*100);
jpb.setValue(i);
}
catch(InterruptedException ie) {
System.out.println(ie);
}
}
System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
}
//Main
public static void main(String[] args) {
new Lab4Part2();
}
}
你的内部 class 应该维护它自己对它传递的 JProgressBar
的引用。
只需取...
private JProgressBar jpb;
然后把它移到你内心的class
class InnerProgress extends JPanel implements Runnable {
private JProgressBar jpb;
//...
那么,另外两个问题
一,(long)Math.random()*100
导致 Math.random()
的结果变为 int
,这将导致它变成 0
。
您需要对运算结果进行强制转换,例如...
Thread.currentThread().sleep((int)(Math.random() * 500));
(注意:我测试了 500)
二、Swing不是线程安全的。这意味着您不应该从事件调度线程的上下文之外更新 UI。
所以,而不是...
jpb.setValue(i);
我写了一个新方法,它会相应地更新 UI
protected void updateProgress(int value) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
InnerProgress.this.jpb.setValue(value);
}
});
}
(总而言之,在匿名上下文中引用变量会带来问题)
然后简单地使用 updateProgress(i);
调用它
可运行示例...
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
public class Lab4Part2 {
//Attributes
private JFrame frame;
private String progress;
//Constructor
public Lab4Part2() {
//Create frame with specified grid layout
frame = new JFrame();
GridLayout grid = new GridLayout(0, 1);
frame.setLayout(grid);
JButton jbClick = new JButton("Let's start this show");
frame.add(jbClick);
//Add in JProgressBars and create Inner Class objects with them
JProgressBar jpb1 = new JProgressBar();
JProgressBar jpb2 = new JProgressBar();
InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);
//Anonymous class for the button's action listener
jbClick.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Thread t1 = new Thread(bar1);
Thread t2 = new Thread(bar2);
t1.start();
t2.start();
}
});
//Adds inner object to frame
frame.add(bar1);
frame.add(bar2);
//Packing and stuff
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//Inner class
class InnerProgress extends JPanel implements Runnable {
private JProgressBar jpb;
//Constructor
public InnerProgress(String pbar, JProgressBar jpBar) {
jpBar.setMinimum(0);
jpBar.setMaximum(80);
jpBar.setStringPainted(true);
progress = pbar;
jpb = jpBar;
JLabel label = new JLabel(pbar);
add(label);
add(jpBar);
}
//Thread action
public void run() {
System.out.println("We are running " + Thread.currentThread().getName());
for (int i = 1; i <= 80; i++) {
try {
Thread.currentThread().sleep((int)(Math.random() * 500));
updateProgress(i);
} catch (InterruptedException ie) {
System.out.println(ie);
}
}
System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
protected void updateProgress(int value) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
InnerProgress.this.jpb.setValue(value);
}
});
}
}
//Main
public static void main(String[] args) {
new Lab4Part2();
}
}
我要做的是制作一个小图形用户界面,当单击 button
时,它会开始显示 threads
的进度条;但是,我们必须使用实现 Runnable interface
的内部 class 来完成它,并且在 class 的构造函数中,它需要一个 String
和一个 JProgressBar
目的。然后在主构造函数中,我们应该实例化 2 个 JProgressBar
对象,然后使用这些 JProgressBars
.
只有我的第二个 JProgressBar
使用 thread
更新。我知道我的第二个 JProgressBar
基本上覆盖了我的第一个,但我不知道我将如何解决这个问题,因为如果我尝试将内部 class 的构造函数更改为设置 2 JProgressBar
属性等于构造函数的参数,那么第一个 JProgessBar
就完全从 GUI 中消失了。这是我的代码,感谢任何可以提供帮助的人。
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Lab4Part2 {
//Attributes
private JFrame frame;
private String progress;
private JProgressBar jpb;
//Constructor
public Lab4Part2() {
//Create frame with specified grid layout
frame = new JFrame();
GridLayout grid = new GridLayout(0,1);
frame.setLayout(grid);
JButton jbClick = new JButton("Let's start this show");
frame.add(jbClick);
//Add in JProgressBars and create Inner Class objects with them
JProgressBar jpb1 = new JProgressBar();
JProgressBar jpb2 = new JProgressBar();
InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);
//Anonymous class for the button's action listener
jbClick.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Thread t1 = new Thread(bar1);
Thread t2 = new Thread(bar2);
t1.start();
t2.start();
}
});
//Adds inner object to frame
frame.add(bar1);
frame.add(bar2);
//Packing and stuff
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//Inner class
class InnerProgress extends JPanel implements Runnable {
//Constructor
public InnerProgress(String pbar, JProgressBar jpBar) {
jpBar.setMinimum(0);
jpBar.setMaximum(80);
jpBar.setStringPainted(true);
progress = pbar;
jpb = jpBar;
JLabel label = new JLabel(pbar);
add(label);
add(jpBar);
}
//Thread action
public void run() {
System.out.println("We are running " + Thread.currentThread().getName());
for(int i = 1; i<= 80; i++) {
try {
Thread.currentThread().sleep((long)Math.random()*100);
jpb.setValue(i);
}
catch(InterruptedException ie) {
System.out.println(ie);
}
}
System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
}
//Main
public static void main(String[] args) {
new Lab4Part2();
}
}
你的内部 class 应该维护它自己对它传递的 JProgressBar
的引用。
只需取...
private JProgressBar jpb;
然后把它移到你内心的class
class InnerProgress extends JPanel implements Runnable {
private JProgressBar jpb;
//...
那么,另外两个问题
一,(long)Math.random()*100
导致 Math.random()
的结果变为 int
,这将导致它变成 0
。
您需要对运算结果进行强制转换,例如...
Thread.currentThread().sleep((int)(Math.random() * 500));
(注意:我测试了 500)
二、Swing不是线程安全的。这意味着您不应该从事件调度线程的上下文之外更新 UI。
所以,而不是...
jpb.setValue(i);
我写了一个新方法,它会相应地更新 UI
protected void updateProgress(int value) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
InnerProgress.this.jpb.setValue(value);
}
});
}
(总而言之,在匿名上下文中引用变量会带来问题)
然后简单地使用 updateProgress(i);
可运行示例...
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
public class Lab4Part2 {
//Attributes
private JFrame frame;
private String progress;
//Constructor
public Lab4Part2() {
//Create frame with specified grid layout
frame = new JFrame();
GridLayout grid = new GridLayout(0, 1);
frame.setLayout(grid);
JButton jbClick = new JButton("Let's start this show");
frame.add(jbClick);
//Add in JProgressBars and create Inner Class objects with them
JProgressBar jpb1 = new JProgressBar();
JProgressBar jpb2 = new JProgressBar();
InnerProgress bar1 = new InnerProgress("Progress 1: ", jpb1);
InnerProgress bar2 = new InnerProgress("Progress 2: ", jpb2);
//Anonymous class for the button's action listener
jbClick.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Thread t1 = new Thread(bar1);
Thread t2 = new Thread(bar2);
t1.start();
t2.start();
}
});
//Adds inner object to frame
frame.add(bar1);
frame.add(bar2);
//Packing and stuff
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//Inner class
class InnerProgress extends JPanel implements Runnable {
private JProgressBar jpb;
//Constructor
public InnerProgress(String pbar, JProgressBar jpBar) {
jpBar.setMinimum(0);
jpBar.setMaximum(80);
jpBar.setStringPainted(true);
progress = pbar;
jpb = jpBar;
JLabel label = new JLabel(pbar);
add(label);
add(jpBar);
}
//Thread action
public void run() {
System.out.println("We are running " + Thread.currentThread().getName());
for (int i = 1; i <= 80; i++) {
try {
Thread.currentThread().sleep((int)(Math.random() * 500));
updateProgress(i);
} catch (InterruptedException ie) {
System.out.println(ie);
}
}
System.out.println("Thread name: " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
protected void updateProgress(int value) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
InnerProgress.this.jpb.setValue(value);
}
});
}
}
//Main
public static void main(String[] args) {
new Lab4Part2();
}
}