【发布时间】:2016-01-27 08:22:32
【问题描述】:
我正在学习高级 Java 并尝试编写一个利用 MVC 设计模式的程序。该程序需要绘制一个字符串,该字符串可以通过用户在JTextField 中的输入进行修改。用户还可以通过JComboBox和JSpinner分别调整文字的颜色和字体大小。
这是我目前所拥有的:
public class MVCDemo extends JApplet {
private JButton jBtnController = new JButton("Show Controller");
private JButton jBtnView = new JButton("Show View");
private TextModel model = new TextModel();
//constructor
public MVCDemo(){
//set layout and add buttons
setLayout(new FlowLayout());
add(jBtnController);
add(jBtnView);
jBtnController.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
JFrame frame = new JFrame("Controllor");
TextController controller = new TextController();
controller.setModel(model);
frame.add(controller);
frame.setSize(200, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
jBtnView.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
JFrame frame = new JFrame("View");
TextView view = new TextView();
view.setModel(model);
frame.add(view);
frame.setSize(500, 200);
frame.setLocation(200, 200);
frame.setVisible(true);
}
});
}
public static void main(String[] args){
MVCDemo applet = new MVCDemo();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("MVCDemo");
frame.getContentPane().add(applet, BorderLayout.CENTER);
frame.setSize(400, 90);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
public class TextModel {
private String text = "Your Student ID #";
//utility field used by event firing mechanism
private ArrayList<ActionListener> actionListenerList;
public void setText(String text){
this.text = text;
//notify the listener for the change on text
processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "text"));
}
public String getText(){
return text;
}
//register an action event listener
public synchronized void addActionListener(ActionListener l){
if (actionListenerList == null)
actionListenerList = new ArrayList<ActionListener>();
}
//remove an action event listener
public synchronized void removeActionListener(ActionListener l){
if (actionListenerList != null && actionListenerList.contains(l))
actionListenerList.remove(l);
}
//fire TickEvent
private void processEvent(ActionEvent e){
ArrayList<ActionListener> list;
synchronized (this){
if (actionListenerList == null)
return;
list = (ArrayList<ActionListener>)(actionListenerList.clone());
}
}
}
public class TextView extends JPanel{
private TextModel model;
//set a model
public void setModel(TextModel model){
this.model = model;
if (model != null)
//register the view as listener for the model
model.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
repaint();
}
});
}
public TextModel getModel(){
return model;
}
@Override
public void paintComponent(Graphics g){
if (model != null){
super.paintComponent(g);
//g.setColor(model.getColor());
g.drawString(model.getText(), 190, 90);
}
}
}
public class TextController extends JPanel {
String[] colorStrings = { "Black", "Blue", "Red" };
private TextModel model;
private JTextField jtfText = new JTextField();
private JComboBox jcboColorList = new JComboBox(colorStrings);
//constructor
public TextController(){
//panel to group labels
JPanel panel1 = new JPanel();
panel1.setLayout(new GridLayout(3, 1));
panel1.add(new JLabel("Text"));
panel1.add(new JLabel("Color"));
panel1.add(new JLabel("Size"));
//panel to group text field, combo box and spinner
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(3, 1));
panel2.add(jtfText);
panel2.add(jcboColorList);
setLayout(new BorderLayout());
add(panel1, BorderLayout.WEST);
add(panel2, BorderLayout.CENTER);
//register listeners
jtfText.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if (model != null)
model.setText(jtfText.getText());
}
});
/*jcboColorList.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if (model != null)
model.set
}
});*/
}
public void setModel(TextModel model){
this.model = model;
}
public TextModel getModel(){
return model;
}
}
目前我只实现了JTextField 组件(还没有弄清楚如何正确执行JComboBox 和JSpinner),即使这样也不是完美的。
当我第一次启动程序并打开视图和控制器面板时,默认字符串“您的学生 ID #”在视图中正确显示。但是当我在JTextField 中输入其他字符串并按回车键时,TextView 中的输出字符串不会更新,除非我关闭视图面板并重新打开它。有人可以指出导致这种行为的原因吗?
我怀疑这可能与我程序的事件处理部分有关。但是我对 GUI 编程还是很陌生,并且对事件的触发和处理方式有非常基本的了解。因此,如果有人能以对初学者友好的方式解释问题的根本原因,我将不胜感激。
【问题讨论】:
-
你混合你的层,模型和控制器都是非视觉实体。我在我的手机里,所以我没有深入检查你的代码,但是,当值发生变化时,你的视图应该通知控制器(直接或直接),控制器将相应地更新模型,这将通知控制器哪个将进一步通知视图
标签: java swing user-interface model-view-controller event-handling