在Netbeans中将逻辑与Jframe文件分开

时间:2016-03-01 23:00:53

标签: java netbeans jframe logic

我试图在同一个包下的另一个类中将逻辑与Jframe分开。但是当我为Jframe conponents添加函数时,例如它在Jframe文件中添加了一个按钮。而且我无法从那里访问逻辑文件中的对象。什么是分离逻辑和图形的正确方法?

1 个答案:

答案 0 :(得分:0)

  你可以更具体一点吗?让我们给它一个背景。假设我只有一个对象Data包含一个int,一个Jframe包含一个按钮,我希望它将1添加到Data。我该如何设置系统?

这基本上描述了一个模型,该模型负责控制逻辑并为其他感兴趣的各方提供所需的功能

所以你可以从简单的合同开始......

public interface DataModel {
    public void add();
    public int getData();
}

然后我会创建一个abstract版本的模型来完成锅炉板的大部分工作......

public abstract class AbstractDataModel implements DataModel {

    private int data;

    public AbstractDataModel(int value) {
        this.data = value;
    }

    public void add(int delta) {
        data += delta;
    }

    @Override
    public int getData() {
        return data;
    }
}

然后允许我创建简单的具体实现......

public class AddByOneDataModel extends AbstractDataModel {

    public AddByOneDataModel(int value) {
        super(value);
    }

    @Override
    public void add() {
        add(1);
    }
}

或者如果你想变得非常懒惰,你可以做......

public class DeltaDataModel extends AbstractDataModel {

    private int delta;

    public DeltaDataModel(int delta, int value) {
        super(value);
        this.delta = delta;
    }

    @Override
    public void add() {
        add(delta);
    }

}

但是,到目前为止,用户界面并未参与其中任何一项,它并不关心,它只需要一个DataModel的实例

然后您的UI可能看起来像......

public class TestPane extends JPanel {

    private DataModel model;
    private JButton add;

    public TestPane() {
        //...
        add = new JButton("Add");
        add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getModel().add();
                int data = getModel().getData();
                // Update the UI in some meaningful way...
            }
        });
        //...
    }

    public void setModel(DataModel model) {
        this.model = model;
    }

    public DataModel getModel() {
        return model;
    }

}

这将允许你做像......这样的事情。

TestPane pane = new TestPane();
pane.setModel(new DeltaDataModel(0, 100));

允许您指定要使用的模型的实际功能(因为谁知道您将来想要做什么)

  

但是我仍然有点混淆视图和控制器部分彼此分离。你可以根据上面的例子解释一下吗?另外,我看到MVC是3个对象所以主要的方法是3个都没有,我是否正确?

How MVC work with java swing GUIJava and GUI - Where do ActionListeners belong according to MVC pattern?Listener Placement Adhering to the Traditional (non-mediator) MVC Pattern及其他关于此主题的其他答案中所述,Swing是MVC的实现,更像是M-VC,其中组件是自我的包含视图和控制器,模型是动态的

这使得尝试包装更传统的MVC变得困难。相反,我们使用视图的概念来处理容器中包含的一系列组件,然后该容器符合某些指定的合同。

在更传统的MVC中,模型和视图不与每个人进行交互,他们对彼此不了解,而是控制器维持关系。

模型...

让我们回去更新我们的模型。为了方便MVC,我们需要为它提供Observer Pattern,因此它可以在更新模型时触发通知(因为模型可以在控制器或视图的后面更新)

public abstract class AbstractDataModel implements DataModel {

    private List<ChangeListener> changeListeners;
    private int data;

    public AbstractDataModel(int value) {
        this.data = value;
        changeListeners = new ArrayList<>(25);
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        changeListeners.add(listener);
    }

    @Override
    public void removeChangeListener(ChangeListener listener) {
        changeListeners.remove(listener);
    }

    protected void fireStateChanged() {
        if (!changeListeners.isEmpty()) {
            ChangeEvent evt = new ChangeEvent(this);
            for (ChangeListener listener : changeListeners) {
                listener.stateChanged(evt);
            }
        }
    }

    public void add(int delta) {
        data += delta;
        fireStateChanged();
    }

    @Override
    public int getData() {
        return data;
    }
}

public class DeltaDataModel extends AbstractDataModel {

    private int delta;

    public DeltaDataModel(int value, int delta) {
        super(value);
        this.delta = delta;
    }

    @Override
    public void add() {
        add(delta);
    }

}

public class AddByOneDataModel extends DeltaDataModel {

    public AddByOneDataModel(int value) {
        super(value, 1);
    }
}

视图...

接下来,让我们看看视图。首先我们定义视图的合同,这确保了控制器只能执行合同所能做的事情。

public interface AddView {
    public static final String ADD_ACTION_COMMAND = "Action.add";
    public void setData(int data);
    public void addActionListener(ActionListener listener);
    public void removeActionListener(ActionListener listener);
}

nb:我可能还想添加一个getComponent方法,该方法返回实现实际使用的实际JComponent,但这将归结为您想要做的事情,并且是在一些其他链接中展示

一个物理实现......

public class AddViewPane extends JPanel implements AddView {

    private JButton btn;
    private JLabel label;

    public AddViewPane() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;

        btn = new JButton("Add");
        label = new JLabel("...");

        add(btn, gbc);
        add(label, gbc);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fireAddAction();
            }
        });
    }

    @Override
    public void setData(int data) {
        label.setText(NumberFormat.getNumberInstance().format(data));
    }

    @Override
    public void addActionListener(ActionListener listener) {
        listenerList.add(ActionListener.class, listener);
    }

    @Override
    public void removeActionListener(ActionListener listener) {
        listenerList.remove(ActionListener.class, listener);
    }

    protected void fireAddAction() {
        ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
        if (listeners.length > 0) {
            ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ADD_ACTION_COMMAND);
            for (ActionListener listener : listeners) {
                listener.actionPerformed(evt);
            }
        }
    }

}

控制器...

再次,从最低级别开始并构建功能

public interface AddController {
    public DataModel getModel();
    public AddView getView();
}

public class AbstractAddController implements AddController {

    private AddView view;
    private DataModel model;

    public AbstractAddController(AddView view, DataModel model) {
        this.view = view;
        this.model = model;

        view.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getModel().add();
            }
        });

        model.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                getView().setData(getModel().getData());
            }
        });
    }

    @Override
    public DataModel getModel() {
        return model;
    }

    @Override
    public AddView getView() {
        return view;
    }

}

public class DefaultAddController extends AbstractAddController {

    public DefaultAddController(AddView view, DataModel model) {
        super(view, model);
    }

}

把它放在一起......

最后,你可以使用像...这样的东西。

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }

        DataModel model = new AddByOneDataModel(0);
        AddViewPane view = new AddViewPane();
        DefaultAddController controller = new DefaultAddController(view, model);

        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // This is where having a getComponent method in
        // view interface would be helpful      
        frame.add(view);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
});

把它们放在一起