MVC进度条线程
我为我的devise使用MVC模式,当用户按下searchbutton时,我调用了模型中的search,但是我也想用从该模型返回的信息更新进度条。
我曾尝试使用一个摆动,但进度栏不更新。 我怀疑我的线程有问题。
我在控制器中定义的button是:
class SearchBtnListener implements ActionListener { public void actionPerformed(ActionEvent e) { _view.displayProgress(); } }
这将调用模型中的search,并在视图中进行以下调用:
public void displayProgress() { TwoWorker task = new TwoWorker(); task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent e) { if ("progress".equals(e.getPropertyName())) { _progressBar.setValue((Integer) e.getNewValue()); } } }); task.execute(); } private class TwoWorker extends SwingWorker<Void, Void> { @Override protected Void doInBackground() throws Exception { _model.startSearch(getTerm()); // time intensive code File file = new File("lock"); while (file.exists()){ setProgress(_model.getStatus()); System.out.println(_model.getStatus()); // never called } return null; } protected void done(){ updateMain(); } }
testing模型中定义的虚拟函数:
public int getStatus(){ Random r = new Random(); return r.nextInt(); }
不要打电话
_progressBar.setValue(_model.getStatus());
从你的SwingWorker中,因为这是从后台线程调用Swing代码,并且是PropertyChangeListener的。 相反,只需设置进度属性即可。
此外,不要从doInBackground方法中调用done(),因为这需要由SwingWorker从EDT调用。 所以当SwingWorker实际完成时,让它自己调用这个方法。
此外,完成()应完成() – 第一个字母不应该大写,你应该在这个代码中使用@Override注释,所以你可以肯定,你正在覆盖方法正确。
另外,这是做什么?
_model.startSearch(_view.getTerm());
它会调用需要一段时间才能完成的代码吗? 是否应该从SwingWorker doInBackground本身初始化?
编辑:另一种select是给模型绑定int属性,称为进度,然后添加一个PropertyChangeListener它直接让它更新JProgressBar。 例如,
import java.awt.BorderLayout; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.*; public class MVC_ProgressBarThread { private static void createAndShowUI() { MVC_View view = new MVC_View(); MVC_Model model = new MVC_Model(); MVC_Control control = new MVC_Control(view, model); view.setControl(control); JFrame frame = new JFrame("MVC_ProgressBarThread"); frame.getContentPane().add(view); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } @SuppressWarnings("serial") class MVC_View extends JPanel { private MVC_Control control; private JProgressBar progressBar = new JProgressBar(); private JButton startActionButton = new JButton("Start Action"); public MVC_View() { startActionButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { buttonActionPerformed(); } }); JPanel buttonPanel = new JPanel(); buttonPanel.add(startActionButton); setLayout(new BorderLayout()); add(buttonPanel, BorderLayout.NORTH); add(progressBar, BorderLayout.CENTER); } public void setControl(MVC_Control control) { this.control = control; } private void buttonActionPerformed() { if (control != null) { control.doButtonAction(); } } public void setProgress(int progress) { progressBar.setValue(progress); } public void start() { startActionButton.setEnabled(false); } public void done() { startActionButton.setEnabled(true); setProgress(100); } } class MVC_Control { private MVC_View view; private MVC_Model model; public MVC_Control(final MVC_View view, final MVC_Model model) { this.view = view; this.model = model; model.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent pce) { if (MVC_Model.PROGRESS.equals(pce.getPropertyName())) { view.setProgress((Integer)pce.getNewValue()); } } }); } public void doButtonAction() { view.start(); SwingWorker<Void, Void> swingworker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { model.reset(); model.startSearch(); return null; } @Override protected void done() { view.done(); } }; swingworker.execute(); } } class MVC_Model { public static final String PROGRESS = "progress"; private static final int MAX = 100; private static final long SLEEP_DELAY = 100; private int progress = 0; private PropertyChangeSupport pcs = new PropertyChangeSupport(this); public void setProgress(int progress) { int oldProgress = this.progress; this.progress = progress; PropertyChangeEvent evt = new PropertyChangeEvent(this, PROGRESS, oldProgress, progress); pcs.firePropertyChange(evt); } public void reset() { setProgress(0); } public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } public void startSearch() { for (int i = 0; i < MAX; i++) { int newValue = (100 * i) / MAX; setProgress(newValue); try { Thread.sleep(SLEEP_DELAY); } catch (InterruptedException e) {} } } }