【问题标题】:Java - implementing mvcJava - 实现 mvc
【发布时间】:2012-01-03 02:27:01
【问题描述】:

我刚开始使用 MVC 模式编写 Java Swing 应用程序,到目前为止,我发现它大大简化了我的工作并解决了很多问题。现在我有几个问题困扰我或现在不知道如何解决:

这是我的用户界面视图:

package env.view;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import net.miginfocom.swing.MigLayout;

import env.helper.*;

public class UI_View extends JFrame
{

    private JPanel left         = new JPanel(new MigLayout());
    private JPanel center       = new JPanel(new MigLayout());
    private JPanel right        = new JPanel(new MigLayout());

    //LEFT PANEL
    private Tower_Helper towers = new Tower_Helper();
    private Tree_Helper modules = new Tree_Helper();
    private JScrollPane mod_bar = new JScrollPane(modules);

    //CENTER PANEL
    private Browse_Helper browser = new Browse_Helper();
    private JScrollPane   browser_bar = new JScrollPane(browser);

    //RIGHT PANEL - LABELS
    private JLabel tower_name = new JLabel("No tower selected");
    private JLabel shield     = new JLabel("0");
    private JLabel armor      = new JLabel("0");
    private JLabel em         = new JLabel("0.0");
    private JLabel th         = new JLabel("0.0");
    private JLabel kn         = new JLabel("0.0");
    private JLabel ex         = new JLabel("0.0");

    //RIGHT PANEL - CONTROLLS
    private JProgressBar cap_bar    = new JProgressBar();
    private JProgressBar cpu_bar    = new JProgressBar();
    private int total   = 0;
    private int consumed    = 0;

    public UI_View()
    {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setMinimumSize(new Dimension(800, 600));
        this.setExtendedState(JFrame.MAXIMIZED_BOTH);
        this.setTitle("Environment Prototype");
        this.setLayout(new MigLayout());

        left.setMinimumSize(new Dimension(252, 540));
        left.setMaximumSize(new Dimension(252, 37500));
        left.add(towers, "growx, pushx, wrap");
        left.add(mod_bar,"grow, push");

        center.setMinimumSize(new Dimension(298, 540));
        center.add(browser_bar, "grow, push");

        right.setMinimumSize(new Dimension(250, 540));
        right.setMaximumSize(new Dimension(250, 37500));
        tower_name.setToolTipText("Double click to remove tower if modules have been removed.");
        right.add(tower_name, "span, wrap");

        right.add(new JLabel(""), "wrap, span");
        right.add(new JLabel(""), "wrap, span");

        right.add(new JLabel("Capacitor"), "wrap, span");
        cap_bar.setMinimumSize(new Dimension(215, 40));
        right.add(cap_bar, "wrap, span");

        right.add(new JLabel("CPU"), "wrap, span");
        cpu_bar.setMinimumSize(new Dimension(215, 40));
        right.add(cpu_bar, "wrap, span");

        right.add(new JLabel("Shield:  "));
        right.add(shield, "wrap");

        right.add(new JLabel("Armor:  "));
        right.add(armor, "wrap");

        right.add(new JLabel(""), "wrap, span");
        right.add(new JLabel(""), "wrap, span");

        right.add(new JLabel("EM:  "));
        right.add(em, "wrap");

        right.add(new JLabel("TH:  "));
        right.add(th, "wrap");

        right.add(new JLabel("KN:  "));
        right.add(kn, "wrap");

        right.add(new JLabel("EX:  "));
        right.add(ex, "wrap");

        this.add(left, "dock west");
        this.add(center, "dock center");
        this.add(right, "dock east");
    }

    //getter - JLabel tower name
    public JLabel getTowerNameLabel()
    {
        return this.tower_name;
    }

    //listener - JLabel tower name
    public void towerLabelListner(MouseListener event)
    {
        this.tower_name.addMouseListener(event);
    }

    //getter - JList browser
    public JList getBrowserList()
    {
        return this.browser;
    }

    //listener - JList browser
    public void browserListListener(MouseListener event)
    {
        this.browser.addMouseListener(event);
    }

    //getter - JTree modules
    public JTree getModuleTree()
    {
        return this.modules;
    }

    //listener - JTree modules
    public void modulesTreeListener(MouseListener event)
    {
        this.modules.addMouseListener(event);
    }

