如何在多个类中使用 swing

发布于 2024-11-08 23:07:00 字数 92 浏览 0 评论 0原文

我只是想了解一些关于秋千的事情 1)如何在swing中使用MVC模式? 2)假设我有一个主窗口,我需要将菜单作为单独的类,将所有组件作为单独的类,这将是集成它的最佳方法

I just want to know some thing about the swing
1) How to use MVC model in swing?
2)Say i Have an Main window and i need to do the menu as separate class ,all the component as separate class and .which will be the best method to integrate it

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

卷耳 2024-11-15 23:07:00

好吧,这就是所谓的过度回答,对此感到抱歉,但这是我编写的一个简单示例,它尝试使用简单的 MVC 模式来完成一件微不足道的事情:按下按钮并更改 JTextField 中的文本。这是多余的,因为您只需几行代码就可以完成同样的事情,但它确实说明了单独文件中的一些 MVC 以及模型如何控制状态。如果有任何令人困惑的地方,请提问!

将所有内容组合在一起并开始工作的主类:

import javax.swing.*;

public class SwingMvcTest {
   private static void createAndShowUI() {

      // create the model/view/control and connect them together
      MvcModel model = new MvcModel();
      MvcView view = new MvcView(model);
      MvcControl control = new MvcControl(model);
      view.setGuiControl(control);

      // EDIT: added menu capability
      McvMenu menu = new McvMenu(control);

      // create the GUI to display the view
      JFrame frame = new JFrame("MVC");
      frame.getContentPane().add(view.getMainPanel()); // add view here
      frame.setJMenuBar(menu.getMenuBar()); // edit: added menu capability
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   // call Swing code in a thread-safe manner per the tutorials
   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

视图类:

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;

public class MvcView {
   private MvcControl control;
   private JTextField stateField = new JTextField(10);
   private JPanel mainPanel = new JPanel(); // holds the main GUI and its components

   public MvcView(MvcModel model) {
      // add a property change listener to the model to listen and 
      // respond to changes in the model's state
      model.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            // if the state change is the one we're interested in...
            if (evt.getPropertyName().equals(MvcModel.STATE_PROP_NAME)) {
               stateField.setText(evt.getNewValue().toString()); // show it in the GUI
            }
         }
      });
      JButton startButton = new JButton("Start");
      startButton.addActionListener(new ActionListener() {
         // all the buttons do is call methods of the control
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.startButtonActionPerformed(e); // e.g., here
            }
         }
      });
      JButton endButton = new JButton("End");
      endButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.endButtonActionPerformed(e); // e.g., and here
            }
         }
      });

      // make our GUI pretty
      int gap = 10;
      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, gap, 0));
      buttonPanel.add(startButton);
      buttonPanel.add(endButton);

      JPanel statePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
      statePanel.add(new JLabel("State:"));
      statePanel.add(Box.createHorizontalStrut(gap));
      statePanel.add(stateField);

      mainPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
      mainPanel.setLayout(new BorderLayout(gap, gap));
      mainPanel.add(buttonPanel, BorderLayout.CENTER);
      mainPanel.add(statePanel, BorderLayout.PAGE_END);
   }

   // set the control for this view
   public void setGuiControl(MvcControl control) {
      this.control = control;
   }

   // get the main gui and its components for display
   public JComponent getMainPanel() {
      return mainPanel;
   }

}

Control:

import java.awt.event.ActionEvent;

public class MvcControl {
   private MvcModel model;

   public MvcControl(MvcModel model) {
      this.model = model;
   }

   // all this simplistic control does is change the state of the model, that's it
   public void startButtonActionPerformed(ActionEvent ae) {
      model.setState(State.START);
   }

   public void endButtonActionPerformed(ActionEvent ae) {
      model.setState(State.END);
   }
}

该模型使用 PropertyChangeSupport 对象来允许其他对象(在这种情况下为 View)侦听状态更改。所以模型实际上是我们的“可观察的”,而视图是“观察者”

import java.beans.*;

public class MvcModel {
   public static final String STATE_PROP_NAME = "State";
   private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
   private State state = State.NO_STATE;

   public void setState(State state) {
      State oldState = this.state;
      this.state = state;
      // notify all listeners that the state property has changed
      pcSupport.firePropertyChange(STATE_PROP_NAME, oldState, state);
   }

   public State getState() {
      return state;
   }

   public String getStateText() {
      return state.getText();
   }

   // allow addition of listeners or observers
   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

}

一个简单的枚举,状态,来封装状态的概念:

