Java - 做大型GUI项目

时间:2011-12-22 03:06:53

标签: java swing user-interface

直接回答我的问题。

您如何进行大规模的GUI项目。到目前为止,我还没有在java中做过任何更大的GUI项目,但是我现在正在进行的工作变得非常快,而且非常大,现在我被困在一大堆非常烦人和混乱的代码中。

由于我来自Web开发领域我习惯于MVC框架所以我在我的项目模型中有3个包我保留了与whit文件或db交互的类,其中我保留了我的类用于Forms或GUI和Controller包的视图我保留了大部分逻辑。

我被告知要将我的逻辑分开,并在一个班级和另一个班级的听众中保持行动,但我不知道如何将所有这些联系起来。

到目前为止,我只有一个Controller类,我可以执行所有关于GUI调用后发生的所有方法。

package pft.controller;


import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.JTree;
import java.awt.event.*;
import javax.swing.JProgressBar;
import pft.view.Invoke_GUI;
import pft.model.Events;
import pft.model.Parse;

public class Tower_Controller {

    public Tower_Controller() {
    }
    //Global variables
    String isSelected = null;
    int hasModules = 0;
    int cap = 0;
    int cpu = 0;
    int shield = 0;
    int armor = 0;

    public void setName(String name){
        this.isSelected = name;
    }

    public String getName(){
        return this.isSelected;
    }

    public void setCap(int cap){
        this.cap = cap;
    }

    public int getCap(){
        return this.cap;
    }

    public void setCpu(int cpu){
        this.cpu = cpu;
    }

    public int getCpu(){
        return this.cpu;
    }

    public void setShield(int shield){
        this.shield = shield;
    }

    public int getShield(){
        return this.shield;
    }

    public void setArmor(int armor){
        this.armor = armor;
    }

    public int getArmor(){
        return this.armor;
    }


    public void invoke() throws IOException {
        Invoke_GUI runnable = new Invoke_GUI();
        final JLabel tower_name = runnable.tower_name;
        final JComboBox tower_select = runnable.tower_select;
        final JTree module_browser = runnable.module_browser;
        final JTree selected_modules = runnable.selected_modules;

        final JProgressBar cap_bar = runnable.cap_bar;
        final JProgressBar cpu_bar = runnable.cpu_bar;

        final JLabel em_res = runnable.em;
        final JLabel th_res = runnable.thermic;
        final JLabel ki_res = runnable.kinetic;
        final JLabel ex_res = runnable.explosive;

        setTowerName(tower_name, tower_select);
        removeTower(tower_name);
        runnable.setVisible(true);       

    }

    public void removeTower(final JLabel tower_name) {
        tower_name.addMouseListener(new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                if (hasModules == 1 & isSelected != null) {
                    Events evt = new Events();
                    evt.towerHasModules();
                } else if (isSelected == null) {
                } else {
                    tower_name.setText("No Control Tower selected");
                    isSelected = null;
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
            }

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }
        });
    }

    public void updateVariables(String name) throws IOException{
        Parse tower = new Parse();
        String data[] = tower.towerData(name);
        Integer x = Integer.valueOf(data[1]).intValue();
        setCap(x);
    }

    public void setTowerName(final JLabel tower_name, final JComboBox tower_select) {
        tower_select.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (isSelected != null) {
                    Events evt = new Events();
                    evt.towerSelected(isSelected);
                } else {
                    tower_name.setText(tower_select.getSelectedItem().toString());
                    setName(tower_name.toString());
                    try {
                        updateVariables(tower_name.toString());
                    } catch (IOException ex) {
                        Logger.getLogger(Tower_Controller.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        });
    }


}

有很多教程和示例如何做小型通常的单一类Java GUI,但没有关于如何进行比单个类大的项目的教程或示例。

提前感谢所有的帮助和 建议。

3 个答案:

答案 0 :(得分:6)