    //getter - JComboBox towers
    public JComboBox getTowers()
    {
        return this.towers;
    }

    //lisetner - JComboBox towers
    public void towersBoxListener(ActionListener evnet)
    {
        this.towers.addActionListener(evnet);
    }

}

这是我的 UI 控制器

package env.controller;

import env.model.UI_Model;
import env.view.UI_View;
import java.awt.event.*;

import javax.swing.*;

public class UI_Controller
{    
    private UI_Model ui_model;
    private UI_View  ui_view;

    public UI_Controller(UI_Model model, UI_View view)
    {
        ui_model = model;
        ui_view  = view;

        ui_view.towersBoxListener(new towerSelectionListener());
        ui_view.modulesTreeListener(new modulesSelectionListener());
        ui_view.browserListListener(new browserSelectionListener());
        ui_view.towerLabelListner(new towerRemovalListener());
    }

    class towerRemovalListener implements MouseListener
    {
        @Override public void mouseClicked(MouseEvent e) 
        {
            if(e.getClickCount() == 2 && ui_model.getModulesCounter() == 0)
            {
                ui_view.getTowerNameLabel().setText(ui_model.reset_label());
                ui_model.retsetSelectionInfo();
            } else if (ui_model.getModulesCounter() != 0){
                JFrame dialog = new JFrame();
                JOptionPane.showMessageDialog(dialog, "Cannot remove tower whit modules still selected.",
                "Cannot remove tower !", JOptionPane.WARNING_MESSAGE);
            }
        }
        @Override public void mousePressed(MouseEvent e) {}
        @Override public void mouseReleased(MouseEvent e) {}
        @Override public void mouseEntered(MouseEvent e) {}
        @Override public void mouseExited(MouseEvent e) {}
    }

    class browserSelectionListener implements MouseListener
    {
        @Override public void mouseClicked(MouseEvent e) 
        {
            if(e.getClickCount() == 2)
            {
                String selection = ui_view.getBrowserList().getSelectedValue().toString();
                ui_model.removeFromList(selection);
                ui_view.getBrowserList().setModel(ui_model.getSelectedModules());
            }
        }
        @Override public void mousePressed(MouseEvent e) {}
        @Override public void mouseReleased(MouseEvent e) {}
        @Override public void mouseEntered(MouseEvent e) {}
        @Override public void mouseExited(MouseEvent e) {}
    }

    class modulesSelectionListener implements MouseListener
    {
        @Override public void mouseClicked(MouseEvent e) 
        {
            if(e.getClickCount() == 2 && ui_model.getSelectionInfo() != null)
            {
                String output = ui_view.getModuleTree().getLastSelectedPathComponent().toString();
                ui_model.addToList(output);
                ui_view.getBrowserList().setModel(ui_model.getSelectedModules());
            }
        }
        @Override public void mousePressed(MouseEvent e) {}
        @Override public void mouseReleased(MouseEvent e) {}
        @Override public void mouseEntered(MouseEvent e) {}
        @Override public void mouseExited(MouseEvent e) {}
    }

    class towerSelectionListener implements ActionListener
    {
        @Override public void actionPerformed(ActionEvent e) 
        {
            String output   = ui_view.getTowers().getSelectedItem().toString();
            if(ui_model.getSelectionInfo() == null)
            {
                if(ui_model.validateTower(output))
                {
                    ui_model.setSelectionInfo(output);
                    ui_view.getTowerNameLabel().setText(ui_model.getSelectionInfo());
                }
            } else {
                JFrame dialog = new JFrame();
                JOptionPane.showMessageDialog(dialog, "There is a already selected tower: "
                + ui_model.getSelectionInfo(), "Cannot select a new tower !",
                JOptionPane.WARNING_MESSAGE);
            }
        }
    }
}

这是我的 UI 模型:

package env.model;

import javax.swing.*;

public class UI_Model 
{
    private String is_tower_selected = null;
    private DefaultListModel selected_modules = new DefaultListModel();
    private int module_counter = 0;
    private final String reset_tower_name = "No tower selected";

    private int shield = 0;
    private int armor  = 0;
    private double em  = 0.0;
    private double th  = 0.0;
    private double kn  = 0.0;
    private double ex  = 0.0;

    public String reset_label()
    {
        return this.reset_tower_name;
    }

    public int getModulesCounter()
    {
        return this.module_counter;
    }