public enum State {
   NO_STATE("No State"), START("Start"), END("End");
   private String text;

   private State(String text) {
      this.text = text;
   }

   @Override
   public String toString() {
      return text;
   }

   public String getText() {
      return text;
   }
}

编辑:我也看到你提到了菜单,所以我添加了菜单支持添加此类并在 SwingMcvTest 类中添加几行。请注意,由于代码分离,对 GUI 进行此更改非常简单,因为菜单所需要做的就是调用控制方法。它不需要了解模型或视图:

import java.awt.event.ActionEvent;
import javax.swing.*;

public class McvMenu {
   private JMenuBar menuBar = new JMenuBar();
   private MvcControl control;

   @SuppressWarnings("serial")
   public McvMenu(MvcControl cntrl) {
      this.control = cntrl;

      JMenu menu = new JMenu("Change State");
      menu.add(new JMenuItem(new AbstractAction("Start") {
         public void actionPerformed(ActionEvent ae) {
            if (control != null) {
               control.startButtonActionPerformed(ae);
            }
         }
      }));
      menu.add(new JMenuItem(new AbstractAction("End") {
         public void actionPerformed(ActionEvent ae) {
            if (control != null) {
               control.endButtonActionPerformed(ae);
            }
         }
      }));

      menuBar.add(menu);
   }

   public JMenuBar getMenuBar() {
      return menuBar;
   }
}

上帝啊,做一些琐碎的事情需要很多代码!我提名我自己和我的代码参加本周的 stackoverflow Rube Goldberg 奖。

OK, this is called answering with overkill, so sorry about that, but here's a quick example I've whipped up that tries to use a simple MVC pattern to do a trivial thing: press a button and change the text in a JTextField. It's overkill because you could do the same thing in just a few lines of code, but it does illustrate some MVC in separate files and how the model controls the State. Please ask questions if anything is confusing!

The main class that puts all together and gets things started:

import javax.swing.*;

public class SwingMvcTest {
   private static void createAndShowUI() {

      // create the model/view/control and connect them together
      MvcModel model = new MvcModel();
      MvcView view = new MvcView(model);
      MvcControl control = new MvcControl(model);
      view.setGuiControl(control);

      // EDIT: added menu capability
      McvMenu menu = new McvMenu(control);

      // create the GUI to display the view
      JFrame frame = new JFrame("MVC");
      frame.getContentPane().add(view.getMainPanel()); // add view here
      frame.setJMenuBar(menu.getMenuBar()); // edit: added menu capability
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   // call Swing code in a thread-safe manner per the tutorials
   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

The view class:

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;

public class MvcView {
   private MvcControl control;
   private JTextField stateField = new JTextField(10);
   private JPanel mainPanel = new JPanel(); // holds the main GUI and its components

   public MvcView(MvcModel model) {
      // add a property change listener to the model to listen and 
      // respond to changes in the model's state
      model.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            // if the state change is the one we're interested in...
            if (evt.getPropertyName().equals(MvcModel.STATE_PROP_NAME)) {
               stateField.setText(evt.getNewValue().toString()); // show it in the GUI
            }
         }
      });
      JButton startButton = new JButton("Start");
      startButton.addActionListener(new ActionListener() {
         // all the buttons do is call methods of the control
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.startButtonActionPerformed(e); // e.g., here
            }
         }
      });
      JButton endButton = new JButton("End");
      endButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.endButtonActionPerformed(e); // e.g., and here
            }
         }
      });

      // make our GUI pretty
      int gap = 10;
      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, gap, 0));
      buttonPanel.add(startButton);
      buttonPanel.add(endButton);

      JPanel statePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
      statePanel.add(new JLabel("State:"));
      statePanel.add(Box.createHorizontalStrut(gap));
      statePanel.add(stateField);

      mainPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
      mainPanel.setLayout(new BorderLayout(gap, gap));
      mainPanel.add(buttonPanel, BorderLayout.CENTER);
      mainPanel.add(statePanel, BorderLayout.PAGE_END);
   }

   // set the control for this view
   public void setGuiControl(MvcControl control) {
      this.control = control;
   }

   // get the main gui and its components for display
   public JComponent getMainPanel() {
      return mainPanel;
   }

}

The Control:

import java.awt.event.ActionEvent;

public class MvcControl {
   private MvcModel model;

   public MvcControl(MvcModel model) {
      this.model = model;
   }

   // all this simplistic control does is change the state of the model, that's it
   public void startButtonActionPerformed(ActionEvent ae) {
      model.setState(State.START);
   }

