如何从 no-gui 类实时更新 Java Jframe 控件

我的 Java JFrame 项目有一个乏味的问题。

我想要做的(并寻找如何做)是从无ListBoxGUI 类实时添加元素,或者换句话说“异步”,而不冻结我的应用程序。这清楚吗?我试过SwingWorker和线程但没有结果。我所能做的就是在所有进程完成后更新列表框(显然我的应用程序冻结了,因为我的进程很长)。

这是我的架构:

http://img3.mukewang.com/618ce63a00012c5c01730093.jpg

控制器


package controller;


import business.MyBusiness;

import util.MyLog;

import view.MyView;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;


public class MyController {


    MyLog log;

    MyBusiness business;

    MyView view;


    public MyController(){

        log = new MyLog();

        business = new MyBusiness(log.getLog());

        view = new MyView(log.getLog());

    }


    public void runProcess() {

        view.addButtonListener(new ActionListener() { 

            @Override 

            public void actionPerformed(ActionEvent e) { 

                business.runProcess();

            }}

        );

    }

}

商业


package business;


import MyLog;

import java.util.List;

import javax.swing.DefaultListModel;

import javax.swing.SwingWorker;


public class MyBusiness {


    private int counter = 0;

    private DefaultListModel<String> model;

    private MyLog log;


    public MyBusiness(DefaultListModel<String> model) {

        this.model = model;a

    }


    public void runProcess() {

        SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {

            @Override

            protected Void doInBackground() throws Exception {

                for (int i = 0; i < 10; i++) {

                    publish("log message number " + counter++);

                    Thread.sleep(2000);

                }


                return null;

            }


            @Override

            protected void process(List<String> chunks) {

                // this is called on the Swing event thread

                for (String text : chunks) {

                    model.addElement("");

                }

            }

        };

        worker.execute();

    }


}



繁星淼淼
浏览 223回答 2
2回答

蓝山帝景

这是一个过度简化的示例,String说明使用SwingWorker.为了使 a 的基本使用SwingWorker更容易理解,它被过度简化。这是一个单文件mcve,这意味着您可以将整个代码复制粘贴到一个文件 (MyView.java) 中并执行:import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.event.ActionListener;import java.util.List;import javax.swing.DefaultListModel;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JList;import javax.swing.SwingWorker;//gui only, unaware of logic&nbsp;public class MyView extends JFrame {&nbsp; &nbsp; private JList<String> loglist;&nbsp; &nbsp; private JButton log;&nbsp; &nbsp; public MyView(DefaultListModel<String> model) {&nbsp; &nbsp; &nbsp; &nbsp; setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&nbsp; &nbsp; &nbsp; &nbsp; log = new JButton("Start Process");&nbsp; &nbsp; &nbsp; &nbsp; add(log, BorderLayout.PAGE_START);&nbsp; &nbsp; &nbsp; &nbsp; loglist = new JList<>(model);&nbsp; &nbsp; &nbsp; &nbsp; loglist.setPreferredSize(new Dimension(200,300));&nbsp; &nbsp; &nbsp; &nbsp; add(loglist, BorderLayout.PAGE_END);&nbsp; &nbsp; &nbsp; &nbsp; pack();&nbsp; &nbsp; &nbsp; &nbsp; setVisible(true);&nbsp; &nbsp; }&nbsp; &nbsp; void addButtonListener(ActionListener listener) {&nbsp; &nbsp; &nbsp; &nbsp; log.addActionListener(listener);&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String args[]) {&nbsp; &nbsp; &nbsp; &nbsp; new MyController();&nbsp; &nbsp; }}//represents the data (and some times logic) used by GUIclass Model {&nbsp; &nbsp; private DefaultListModel<String> model;&nbsp; &nbsp; Model() {&nbsp; &nbsp; &nbsp; &nbsp; model = new DefaultListModel<>();&nbsp; &nbsp; &nbsp; &nbsp; model.addElement("No logs yet");&nbsp; &nbsp; }&nbsp; &nbsp; DefaultListModel<String> getModel(){&nbsp; &nbsp; &nbsp; &nbsp; return model;&nbsp; &nbsp; }}//"wires" the GUI, model and business process&nbsp;class MyController {&nbsp; &nbsp; MyController(){&nbsp; &nbsp; &nbsp; &nbsp; Model model = new Model();&nbsp; &nbsp; &nbsp; &nbsp; MyBusiness business = new MyBusiness(model.getModel());&nbsp; &nbsp; &nbsp; &nbsp; MyView view = new MyView(model.getModel());&nbsp; &nbsp; &nbsp; &nbsp; view .addButtonListener(e -> business.start());&nbsp; &nbsp; }}//represents long process that needs to update GUIclass MyBusiness extends SwingWorker<Void, String>{&nbsp; &nbsp; private static final int NUMBER_OF_LOGS = 9;&nbsp; &nbsp; private int counter = 0;&nbsp; &nbsp; private DefaultListModel<String> model;&nbsp; &nbsp; public MyBusiness(DefaultListModel<String> model) {&nbsp; &nbsp; &nbsp; &nbsp; this.model= model;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; //simulate long process&nbsp;&nbsp; &nbsp; protected Void doInBackground() throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; for(int i = 0; i < NUMBER_OF_LOGS; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Successive calls to publish are coalesced into a java.util.List,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //which is by process.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; publish("log message number " + counter++);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(1000);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void process(List<String> logsList) {&nbsp; &nbsp; &nbsp; &nbsp; //process the list received from publish&nbsp; &nbsp; &nbsp; &nbsp; for(String element : logsList) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model.addElement(element);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; void start() {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; model.clear(); //clear initial model content&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; super.execute();&nbsp; &nbsp; }}

