问题描述
我正在一个线程中模拟多个任务-当所有任务都应报告给GUI时。因此,我有一个独特的表单,其中包含4个面板,这些面板应答复并执行不同的任务..它们每个都应保持数据库合并并向GUI报告内容。在此示例中,我只是将数字写到textArea中。
public class FormMain extends JFrame {
private JButton btnStart;
private JPanel _panelTop,_panelMid,_panelBot;
private PanelFoo panelFooA,panelFooB,panelFooC,panelFooD;
private final List<String> ugsRj = Arrays.asList("AB");
private final List<String> ugsMg = Arrays.asList("CD","EF");
private final List<String> ugsBA = Arrays.asList("GH","IJ","KL");
private final List<String> ugsPE = Arrays.asList("MN","OP","RS","TU");
private void initialize() {
this._panelTop = new JPanel();
this._panelMid = new JPanel();
this._panelBot = new JPanel();
this.btnStart = new JButton("Start");
this._panelBot.add(this.btnStart);
this.panelFooA = new PanelFoo(this.ugsRj);
this.panelFooB = new PanelFoo(this.ugsMg);
this.panelFooC = new PanelFoo(this.ugsBA);
this.panelFooD = new PanelFoo(this.ugsPE);
_panelMid.setLayout(new BoxLayout(_panelMid,BoxLayout.X_AXIS));
this._panelMid.add(this.panelFooA);
this._panelMid.add(this.panelFooB);
this._panelMid.add(this.panelFooC);
this._panelMid.add(this.panelFooD);
}
public FormMain() {
initialize();
getContentPane().setLayout(new BorderLayout());
setSize(800,516);
setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(this._panelTop,BorderLayout.norTH);
getContentPane().add(this._panelMid,BorderLayout.CENTER);
getContentPane().add(this._panelBot,BorderLayout.soUTH);
this.btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final AuthenticationUser auth = new AuthenticationUser();
auth.setUser("test");
auth.setPassword("p@ss");
//
final SwingWorker<Void,Void> worker = new SwingWorker<Void,Void>() {
@Override
protected Void doInBackground() throws Exception {
final WorkerDoSomething w1 = new WorkerDoSomething(panelFooA);
w1.addPropertychangelistener(new ProgressListener(panelFooA.getProgressBar()));
final WorkerDoSomething w2 = new WorkerDoSomething(panelFooB);
w2.addPropertychangelistener(new ProgressListener(panelFooB.getProgressBar()));
final WorkerDoSomething w3 = new WorkerDoSomething(panelFooC);
w3.addPropertychangelistener(new ProgressListener(panelFooC.getProgressBar()));
final WorkerDoSomething w4 = new WorkerDoSomething(panelFooD);
w4.addPropertychangelistener(new ProgressListener(panelFooD.getProgressBar()));
w1.execute();
w2.execute();
w3.execute();
w4.execute();
return null;
}
};
worker.execute();
}
});
}
}
public class ProgressListener implements Propertychangelistener {
private JProgressBar bar;
ProgressListener() {
}
ProgressListener(final JProgressBar b) {
this.bar = b;
this.bar.setValue(0);
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
// Determine whether the property is progress type
if ("progress".equals(evt.getPropertyName())) {
this.bar.setValue((int) evt.getNewValue());
}
}
}
public class PanelFoo extends JPanel {
/**
*
*/
private static final long serialVersionUID = -1400188281877395934L;
private JLabel label;
private JTextArea textArea;
private JScrollPane scrollPanel;
private JProgressBar progressBar;
public PanelFoo(final List<String> listofStates) {
setLayout(new FlowLayout());
setSize(180,400);
final ImageIcon icon = createImageIcon("/images/waiting-list.png","waiting start");
this.label = new JLabel(listofStates.get(0),icon,SwingConstants.HORIZONTAL);
add(this.label);
this.textArea = new JTextArea("Numbers: \n");
this.textArea.setWrapStyleWord(true);
this.scrollPanel = new JScrollPane(this.textArea);
this.scrollPanel.setPreferredSize(new Dimension(150,350));
this.progressBar = new JProgressBar(0,100);
add(this.scrollPanel);
add(this.progressBar);
setVisible(true);
}
/** Returns an ImageIcon,or null if the path was invalid. */
public ImageIcon createImageIcon(final String path,final String description) {
if (path != null) {
ImageIcon imageIcon = new ImageIcon(getClass().getResource(path));
final Image image = imageIcon.getimage();
final Image newimg = image.getScaledInstance(30,30,Image.SCALE_SMOOTH);
imageIcon = new ImageIcon(newimg,description);
return imageIcon;
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
public final JLabel getLabel() {
return this.label;
}
public final void setLabel(final JLabel label) {
this.label = label;
}
public final JTextArea getTextArea() {
return this.textArea;
}
public final void setTextArea(final JTextArea textArea) {
this.textArea = textArea;
}
public final JProgressBar getProgressBar() {
return this.progressBar;
}
public final void setProgressBar(final JProgressBar progressBar) {
this.progressBar = progressBar;
}
}
public class WorkerDoSomething extends SwingWorker<Void,Void> {
private JTextArea txtArea;
private JLabel label;
private Random r = new Random();
WorkerDoSomething() {
}
public WorkerDoSomething(final PanelFoo panelFooInstance) {
this.txtArea = panelFooInstance.getTextArea();
this.label = panelFooInstance.getLabel();
}
private Integer randomInt(final int min,final int max) {
final Integer randomNumber = this.r.nextInt((max - min) + 1) + min;
return randomNumber;
}
@Override
protected Void doInBackground() throws Exception {
final Integer randomNumber = randomInt(10000000,1000000000);
long j;
int progress = 0;
final int onePerCent = randomNumber / 100;
final int onePerMillion = onePerCent / 10;
for (j = 0; j <= randomNumber; j++) {
if (j % onePerCent == 0) {
progress = (int) j / onePerCent;
setProgress(progress);
}
if (j % onePerMillion == 0) {
publish(j);
}
//Thread.sleep(randomInt(1000,5000));
}
return null;
}
private void publish(final long num) {
this.txtArea.append(num + "\n");
this.txtArea.setCaretPosition(this.txtArea.getDocument().getLength());
}
}
这毕竟是主要的GUI:
这是执行:
我只需要在每个WorkerDoSomething
的任务上等待一段时间,然后添加该行(以前已注释掉):Thread.sleep(randomInt(1000,5000));
但是,当我这样做时,..当然,整个执行都冻结了,..因为我使用单个线程来运行所有任务。
有解决方案吗?
哦...我必须在业务中使用java 1.8:
java version "1.8.0_251"
Java(TM) SE Runtime Environment (build 1.8.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.251-b08,mixed mode)
整个项目都在我个人的git
上---首先使用调试透视图进行编辑
解决方法
由于Swing使用10个线程的线程池运行工作程序,因此执行不会冻结。
如果您对此部分进行注释,则可以看到它正常工作:
mov eax,10
push eax
push 20
mov ecx,eax
pop eax
PS-为什么要在actionPerformed方法中创建一个新的SwingWorker?
为什么不这样简单地写:
@IBOutlet weak var Label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
Label.font = LobsterTwo.bold.font(size: 50)
}
}
public enum LobsterTwo: String {
case bold = "LobsterTwo-Bold"
case boldItalic = "LobsterTwo-BoldItalic"
case italic = "LobsterTwo-Italic"
public func font(size: CGFloat) -> UIFont {
return UIFont(name: self.rawValue,size: size)!
}
,
您是否读过SwingWorker类的 javadoc ?这是摘录:
SwingWorker类
类型参数:
T-此SwingWorker的doInBackground和get方法返回的结果类型
V-此SwingWorker的发布和处理方法用于执行中间结果的类型
您在publish()
方法中正确调用了方法doInBackground()
,但是尚未覆盖方法process()
。请参阅Tasks that Have Interim Results。假设您的publish()
方法确实应该是process()
方法,那么这应该是类WorkerDoSomething
public class WorkerDoSomething extends SwingWorker<Void,Long> {
这应该是方法process()
(而不是方法publish()
)
protected void process(List<Long> nums) {
this.txtArea.append(nums.get(nums.size() - 1) + "\n");
this.txtArea.setCaretPosition(this.txtArea.getDocument().getLength());
}
但是这样做不能解决您的问题。我无法解释为什么,但是如果您在方法Thread.sleep()
中将调用的位置更改为doInBackground()
,则可以解决问题。如果我将对方法sleep()
的调用放在对setProgress()
的调用之前,则GUI不会“冻结”。我想到了从this网页(名为 Java Swing如何-将冗长的任务放入SwingWorker
这是我对您的应用程序的重写。我可以自由地重写其中的一部分,但实际上,您只需要注意WorkerDoSomething
类即可。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class FormMain implements Runnable,ActionListener {
private static final int PANELS = 4;
private static final String START = "Start";
private JFrame frame;
private PanelFoo[] fooPanels;
public FormMain() {
fooPanels = new PanelFoo[PANELS];
for (int i = 0; i < PANELS; i++) {
fooPanels[i] = new PanelFoo();
}
}
@Override // java.awt.event.ActionListener
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case START:
start();
break;
default:
JOptionPane.showMessageDialog(frame,actionCommand,"Unhandled",JOptionPane.WARNING_MESSAGE);
}
}
@Override // java.lang.Runnable
public void run() {
createGui();
}
private JButton createButton(String text,int mnemonic,String tooltip) {
JButton button = new JButton(text);
button.setMnemonic(mnemonic);
button.setToolTipText(tooltip);
button.addActionListener(this);
return button;
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(createButton(START,KeyEvent.VK_S,"Start your engines!"));
return buttonsPanel;
}
private void createGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMainPanel(),BorderLayout.CENTER);
frame.add(createButtonsPanel(),BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel(new GridLayout(0,4,10,10));
for (PanelFoo pf : fooPanels) {
mainPanel.add(pf);
}
return mainPanel;
}
private void start() {
for (PanelFoo pf : fooPanels) {
pf.start();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new FormMain());
}
}
class PanelFoo extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 4029040375048696554L;
private JProgressBar progressBar;
private JTextArea textArea;
public PanelFoo() {
super(new BorderLayout());
textArea = new JTextArea(20,10);
JScrollPane scrollPane = new JScrollPane(textArea);
add(scrollPane,BorderLayout.CENTER);
progressBar = new JProgressBar(0,100);
add(progressBar,BorderLayout.PAGE_END);
}
public void appendText(String text) {
textArea.append(text);
textArea.append("\n");
}
@Override // java.beans.PropertyChangeListener
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
}
}
public void start() {
WorkerDoSomething worker = new WorkerDoSomething(this);
worker.addPropertyChangeListener(this);
worker.execute();
}
}
class WorkerDoSomething extends SwingWorker<Void,Long> {
private PanelFoo fooPanel;
private Random r = new Random();
public WorkerDoSomething(PanelFoo pf) {
fooPanel = pf;
}
@Override
protected Void doInBackground() throws Exception {
Integer randomNumber = randomInt(10000000,1000000000);
long j;
int progress = 0;
final int onePerCent = randomNumber / 100;
final int onePerMillion = onePerCent / 10;
for (j = 0; j <= randomNumber; j++) {
if (j % onePerCent == 0) {
try {
Thread.sleep(1000);
}
catch (InterruptedException xInterrupted) {
// Ignore
}
progress = (int) j / onePerCent;
setProgress(progress);
}
if (j % onePerMillion == 0) {
publish(j);
}
}
return null;
}
@Override
protected void process(List<Long> numbers) {
Long number = numbers.get(numbers.size() - 1);
fooPanel.appendText(String.valueOf(number));
}
private Integer randomInt(final int min,final int max) {
final Integer randomNumber = this.r.nextInt((max - min) + 1) + min;
return randomNumber;
}
}
从技术上讲,以上内容回答了您的问题,即:
有解决方案吗?
我相信我已经提供了一个解决方案,即使我无法解释它为什么起作用。