2

我有我的自定义组件,它在我的自定义数据类中保存它的数据。我的组件extends JComponent,而数据是完全自定义的。

数据类可以通知组件它已更改的常规模式是什么?我是否应该在数据类中实现一些事件并在设置数据时让组件订阅它?或者有预定义的模式是 Swing 库?

例如,我正在查看ListModel<E>interface 并看到它只是 hasaddListDataListener(ListDataListener l)removeListDataListener(ListDataListener l). 这是机制模型通知的List吗?

4

2 回答 2

4

作为记录,这主要是我的个人意见(因为这更多是一个意见问题)。

通常对于 Swing 应用程序,最好将代码分离到模型/视图/控制 (MVC) 中。这意味着实际的 Swing 组件是您的 Viow,您的侦听器是您的控件,而您实际执行操作的代码是模型。在这种情况下,您的视图和模型都只知道控件(并且控件知道视图和模型)。

因此,如果您的模型更新 - 它会通知控件,它会更新视图。视图也是如此(视图中的侦听器执行,通知控制,控制更新模型)。

这样做的好处是它松散地耦合了视图和模型(视图只关心向用户展示东西,模型只关心数据,他们不关心彼此在做什么,只要他们获取正确的信息)。

这是一个示例(为简单起见,它们都在一个文件中,但通常您至少每个 MVC 都在它们自己的文件中):

import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;

public class MVCSeparation {

    // Model:  (Number crunching math-y) or (data processing) stuff
    public static class Model{
        ArrayList<String> data = new ArrayList<String>();
        public void addData(String value){
            data.add(value);
        }

        public int getCount(){
            return data.size();
        }

        public String randomValue(){
            String result = "";
            if(data.size() > 0){
                int index = (int)(Math.random() * data.size());
                System.out.println(index);
                result = data.get(index);
            }
            System.out.println("Getting Value: " + result);
            return result;
        }
    }

    // View:  Pretty graphics and visuals
    public static class View extends Box{
        JLabel text = new JLabel("Random Value:");
        JTextField newItem = new JTextField(10);
        JButton submit = new JButton("Submit");

        public View(){
            super(BoxLayout.Y_AXIS);
            add(text);
            add(newItem);
            add(submit);
        }

        public void setSubmitAction(ActionListener submitAction){
            submit.addActionListener(submitAction);
        }

        public void setDisplayText(String value){
            text.setText("Random Value: " + value);
        }

        public String getText(){
            String result = newItem.getText();
            newItem.setText("");
            return result;
        }

        public void startupApp(){
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setContentPane(this);
            frame.validate();
            frame.pack();
            frame.setVisible(true);
        }
    }

    // Processing User Interactions and Data Updates (links two above together)
    public static class Control{
        Model m = new Model();
        View v = new View();

        public Control(){
            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {
                    v.setSubmitAction(new SubmitText());
                    v.startupApp();
                }});

            //Randomly update label
            while(true){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                SwingUtilities.invokeLater(new Runnable(){
                    @Override
                    public void run() {
                        v.setDisplayText(m.randomValue());
                    }});
            }
        }

        // Listener to notify us of user interactions on the View
        public class SubmitText implements ActionListener{
            @Override
            public void actionPerformed(ActionEvent e) {
                m.addData(v.getText());
            }
        }
    }


    public static void main(String[] args) {
        new Control();
    }
}
于 2012-12-19T19:15:03.267 回答
2

您可以使用ObservablePropertyChangeListener

于 2012-12-19T13:39:13.613 回答