当前位置: 首页 > 知识库问答 >
问题:

MVC如何使用java swing GUI

逄俊贤
2023-03-14

假设我有一个swing GUI,它有textfeild和button。当我单击按钮时,我希望将该值保存在db中的文本中,并返回joptionpane“成功”消息。
我使用的方法是
Model:JDBC class
View:GUI:在按钮的“action performed”操作中,我使用参数调用save方法。

   Controller con = new Controller();
   con.save(text1.getText());

控制器:编写保存方法。

   JDBC db = new                             
   public void save(jTextfeild text){     
   text= text1.getText();
   boolean b= db.putData("insert into .. values(text)");
   if(b){
   JOptionPane("Success"); 
   }
 }


我就是这样开始的。但后来我明白这不应该是这样的,这是完全不安全和愚蠢的。
我非常想学习如何在MVC中正确地做到这一点。请用一个小例子来解释这一点。谢谢你抽出时间。

共有1个答案

米景辉
2023-03-14

在像Swing这样的东西中,这是一个很难理解的主题,它已经使用了MVC的一种形式,尽管更像VC-M,在VC-M中,模型与视图和控制器分离,但视图和控制器结合在一起。

考虑一下JButton,您没有提供控制器来管理当用户按下某个键或用鼠标单击它时如何触发它,这是在内部完成的,并且在发生时通知您有关操作。

考虑到这一点,您需要允许视图是半自管理的。例如,根据您的需求,视图将有一个按钮和文本字段。

视图本身将管理用户与按钮本身之间的交互(例如维护内部的ActionListener),但随后将向控制器提供关于控制器可能感兴趣的任何状态更改的通知。

在更纯粹的MVC意义上,视图和模型彼此不了解,而控制器将管理它们。这与Swing的工作方式有点矛盾,因为Swing允许您将模型直接传递给视图,查看任何Swing组件。

这并不意味着你不能让事情运转起来,而是你需要知道这个概念在哪里可以摇摇欲坠,或者需要“按摩”才能更好地运转。

通常情况下,当我接近这类事物时,我会后退一步,看看更广阔的图景,例如。

  • 您的视图可以接受文本并生成文本或对其进行更改
  • 您有一个可以加载和修改文本的模型,但很少提供其他事件
  • 您有一个控制器,它希望从模型中获取文本并将其提供给视图,监视视图对文本的更改并在模型中更新它们

现在,MVC在“代码到接口(而不是实现)”的概念下工作得很好,在这种程度上,我倾向于从契约开始。

public interface TextView {

    public void setText(String text);
    public String getText();
    public void addTextViewObserver(TextViewObserver observer);
    public void removeTextViewObserver(TextViewObserver observer);

}

public interface TextViewObserver {
    public void textWasChanged(TextView view);
}

现在,视图的一个要求是在文本以某种有意义的方式发生变化时生成事件,为此,我使用了一个简单的观察者模式来实现。现在,您可以认为控制器是观察者,但在我看来,控制器可能具有我不想向视图公开的功能(例如模型)

接下来是模型...

public interface TextModel {
    public String getText();
    public void setText(String text);
}

真的很简单。现在,您可以考虑向这些方法中添加某种exception以允许模型由于某种原因而失败,但是exception应该尽可能通用(或者甚至是自定义的exception),以便在需要时替换实现

最后,控制器...

public interface TextViewController {

    public TextView getTextView();
    public TextModel getTextModel();

}

再一次,很简单。您可能对控制器有更复杂的要求,但对于本例,这是我们真正需要的全部。

public class TextViewPane extends JPanel implements TextView {

    private JTextField textField;
    private JButton updateButton;
    private List<TextViewObserver> observers;

    public TextViewPane() {
        observers = new ArrayList<>(25);
        textField = new JTextField(25);
        updateButton = new JButton("Update");
        updateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fireTextWasChanged();
            }
        });

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        add(textField, gbc);
        add(updateButton, gbc);
    }

    @Override
    public void setText(String text) {
        textField.setText(text);
    }

    @Override
    public String getText() {
        return textField.getText();
    }

    @Override
    public void addTextViewObserver(TextViewObserver observer) {
        observers.add(observer);
    }

    @Override
    public void removeTextViewObserver(TextViewObserver observer) {
        observers.remove(observer);
    }

    protected void fireTextWasChanged() {
        for (TextViewObserver observer : observers) {
            observer.textWasChanged(this);
        }
    }

}
public class SimpleTextModel implements TextModel {

    private String text = "This is some text";

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

    @Override
    public void setText(String text) {
        this.text = text;
    }

}
public class SimpleTextController implements TextViewController, TextViewObserver {

    private TextView view;
    private TextModel model;

