JProgress Bar 不在 SwingWorker 中更新
JProgress Bar Not Updating Within SwingWorker
对于添加许多 JProgressBar 更新问题,我深表歉意,但这真的让我发疯。
我有一个正在通过 SwingWorker 更新的 JProgressBar,但我仍然遇到在完成后更新栏的典型问题。
相关代码如下:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class SwingTest {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
init();
}
});
}
public static void init() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JProgressBar bar = new JProgressBar();
JButton button = new JButton("Start");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
bar.setMaximum(100);
bar.setValue(0);
SwingWorker worker = new SwingWorker<String, Void>()
{
@Override
public String doInBackground()
{
int val = 0;
// +1 to make inclusive
for (int i = 0; i < 100; i++)
{
try
{
Thread.sleep(50);
} catch (InterruptedException e)
{
e.printStackTrace();
}
setProgress(++val);
}
return "Hello SwingWorker World";
}
@Override
public void done()
{
}
};
worker.addPropertyChangeListener(
new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent evt)
{
if ("progress".equals(evt.getPropertyName()))
{
bar.setValue((Integer)evt.getNewValue());
}
}
}
);
worker.execute();
try
{
System.out.println("Return: " + worker.get().toString());
} catch (InterruptedException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
} catch (ExecutionException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
}
}
});
panel.add(button);
panel.add(bar);
frame.add(panel);
frame.pack();
frame.setSize(200,90);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
如果问题可能是由于其他部分引起的,我将在需要时使用更多代码编辑我的问题。
提前致谢。
编辑:将代码精简为最小的产品。
好吧,我不确切知道你的代码在做什么,但我在你的代码中没有看到你有 "delay" 的任何地方。
因此,循环继续执行,所有绘制请求都合并到一个请求中,因此您只能看到最终值。
您可以通过在 setProgress(...)
方法后添加 Thread.sleep()
来验证是否是问题所在。
如果是这种情况,问题是为什么要使用进度条,因为代码执行得如此之快。
阅读 How to Use Progress Bars 上的 Swing 教程部分并从工作演示开始。然后您可以修改工作代码以查看在您进行更改时会发生什么。
您发布的代码中的问题是当您启动 SwingWorker 时,您会立即等待它 运行。这会阻塞事件线程,从而阻止更新显示:
worker.execute(); // This starts the thread in the background
try
{
// This immediately stops the event handler waiting for the worker to finish
System.out.println("Return: " + worker.get().toString());
} catch (InterruptedException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
} catch (ExecutionException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
}
如果您注释掉整个 try-catch 块,它将 运行 并更新显示。
如果您需要等待 worker 的结果,那么您应该在另一个线程上等待结果,并允许 UI 线程继续。
对于添加许多 JProgressBar 更新问题,我深表歉意,但这真的让我发疯。
我有一个正在通过 SwingWorker 更新的 JProgressBar,但我仍然遇到在完成后更新栏的典型问题。
相关代码如下:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class SwingTest {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
init();
}
});
}
public static void init() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JProgressBar bar = new JProgressBar();
JButton button = new JButton("Start");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
bar.setMaximum(100);
bar.setValue(0);
SwingWorker worker = new SwingWorker<String, Void>()
{
@Override
public String doInBackground()
{
int val = 0;
// +1 to make inclusive
for (int i = 0; i < 100; i++)
{
try
{
Thread.sleep(50);
} catch (InterruptedException e)
{
e.printStackTrace();
}
setProgress(++val);
}
return "Hello SwingWorker World";
}
@Override
public void done()
{
}
};
worker.addPropertyChangeListener(
new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent evt)
{
if ("progress".equals(evt.getPropertyName()))
{
bar.setValue((Integer)evt.getNewValue());
}
}
}
);
worker.execute();
try
{
System.out.println("Return: " + worker.get().toString());
} catch (InterruptedException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
} catch (ExecutionException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
}
}
});
panel.add(button);
panel.add(bar);
frame.add(panel);
frame.pack();
frame.setSize(200,90);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
如果问题可能是由于其他部分引起的,我将在需要时使用更多代码编辑我的问题。
提前致谢。
编辑:将代码精简为最小的产品。
好吧,我不确切知道你的代码在做什么,但我在你的代码中没有看到你有 "delay" 的任何地方。
因此,循环继续执行,所有绘制请求都合并到一个请求中,因此您只能看到最终值。
您可以通过在 setProgress(...)
方法后添加 Thread.sleep()
来验证是否是问题所在。
如果是这种情况,问题是为什么要使用进度条,因为代码执行得如此之快。
阅读 How to Use Progress Bars 上的 Swing 教程部分并从工作演示开始。然后您可以修改工作代码以查看在您进行更改时会发生什么。
您发布的代码中的问题是当您启动 SwingWorker 时,您会立即等待它 运行。这会阻塞事件线程,从而阻止更新显示:
worker.execute(); // This starts the thread in the background
try
{
// This immediately stops the event handler waiting for the worker to finish
System.out.println("Return: " + worker.get().toString());
} catch (InterruptedException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
} catch (ExecutionException e1)
{
e1.printStackTrace();
System.out.println("Failed.");
}
如果您注释掉整个 try-catch 块,它将 运行 并更新显示。
如果您需要等待 worker 的结果,那么您应该在另一个线程上等待结果,并允许 UI 线程继续。