哆啦的时光机

首先是一些规则和建议:您的模型或此处的“业务”代码应该不了解 GUI,并且不应依赖于 GUI 结构同样,所有 Swing 代码都应在事件线程上调用,所有长时间运行的代码都应在后台线程中调用如果您有长时间运行的更改状态的代码,并且如果该状态需要反映在 GUI 中,这意味着您需要某种回调机制,模型以某种方式通知重要方其状态已经改变。这可以使用 PropertyChangeListeners 或通过将某种类型的回调方法注入模型来完成。使视图变得愚蠢。它从用户那里获取输入并通知控制器,它由控制器更新。几乎所有的程序“大脑”都位于控制器和模型中。例外——一些输入验证通常在视图中完成。不要忽略基本的 Java OOP 规则——通过保持字段私有来隐藏信息,并允许外部类仅通过您完全控制的公共方法更新状态。该MCVE结构是一个很好的学习和使用,即使不问一个问题在这里。学习简化您的代码并隔离您的问题以最好地解决它。例如,可以将此代码复制并粘贴到所选 IDE 中的单个文件中,然后运行:import java.awt.event.ActionEvent;import java.awt.event.KeyEvent;import java.util.List;import java.util.Random;import java.util.concurrent.TimeUnit;import java.util.function.Consumer;import javax.swing.*;public class Mcve1 {&nbsp; &nbsp; private static void createAndShowGui() {&nbsp; &nbsp; &nbsp; &nbsp; // create your model/view/controller and hook them together&nbsp; &nbsp; &nbsp; &nbsp; MyBusiness1 model = new MyBusiness1();&nbsp; &nbsp; &nbsp; &nbsp; MyView1 myView = new MyView1();&nbsp; &nbsp; &nbsp; &nbsp; new MyController1(model, myView);&nbsp; // the "hooking" occurs here&nbsp; &nbsp; &nbsp; &nbsp; // create and start the GUI&nbsp; &nbsp; &nbsp; &nbsp; JFrame frame = new JFrame("MCVE");&nbsp; &nbsp; &nbsp; &nbsp; frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&nbsp; &nbsp; &nbsp; &nbsp; frame.getContentPane().add(myView);&nbsp; &nbsp; &nbsp; &nbsp; frame.pack();&nbsp; &nbsp; &nbsp; &nbsp; frame.setLocationRelativeTo(null);&nbsp; &nbsp; &nbsp; &nbsp; frame.setVisible(true);&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; // start GUI on Swing thread&nbsp; &nbsp; &nbsp; &nbsp; SwingUtilities.invokeLater(() -> createAndShowGui());&nbsp; &nbsp; }}@SuppressWarnings("serial")class MyView1 extends JPanel {&nbsp; &nbsp; private MyController1 controller;&nbsp; &nbsp; private DefaultListModel<String> logListModel = new DefaultListModel<>();&nbsp; &nbsp; private JList<String> logList = new JList<>(logListModel);&nbsp; &nbsp; public MyView1() {&nbsp; &nbsp; &nbsp; &nbsp; logList.setFocusable(false);&nbsp; &nbsp; &nbsp; &nbsp; logList.setPrototypeCellValue("abcdefghijklabcdefghijklabcdefghijklabcdefghijkl");&nbsp; &nbsp; &nbsp; &nbsp; logList.setVisibleRowCount(15);&nbsp; &nbsp; &nbsp; &nbsp; add(new JScrollPane(logList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));&nbsp; &nbsp; &nbsp; &nbsp; // my view's buttons just notify the controller that they've been pushed&nbsp; &nbsp; &nbsp; &nbsp; // that's it&nbsp; &nbsp; &nbsp; &nbsp; add(new JButton(new AbstractAction("Do stuff") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; putValue(MNEMONIC_KEY, KeyEvent.VK_D);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void actionPerformed(ActionEvent evt) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (controller != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; controller.doStuff(); // notification done here&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; &nbsp; public void setController(MyController1 controller) {&nbsp; &nbsp; &nbsp; &nbsp; this.controller = controller;&nbsp; &nbsp; }&nbsp; &nbsp; // public method to allow controller to update state&nbsp; &nbsp; public void updateList(String newValue) {&nbsp; &nbsp; &nbsp; &nbsp; logListModel.addElement(newValue);&nbsp; &nbsp; }}class MyController1 {&nbsp; &nbsp; private MyBusiness1 myBusiness;&nbsp; &nbsp; private MyView1 myView;&nbsp; &nbsp; // hook up concerns&nbsp; &nbsp; public MyController1(MyBusiness1 myBusiness, MyView1 myView) {&nbsp; &nbsp; &nbsp; &nbsp; this.myBusiness = myBusiness;&nbsp; &nbsp; &nbsp; &nbsp; this.myView = myView;&nbsp; &nbsp; &nbsp; &nbsp; myView.setController(this);&nbsp; &nbsp; }&nbsp; &nbsp; public void doStuff() {&nbsp; &nbsp; &nbsp; &nbsp; // long running code called within the worker's doInBackground method&nbsp; &nbsp; &nbsp; &nbsp; SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; protected Void doInBackground() throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // pass a call-back method into the method&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // so that this worker is notified of changes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myBusiness.longRunningCode(new Consumer<String>() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // call back code&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void accept(String text) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; publish(text); // publish to the process method&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; protected void process(List<String> chunks) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // this is called on the Swing event thread&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (String text : chunks) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myView.updateList(text);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; worker.execute();&nbsp; &nbsp; }}class MyBusiness1 {&nbsp; &nbsp; private Random random = new Random();&nbsp; &nbsp; private String text;&nbsp; &nbsp; public void longRunningCode(Consumer<String> consumer) throws InterruptedException {&nbsp; &nbsp; &nbsp; &nbsp; consumer.accept("Starting");&nbsp; &nbsp; &nbsp; &nbsp; // mimic long-running code&nbsp; &nbsp; &nbsp; &nbsp; int sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; consumer.accept("This is message for initial process");&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; // Doing another long process and then print log&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; consumer.accept("This is not complete. Review");&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; // Doing another long process and then print log&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; consumer.accept("Ok this works. Have fun");&nbsp; &nbsp; }&nbsp; &nbsp; public String getText() {&nbsp; &nbsp; &nbsp; &nbsp; return text;&nbsp; &nbsp; }}另一种做同样事情的方法是使用符合 Swing 的 PropertyChangeSupport 和 PropertyChangeListeners。例如:import java.awt.event.ActionEvent;import java.awt.event.KeyEvent;import java.beans.*;import java.util.Random;import java.util.concurrent.TimeUnit;import javax.swing.*;import javax.swing.event.SwingPropertyChangeSupport;public class Mcve2 {&nbsp; &nbsp; private static void createAndShowGui() {&nbsp; &nbsp; &nbsp; &nbsp; MyBusiness2 myBusiness = new MyBusiness2();&nbsp; &nbsp; &nbsp; &nbsp; MyView2 myView = new MyView2();&nbsp; &nbsp; &nbsp; &nbsp; new MyController2(myBusiness, myView);&nbsp; &nbsp; &nbsp; &nbsp; JFrame frame = new JFrame("MCVE");&nbsp; &nbsp; &nbsp; &nbsp; frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&nbsp; &nbsp; &nbsp; &nbsp; frame.getContentPane().add(myView);&nbsp; &nbsp; &nbsp; &nbsp; frame.pack();&nbsp; &nbsp; &nbsp; &nbsp; frame.setLocationRelativeTo(null);&nbsp; &nbsp; &nbsp; &nbsp; frame.setVisible(true);&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; SwingUtilities.invokeLater(() -> createAndShowGui());&nbsp; &nbsp; }}@SuppressWarnings("serial")class MyView2 extends JPanel {&nbsp; &nbsp; private MyController2 controller;&nbsp; &nbsp; private DefaultListModel<String> logListModel = new DefaultListModel<>();&nbsp; &nbsp; private JList<String> logList = new JList<>(logListModel);&nbsp; &nbsp; public MyView2() {&nbsp; &nbsp; &nbsp; &nbsp; logList.setFocusable(false);&nbsp; &nbsp; &nbsp; &nbsp; logList.setPrototypeCellValue("abcdefghijklabcdefghijklabcdefghijklabcdefghijkl");&nbsp; &nbsp; &nbsp; &nbsp; logList.setVisibleRowCount(15);&nbsp; &nbsp; &nbsp; &nbsp; add(new JScrollPane(logList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));&nbsp; &nbsp; &nbsp; &nbsp; add(new JButton(new AbstractAction("Do stuff") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; putValue(MNEMONIC_KEY, KeyEvent.VK_D);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void actionPerformed(ActionEvent evt) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (controller != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; controller.doStuff();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; &nbsp; public void setController(MyController2 controller) {&nbsp; &nbsp; &nbsp; &nbsp; this.controller = controller;&nbsp; &nbsp; }&nbsp; &nbsp; public void updateList(String newValue) {&nbsp; &nbsp; &nbsp; &nbsp; logListModel.addElement(newValue);&nbsp; &nbsp; }}class MyController2 {&nbsp; &nbsp; private MyBusiness2 myBusiness;&nbsp; &nbsp; private MyView2 myView;&nbsp; &nbsp; public MyController2(MyBusiness2 myBusiness, MyView2 myView) {&nbsp; &nbsp; &nbsp; &nbsp; this.myBusiness = myBusiness;&nbsp; &nbsp; &nbsp; &nbsp; this.myView = myView;&nbsp; &nbsp; &nbsp; &nbsp; myView.setController(this);&nbsp; &nbsp; &nbsp; &nbsp; myBusiness.addPropertyChangeListener(MyBusiness2.TEXT, new TextListener());&nbsp; &nbsp; }&nbsp; &nbsp; public void doStuff() {&nbsp; &nbsp; &nbsp; &nbsp; new Thread(() -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myBusiness.longRunningCode();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (InterruptedException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }) .start();&nbsp; &nbsp; }&nbsp; &nbsp; private class TextListener implements PropertyChangeListener {&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public void propertyChange(PropertyChangeEvent evt) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String newValue = (String) evt.getNewValue();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myView.updateList(newValue);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}class MyBusiness2 {&nbsp; &nbsp; public static final String TEXT = "text";&nbsp; &nbsp; private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);&nbsp; &nbsp; private Random random = new Random();&nbsp; &nbsp; private String text;&nbsp; &nbsp; public void longRunningCode() throws InterruptedException {&nbsp; &nbsp; &nbsp; &nbsp; setText("Starting");&nbsp; &nbsp; &nbsp; &nbsp; // mimic long-running code&nbsp; &nbsp; &nbsp; &nbsp; int sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; setText("This is message for initial process");&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; // Doing another long process and then print log&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; setText("This is not complete. Review");&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; // Doing another long process and then print log&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; &nbsp; sleepTime = 500 + random.nextInt(2 * 3000);&nbsp; &nbsp; &nbsp; &nbsp; TimeUnit.MILLISECONDS.sleep(sleepTime);&nbsp; &nbsp; &nbsp; &nbsp; setText("Ok this works. Have fun");&nbsp; &nbsp; }&nbsp; &nbsp; public void setText(String text) {&nbsp; &nbsp; &nbsp; &nbsp; String oldValue = this.text;&nbsp; &nbsp; &nbsp; &nbsp; String newValue = text;&nbsp; &nbsp; &nbsp; &nbsp; this.text = text;&nbsp; &nbsp; &nbsp; &nbsp; pcSupport.firePropertyChange(TEXT, oldValue, newValue);&nbsp; &nbsp; }&nbsp; &nbsp; public String getText() {&nbsp; &nbsp; &nbsp; &nbsp; return text;&nbsp; &nbsp; }&nbsp; &nbsp; public void addPropertyChangeListener(PropertyChangeListener listener) {&nbsp; &nbsp; &nbsp; &nbsp; pcSupport.addPropertyChangeListener(listener);&nbsp; &nbsp; }&nbsp; &nbsp; public void removePropertyChangeListener(PropertyChangeListener listener) {&nbsp; &nbsp; &nbsp; &nbsp; pcSupport.removePropertyChangeListener(listener);&nbsp; &nbsp; }&nbsp; &nbsp; public void addPropertyChangeListener(String name, PropertyChangeListener listener) {&nbsp; &nbsp; &nbsp; &nbsp; pcSupport.addPropertyChangeListener(name, listener);&nbsp; &nbsp; }&nbsp; &nbsp; public void removePropertyChangeListener(String name, PropertyChangeListener listener) {&nbsp; &nbsp; &nbsp; &nbsp; pcSupport.removePropertyChangeListener(name, listener);&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java