    public SimpleTextController(TextView view, TextModel model) {
        this.view = Objects.requireNonNull(view, "TextView can not null");
        this.model = Objects.requireNonNull(model, "TextModel can not be null");
        view.addTextViewObserver(this);
    }

    @Override
    public TextView getTextView() {
        return view;
    }

    @Override
    public TextModel getTextModel() {
        return model;
    }

    @Override
    public void textWasChanged(TextView view) {
        getTextModel().setText(view.getText());
    }
}
TextViewPane view = new TextViewPane();
TextModel model = new SimpleTextModel();
TextViewController controller = new SimpleTextController(view, model);

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

现在,这一切只是一个可能解决方案的例子。例如,您可以有一个控制器实现,它具有模型或视图的特定实现,或者同时具有模型或视图的特定实现。

关键是,你不应该在乎。控制器并不关心视图是如何实现的,它只关心它会生成textwaschanged事件。模型根本不关心视图(反之亦然),控制器也不关心模型,只关心它将获取和设置一些文本。

对于更复杂的示例,您可以看一下Java和GUI--根据MVC模式,ActionListeners属于哪里?

  • 这只是解决问题的一种可能方法。例如,您可以将视图限制为单个观察者。
  • 您应该一直在想“我可以更改MVC的任何一部分吗?它还能工作吗?”这使您考虑更改实现的任何一部分可能会对周围的合同产生的问题。您应该了解到,如何实现每一层并不重要
  • 视图可以充当另一个子视图的控制器(或充当子视图的另一控制器的容器)。这有时会让人害怕,但视图可以充当一个或多个子控制器/视图的父容器,这允许您开发复杂的UI
  • 不要在合同中公开实现细节,例如,模型不应该抛出SQLException,因为另一个实现可能不是基于SQL的解决方案。不要公开UI元素,这意味着所有实现都需要实现这些元素。如果我想要一个视图的实现,该视图向用户呈现JComboBox而不是JTextField会发生什么?这也是我不在视图协定中使用ActionListener的原因,因为我不知道视图的实现实际上是如何生成TextWasChanged事件的
 类似资料:
  • 问题内容: 我一直在研究将JasperReports(6.0.0)与Spring MVC(4.1.3)结合使用以生成PDF报告。Spring充斥着与JasperReports集成以生成PDF的“特定于Spring”的方式: 使用 依赖于现已弃用的JasperReport功能 __ 采用 采用 我很难在网上找到好的完整示例,并想分享我的发现。 随意添加与“如何将JasperReports与Sprin

  • 如何使用 MVC 模式 首先,你需要确定你的项目中的每个类都是三大基本类型中的一种:控制器、模型、视图。不要在一个类里糅合多个角色。目前我们创建了 Album 类和 AlbumView 类是符合要求的,做得很好。 然后,为了确保你遵循这种模式,你最好创建三个项目分组来存放代码,分别是 Model、View、Controller,保持每个类型的文件分别独立。 接下来把 Album.swift 拖到

  • 问题内容: 是否可以将ASP.NET MVC 2设置为与MySQL数据库一起使用? 问题答案: 我假设您具有Visual Studio Professional 2008,可以访问MySQL服务器的实例,并且具有中级到高级的开发经验。这可能与VS2008 Web版一起使用,但不能完全确定。 如果尚未安装,请安装适用于.NET的MySQL Connector(在撰写本文时为6.2.2.0) 可选:安

  • 问题内容: 我正在研究一个新的ASP.NET MVC和AngularJS应用程序,该应用程序旨在作为SPA的集合。我使用MVC区域概念来分隔每个单独的SPA,然后在每个MVC区域内使用AngularJS创建SPA。 由于我是AngularJS的新手,并且无法找到有关结合MVC和AngularJS路由的答案,因此我想在这里发表我的问题,以查看是否可以获得帮助。 我有标准的MVC路由设置,可用于每个M

  • 您好,我正在从事一个spring mvc项目,我想使用FreeMarker作为我的模板引擎,我在使用宏时遇到了问题,我想创建一个母版页或布局(页脚、页眉和菜单),我可以在其他页面中使用,到目前为止,我正在做一个简单的示例,说明如何操作,但我无法让它工作,我在宏中输入的内容没有显示我的FreeMarker版本是2.3.21。 以下是我的freemarker java类配置: 我正在将宏保存为。类似于

  • MVC 我们已经可以用koa处理不同的URL,还可以用Nunjucks渲染模板。现在,是时候把这两者结合起来了! 当用户通过浏览器请求一个URL时,koa将调用某个异步函数处理该URL。在这个异步函数内部,我们用一行代码: ctx.render('home.html', { name: 'Michael' }); 通过Nunjucks把数据用指定的模板渲染成HTML,然后输出给浏览器,用户就可以