java - 当 ArrayList 在模型中更新时 JList 应该在 View 中更新

标签 java swing model-view-controller arraylist jlist

我已经尝试了一段时间,但没有成功。我看过 ListModel,但一直难以将其实现到我当前的项目中。

我有一个 Producer 类线程向模型中的 ArrayList 添加元素。这工作正常并且 ArrayList 正在运行时更新。我的问题是,然后我希望将添加到 ArrayList 的新对象添加到 View 类中的 JList。我看不到如何将 ListModel 或 DefaultListModel 合并到我当前的设置中。非常感谢帮助。

public class Person
{
    private String name;
    private int    age;

    public Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public int getAge()
    {
        return age;
    }

    public String toString()
    {
        return this.name;
    }
}

public class Producer extends Thread
{
    private Model model;

    public Producer(Model model)
    {
        this.model = model;
    }

    public void run()
    {
        Person fred     = new Person("Fred Flintstone", 37);
        Person wilma    = new Person("Wilma Flintstone", 18);
        Person pebbles  = new Person("Pebbles Flintstone", 15);
        Person dino     = new Person("Dino Flintstone", 45);
        Person barney   = new Person("Barney Rubble", 76);
        Person betty    = new Person("Betty Rubble", 76);
        Person bamm     = new Person("Bamm-Bamm Rubble", 76);

        try
        {
            model.addPerson(fred);
            Thread.sleep(1500);
            model.addPerson(wilma);
            Thread.sleep(1500);
            model.addPerson(pebbles);
            Thread.sleep(1500);
            model.addPerson(dino);
            Thread.sleep(1500);
            model.addPerson(barney);
            Thread.sleep(1500);
            model.addPerson(betty);
            Thread.sleep(1500);
            model.addPerson(bamm);
        }
        catch(Exception e)
        {
            System.out.println("Error adding Person object to Model.people
                                ArrayList" + e);
        }
    }
}

public class Model 
{
    private List <Person> people;

    public Model()
    {
        people = new ArrayList<Person>();
    }

    public List<Person> getPeople()
    {
        return people;
    }

    public void addPerson(Person aPerson)
    {
        people.add(aPerson);
        System.out.println("Person object added to people list:" + aPerson);
    }

    public void removePerson(Person aPerson)
    {
        people.remove(aPerson);
    }
}

public class View extends JFrame
{
    private JPanel              topPanel, botPanel;
    private JList               peopleList;
    private JScrollPane         scrollPane;
    private Model               model;

    public View(Model model)
    {
        this.model = model;
        setSize(200, 220);
        setTitle("View");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        topPanel = new JPanel();
        botPanel = new JPanel();
        peopleList = new JList(model.getPeople().toArray());
        scrollPane = new JScrollPane(peopleList);
        topPanel.setLayout(new GridLayout(1, 1));
        topPanel.add(scrollPane);
        topPanel.setBorder(BorderFactory.createTitledBorder
       (BorderFactory.createEtchedBorder(), "People list"));

        Container cp = getContentPane();
        cp.add(topPanel, BorderLayout.NORTH);
        cp.add(botPanel, BorderLayout.SOUTH);
    }
}

public class Main 
{
    public static void main(String[] args)
    {
        Model model = new Model();
        View theView = new View(model);
        theView.setVisible(true);
        Producer producer = new Producer(model);
        producer.start();
    }
}

最佳答案

在这里使用适当的 MVC 模式: View 监听模型中的变化并根据来自模型的通知进行更新:

  1. 在模型上添加 PropertyChangeSupport 并在修改模型时触发 PropertyChangeEvent
  2. 将 View 添加为模型的 PropertyChangeListener
  3. 相应地对通知使用react(如果 Person 被添加到您的模型中,当您收到“New person added”的事件时,将其添加到 ListModel您的 peopleList,与“删除的人”等相同...)

http://docs.oracle.com/javase/7/docs/api/java/beans/PropertyChangeSupport.html

注意:由于您的模型将被 EDT(事件调度线程)以外的另一个线程修改,因此请确保您在 EDT 上修改您的 UI(查看 SwingUtilities.isEventDispatchingThread()SwingUtilities.invokeLater())

更新:

这是一个片段,说明了我在上面试图解释的内容(很抱歉,如果它有点冗长,但我尽量保持与您的原始代码尽可能接近):

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Main {

    public class Person {

        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        @Override
        public String toString() {
            return this.name;
        }
    }

    public class Producer extends Thread {
        private Model model;

        public Producer(Model model) {
            this.model = model;
        }

        @Override
        public void run() {
            Random random = new Random();
            Person fred = new Person("Fred Flintstone", 37);
            Person wilma = new Person("Wilma Flintstone", 18);
            Person pebbles = new Person("Pebbles Flintstone", 15);
            Person dino = new Person("Dino Flintstone", 45);
            Person barney = new Person("Barney Rubble", 76);
            Person betty = new Person("Betty Rubble", 76);
            Person bamm = new Person("Bamm-Bamm Rubble", 76);
            while (true) {
                try {
                    model.addPerson(fred);
                    Thread.sleep(1500);
                    model.addPerson(wilma);
                    Thread.sleep(1500);
                    model.addPerson(pebbles);
                    Thread.sleep(1500);
                    model.addPerson(dino);
                    Thread.sleep(1500);
                    model.addPerson(barney);
                    Thread.sleep(1500);
                    model.addPerson(betty);
                    Thread.sleep(1500);
                    model.addPerson(bamm);
                    while (model.getPeople().size() > 0) {
                        Person p = model.getPeople().get(random.nextInt(model.getPeople().size()));
                        model.removePerson(p);
                        Thread.sleep(1000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public class Model {
        private static final String PEOPLE = "people";

        private List<Person> people;

        private PropertyChangeSupport propertyChangeSupport;

        public Model() {
            people = new ArrayList<Person>();
            propertyChangeSupport = new PropertyChangeSupport(this);
        }

        public PropertyChangeSupport getPropertyChangeSupport() {
            return propertyChangeSupport;
        }

        public List<Person> getPeople() {
            return people;
        }

        public void addPerson(Person aPerson) {
            people.add(aPerson);
            System.out.println("Person object added to people list:" + aPerson);
            getPropertyChangeSupport().firePropertyChange(PEOPLE, null, aPerson);
        }

        public void removePerson(Person aPerson) {
            people.remove(aPerson);
            getPropertyChangeSupport().firePropertyChange(PEOPLE, aPerson, null);
        }
    }

    public class View extends JFrame implements PropertyChangeListener {
        private JPanel topPanel, botPanel;
        private JList peopleList;
        private JScrollPane scrollPane;
        private Model model;
        private DefaultListModel peopleListModel;

        public View(Model model) {
            this.model = model;
            setSize(200, 220);
            setTitle("View");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            topPanel = new JPanel();
            botPanel = new JPanel();
            peopleListModel = new DefaultListModel();
            for (Person p : model.getPeople()) {
                peopleListModel.addElement(p);
            }
            peopleList = new JList(peopleListModel);
            model.getPropertyChangeSupport().addPropertyChangeListener(Model.PEOPLE, this);
            scrollPane = new JScrollPane(peopleList);
            topPanel.setLayout(new GridLayout(1, 1));
            topPanel.add(scrollPane);
            topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "People list"));

            Container cp = getContentPane();
            cp.add(topPanel, BorderLayout.NORTH);
            cp.add(botPanel, BorderLayout.SOUTH);
        }

        @Override
        public void propertyChange(final PropertyChangeEvent evt) {
            if (!SwingUtilities.isEventDispatchThread()) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        propertyChange(evt);
                    }
                });
                return;
            }
            if (evt.getSource() == model) {
                if (Model.PEOPLE.equals(evt.getPropertyName())) {
                    if (evt.getOldValue() != null && evt.getNewValue() == null) {
                        peopleListModel.removeElement(evt.getOldValue());
                    } else if (evt.getOldValue() == null && evt.getNewValue() != null) {
                        peopleListModel.addElement(evt.getNewValue());
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        new Main().init();
    }

    private void init() {
        final Model model = new Model();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                View theView = new View(model);
                theView.setVisible(true);
            }
        });
        Producer producer = new Producer(model);
        producer.start();
    }
}

关于java - 当 ArrayList 在模型中更新时 JList 应该在 View 中更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13141732/

相关文章:

java - JSON 转换问题

model-view-controller - 在哪里可以找到 MVC 的清晰示例?

java - 我们可以创建一个 Spring ScheduledExecutorTask 池吗?

java - 使用哪个程序将 Java 输出捕获为视频

java - 从一个jdialog跳转到另一个jdialog时如何避免闪烁效果

java - 不在 jtable 的列内显示单选按钮组

model-view-controller - 选择具有多个启动项目的配置文件

Java OO MVC 问题

jpa - 如何在 Java SE 中使用持久性 API 来防止不可重复的查询结果?

Java - 无论 JRE 版本如何,查找正在使用的 tzdata 版本