    public UI_Model()
    {

    }

    public DefaultListModel getSelectedModules()
    {
        return this.selected_modules;
    }

    public void removeFromList(String input)
    {
        this.selected_modules.removeElement(input);
        this.module_counter -= 1;
    }

    public void addToList(String output)
    {
        if(validateInput(output) == true)
        {
            this.selected_modules.addElement("   " + output);
            this.module_counter += 1;
        }
    }

    public String getSelectionInfo()
    {
        return this.is_tower_selected;
    }

    public void setSelectionInfo(String tower)
    {
        this.is_tower_selected = tower;
    }

    public void retsetSelectionInfo()
    {
        this.is_tower_selected = null;
    }

    public void outputSelection(String output)
    {
        System.out.println(output);
    }    

    public boolean validateTower(String input)
    {
        if(input.equals("Select a Control Tower "))
        {
            return false;
        }
        return true;
    }

    public boolean validateInput(String input)
    {
        if(input.contains("<html>") || input.equals("Starbase Modules"))
        {
            return false;
        }
        return true;
    }
}

非常感谢您到目前为止:) 现在提问:

  1. 我正在尝试在我的视图中实现 JProgressBar 组件 创建了它的一个实例,但我对什么是有点困惑 实现它的正确方法,因为元素被添加到 JList 组件总最大量中消耗的部分 JProgressBar 将被更新。

  2. 在项目开始时,我被告知要实现 Observable 类到我的视图和观察者到我的模型。但是我被告知 提供一些我当时没有的代码供参考。 好吧,现在我有一些代码,但是我看不到这个 Observer / 可观察的实施可以帮助我在我的情况下或我的 特别是 JProgressBar 问题。我能得到一些建议吗 在这段代码中实现 O/O 如何帮助我。

  3. 由于我无法将 BorderFactory.createEmptyBorder 应用于 JLabel 在我的 JPanel 上设置标签之间的间距我使用“right.add(new JLabel(""), "wrap, span")" 之间如何创建垂直间隙 我用这个代替。是否有预定义的方法可以设置 JPanel 元素之间的差距还是我需要参考布局 经理。

欢迎任何关于修复、更改或替换的提示我知道我在这里放了很多数据,但我正在努力正确地学习这一点,我没有其他地方可以参考。

【问题讨论】:

  • 请缩短您的sscce 以专注于您要解决的问题。也可以考虑MouseAdapter
  • "...到目前为止,我发现它大大简化了我的工作..." UI 构建器将大大简化您的工作。 NetBeans 和 IntelliJ 都带有一个不错的构建器。

标签: java model-view-controller swing user-interface miglayout


【解决方案1】:

你说

在项目开始时,我被告知要为我的视图实现 Observable 类,并为我的模型实现 Observer。

但这对我来说听起来很倒退。视图最类似于Observer,模型类似于Observable. 也许你弄错了?

另外,查看 MouseAdapter 类——继承它而不是直接实现 MouseListener 会减少很多无用的代码!

【讨论】:

  • +1 表示MouseAdapter。另请参阅MVC example
  • 我有点假设描述只是错误的方式,在这种情况下(和大多数其他情况),观察观察和观察模型,你是观察(ing),模型。
【解决方案2】:
  1. 我不确定你在这里得到了什么,除非你链接它们,否则它不会更新?

  2. 如果您在 UI_Model 类上扩展 Observable,请将 addToList() 更改为调用 setChanges(),然后调用 notifyObservers()。


 public void addToList(String output)
    {
        if (validateInput(output) == true)
        {
            this.selected_modules.addElement("   " + output);
            this.module_counter += 1;
            setChanged();
            notifyObservers();
        }
    }

然后在你的视图对象上实现 Observer,然后将视图作为观察者添加到控制器中的模型中:

public UI_Controller(UI_Model model, UI_View view)
{
    ui_model = model;
    ui_view  = view;

    ui_model.addObserver(ui_view);

    ui_view.towersBoxListener(new towerSelectionListener());
    ui_view.modulesTreeListener(new modulesSelectionListener());
    ui_view.browserListListener(new browserSelectionListener());
    ui_view.towerLabelListner(new towerRemovalListener());
}
  1. 查看规范和其他各种来源,似乎 JLabel.setBorder(BorderFactory.createEmptyBorder(...)) 应该可以工作。

【讨论】:

    猜你喜欢
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多