这些方法可能是关键在这里:
getWorkedItems ();getWorkedTickets ();getRemainTickets ();
如果它们需要任何时间执行,则在Swing事件线程上调用它们将阻塞该线程并完全冻结您的GUI,从而使其无法正确绘制自己。解决方案是在后台线程中调用任何长时间运行的方法,例如SwingWorker的
doInBackground()方法,并仅在Swing事件线程上进行Swing调用。同样,SwingWorker可以很好地解决此问题,实际上,它具有可以使用的自己的“绑定”进度属性。在worker中,只需调用
setProgress(value)其中value是您的int从0到100的值。然后将PropertyChangeListener附加到worker,以便在progress属性更新时可以将这些更改通知给GUI。
注意事项:请务必听取工作人员完成其运行的信息,以便您可以致电
get()该工作人员,因为这种病使您可以捕获并响应运行过程中可能已调用的任何异常。
例如,您的代码可能类似于:
public void executeTask() { progress = new UIProgress(); progress.prepareGUI(); final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // progress.updateProgress (10); setProgress(10); // sets the worker's "bound" progress property getWorkedItems(); setProgress(30); getWorkedTickets(); setProgress(50); getRemainTickets(); setProgress(70); // ... only further background work goes here // no direct Swing calls return null; } }; myWorker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { // if the progress property has been changed // get its value and use it to update the GUI progress.updateProgress((int) evt.getNewValue()); } else if (SwingWorker.Statevalue.DONE == evt.getNewValue()) { // worker is done then here notify the GUI // perhaps call: // jf.postTriagedTicketDetailsDaily(); // call get() on worker to catch and handle exceptions try { myWorker.get(); } catch (InterruptedException | ExecutionException e) { // TODO handle the excpetions here e.printStackTrace(); } } } }); myWorker.execute();}
注意:代码未经测试。
- 请查看课程:Swing中的并发
- 另请查看Swing教程
如果这不能解决您的问题,那么您可能必须创建并发布一个sscce或最小示例程序/mcve,在其中将代码压缩为仍可编译和运行的最小位,并且没有外部依赖项(例如需要(链接到数据库或图像),没有与您的问题无关的额外代码,但仍然可以演示您的问题。
例如,此小程序在工作的GUI中演示以上代码:
import java.awt.*;import java.awt.event.ActionListener;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.io.IOException;import java.net.URI;import java.net.URISyntaxException;import java.util.concurrent.ExecutionException;import java.util.concurrent.TimeUnit;import javax.swing.*;public class TestWorker { private UIProgress progress; public static void main(String[] args) { SwingUtilities.invokeLater(() -> { new TestWorker().executeTask(); }); } public void executeTask() { progress = new UIProgress(); progress.prepareGUI(); final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // progress.updateProgress (10); setProgress(10); // sets the worker's "bound" progress property getWorkedItems(); setProgress(30); getWorkedTickets(); setProgress(50); getRemainTickets(); setProgress(70); TimeUnit.SECONDS.sleep(2); // ... only further background work goes here // no direct Swing calls return null; } }; myWorker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { // if the progress property has been changed // get its value and use it to update the GUI progress.updateProgress((int) evt.getNewValue()); } else if (SwingWorker.Statevalue.DONE == evt.getNewValue()) { // worker is done then here notify the GUI progress.updateProgress(100); // perhaps call: // jf.postTriagedTicketDetailsDaily(); // call get() on worker to catch and handle exceptions try { myWorker.get(); } catch (InterruptedException | ExecutionException e) { // TODO handle the exceptions here e.printStackTrace(); } } } }); myWorker.execute(); } // dummy methods just to demonstrate long-running pre private void getRemainTickets() { mySleep(3); // emulate long-running pre } private void getWorkedTickets() { mySleep(4); } private void getWorkedItems() { mySleep(2); } private void mySleep(int seconds) { try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) {} } @SuppressWarnings("serial") private class UIProgress extends JPanel { private static final int PREF_W = 400; private static final int PREF_H = 100; private JProgressBar progressBar = new JProgressBar(0, 100); private JLabel statusLabel = new JLabel(" "); public UIProgress() { JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); statusPanel.add(new JLabel("Status:")); statusPanel.add(Box.createHorizontalStrut(4)); statusPanel.add(statusLabel); setLayout(new BorderLayout()); setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); add(statusPanel, BorderLayout.PAGE_START); add(progressBar, BorderLayout.PAGE_END); } public void prepareGUI() { Jframe frame = new Jframe("UI Progress"); frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); frame.add(this); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } @Override public Dimension getPreferredSize() { if (isPreferredSizeSet()) { return super.getPreferredSize(); } return new Dimension(PREF_W, PREF_H); } public void updateProgress(int prog) { String text = String.format("Current Progress is %d%%", prog); statusLabel.setText(text); progressBar.setValue(prog); } }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)