以下是我对Swing开发的一般建议。它确实讨论了使用控制器来弥合视图需求和模型交互的重要性。

GUI guidelines for swing

我做过的最后一个Swing项目我设计了一个MVC框架,它使用Spring来定义程序和控制器的模型,然后在Controller中使用注释将视图调度的事件连接到控制器中的方法。该视图可以访问事件调度程序,它是一个事件总线,通过总线发送的事件通过注释在Controller上调用方法。这允许任何Controller响应View中的事件。因此,当控制器太大时,将每组方法重构为另一个控制器非常简单,并且视图或模型不必更改。

事件总线的优点在于它可以与模型共享,因此模型可以调度Controller也可以注册的异步事件。它看起来像是:

public class SomeController {

   private AuthenticationModel authenticationModel;

   private LoginService loginService;

   private MyApp view;

   @Listener( event = "login" )
   public void login( LoginEvent event ) {
       view.showWaitDialog();
       loginService.login( event.getUserName(), event.getPassword() )
       .onResult( new Callback<User>() {
           public void onResult( User user ) {
               authenticationModel.setUser( user );
               view.hideWaitDialog();
               view.showStartScreen(user);
           }
       });
   }

}

一旦这个框架到位,令人惊讶的是我们能够以多快的速度完成任务。当我们添加功能时,它的表现相当不错。我已经完成了大量Swing项目(迄今为止3个)的公平份额,这种架构产生了巨大的差异。

答案 1 :(得分:3)

扩展GUI的最简单方法是使所有内容松散耦合。事件(Swing和您自己的)是最好的方法。除非一个类直接创建或显示GUI元素,否则它不应该知道或关心UI中的任何其他内容。

Controller应该继续做它应该做的事情 - 触发事件以响应其他事件。但是,这些事件应该是应用程序需求定义的应用程序级事件。 Controller不应直接操作GUI元素。相反,您应该创建组件(可能只是JWhatever的子类),它们将自己注册为对事件感兴趣的控制器。

例如,使用TowerEventListener函数创建nameChanged()接口。 Controller还有一个changeTowerName()函数,在调用时,它会更新模型(Tower类),然后在所有已注册的nameChanged()上调用TowerEventListeners

然后创建一个TowerRenamer类,例如,子类JDialog(即一个弹出窗口),它包含一个文本框和OK按钮以及对Controller的引用。当用户单击“确定”时,将调用Controller.changeTowerName()。注册为TowerEventListeners的GUI的其他部分将根据需要接收事件并进行更新(可能通过在UI上更新JLabel)。

注意,如果您的需求足够简单,您可以使用PropertyChangeEvents而不用担心整个事件接口结构。 Controller可以使用PropertyChangeSupport来触发事件通知。

答案 2 :(得分:2)

除了已经提出的好建议外,我还建议您阅读Trygve Reenskaug撰写和/或记录on his MVC page的一些内容。他在70年代后期开发这种建筑风格时就在那里。他从1979年12月开始的题为Models - Views - Controllers的两页技术报告对模型,视图和控制器进行了最简洁的描述。

特别值得注意的是,视图是模型的观察者操纵者。控制器主要涉及安排(布线)视图并将用户输入转换为与模型的交互。有几个MVC框架有控制器将数据从模型中继到视图 - 这是完全错误的。 paper from earlier in 1979编辑器的概念作为相关视图的组合包含在内。编辑被丢弃了;它的功能被移动到控制器和视图中。

另一篇擅长描述如何应用此指南的文章是Burbeck's How to use Model-View-Controller。它是用Smalltalk编写的,因此它可能不会轻易转换为Java,但它很好地描述了如何应用指南。

我认为最重要的是要考虑原始MVC样式是为包含同一模型的多个视图(表示)的用户界面创建的。这对用户界面非常有效,但不能很好地转换为Web服务世界。使用MVC进行GUI可以让您真正看到并理解这种风格的强大功能。