   public void endButtonActionPerformed(ActionEvent ae) {
      model.setState(State.END);
   }
}

The model uses a PropertyChangeSupport object to allow other objects (in this situation the View) to listen for changes in state. So the model is in effect our "observable" while the view is the "observer"

import java.beans.*;

public class MvcModel {
   public static final String STATE_PROP_NAME = "State";
   private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
   private State state = State.NO_STATE;

   public void setState(State state) {
      State oldState = this.state;
      this.state = state;
      // notify all listeners that the state property has changed
      pcSupport.firePropertyChange(STATE_PROP_NAME, oldState, state);
   }

   public State getState() {
      return state;
   }

   public String getStateText() {
      return state.getText();
   }

   // allow addition of listeners or observers
   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

}

A simple enum, State, to encapsulate the concept of state:

public enum State {
   NO_STATE("No State"), START("Start"), END("End");
   private String text;

   private State(String text) {
      this.text = text;
   }

   @Override
   public String toString() {
      return text;
   }

   public String getText() {
      return text;
   }
}

edit: I see you mentioned menu as well, so I've added menu support with the addition of this class and the addition of several lines in the SwingMcvTest class. Note that because of separation of code, it was trivial to make this change to the GUI since all the menu needs to do is call control methods. It needs to know nothing of the model or the view:

import java.awt.event.ActionEvent;
import javax.swing.*;

public class McvMenu {
   private JMenuBar menuBar = new JMenuBar();
   private MvcControl control;

   @SuppressWarnings("serial")
   public McvMenu(MvcControl cntrl) {
      this.control = cntrl;

      JMenu menu = new JMenu("Change State");
      menu.add(new JMenuItem(new AbstractAction("Start") {
         public void actionPerformed(ActionEvent ae) {
            if (control != null) {
               control.startButtonActionPerformed(ae);
            }
         }
      }));
      menu.add(new JMenuItem(new AbstractAction("End") {
         public void actionPerformed(ActionEvent ae) {
            if (control != null) {
               control.endButtonActionPerformed(ae);
            }
         }
      }));

      menuBar.add(menu);
   }

   public JMenuBar getMenuBar() {
      return menuBar;
   }
}

God that's a lot of code to do a trivial bit of chit! I nominate myself and my code for this week's stackoverflow Rube Goldberg award.

绾颜 2024-11-15 23:07:00

Swing 具有简化 MVC 实现的内置机制。它有行动框架。
负责构建视图的类应该关心 JComponent 子类的实例化并将它们放置到面板上。每个对用户活动做出反应的组件都应该有相应的操作 (b.setAction(myAction))。
我通常创建包 com.myapp.actions 并将所有操作放在那里。有时我也会创建抽象动作,但它是特定于应用程序的。操作允许您将逻辑与表示层分开。将行动视为“模型”的入口点。

典型的应用程序具有比操作更多的控件。某些控件重复使用相同的操作。例如,您可以通过键入 Ctrl-S、单击菜单项或工具栏按钮、使用上下文菜单等来保存文件。但所有这些控件都将调用相同的操作 SaveFileAction

关于你的第二个问题,有两种不同的方法。首先是基于继承。有人在需要框架时扩展 JFrame 并将所有布局实现到这个特殊的类中。

其他方法是创建一组生成布局的实用方法。我个人比较喜欢这个。我认为如果您确实需要某个东西的子类,例如当您希望重写超类方法之一(例如 paint())时,应该使用继承,

我希望我的描述有所帮助。祝你好运。

Swing has build in mechanism that simplifies MVC implementation. It has Actions framework.
Class that is responsible on building view should care about instantiation of the JComponent subclasses and placing them onto panels. Each component that should react on the user's activity should have corresponding Action (b.setAction(myAction)).
I typically create package com.myapp.actions and put all actions there. Sometimes I create abstract action as well but it is application specific. Actions allow you to separate the logic from presentation layer. Think about action as a entry point to "Model".

Typical application has more controls than actions. Some controls reuse the same action. For example you can save file by typing Ctrl-S, clicking menu item or toolbar button, using context menu etc. But all theses controls will invoke the same action SaveFileAction.

Concerning to your second question there are 2 different ways. First is based on inheritance. There are people that extend JFrame when they need frame and implement all layout into this special class.

Other approach is to create a set of utility methods that generate the layout. I personally prefer this one. I think that inheritance should be used if you really need a subclass of something for example when you wish to override one of super class methods (e.g. paint())

I hope my description helps. Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文