Java - выполнение масштабных проектов с графическим интерфейсом - PullRequest
8 голосов
/ 22 декабря 2011

Чтобы получить право прямо на мой вопрос.

Как вы делаете масштабные проекты с графическим интерфейсом.Я не делал больших графических проектов в Java до сих пор, но то, над чем я работаю, теперь росло довольно быстро и довольно масштабно, и теперь я застрял в огромной куче кода, который действительно раздражает и запутывает.

Так какЯ пришел из области веб-разработки, я привык к фреймворкам MVC, поэтому у меня есть 3 пакета в моих проектах Модель, в которой я храню классы, которые взаимодействуют с файлами или БД, представления, где я храню свои классы для форм, или пакет с графическим интерфейсом и контроллером, где я хранюБольшая часть моей логики.

Мне сказали разделить мою логику, а также хранить действия в одном классе, а слушателей - в другом, но я не знаю, как все это связать.

Пока у меня есть только 1 класс 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, но нет учебных пособий или примеров того, как выполнять проекты, размер которых немного превышает один класс.

Заранее благодарим за помощь и советы.

Ответы [ 3 ]

6 голосов
/ 22 декабря 2011

Вот мой совет по разработке Swing в целом.В нем обсуждается важность использования контроллеров для согласования потребностей представления и взаимодействия модели.

Рекомендации по графическому интерфейсу для свинга

Последний проект Swing, который я сделал, яспроектировал среду MVC, которая использовала Spring для определения модели программы и контроллеров, а затем использовала аннотации в контроллере для связывания событий, отправляемых представлением, в методы в контроллере.Представление имело доступ к диспетчеру событий, который был шиной событий, и события, отправленные по шине, вызывали методы на контроллере через аннотации.Это позволило любому контроллеру реагировать на события из представления.Поэтому, когда Контроллер стал слишком большим, было очень просто перестроить каждый набор методов в другой Контроллер, и представление или модель не нужно было менять.

Красота шины событий заключалась в том, что она могла использоваться совместно.также с моделью, чтобы модель могла отправлять асинхронные события, для которых контроллер мог также регистрироваться.Это выглядело примерно так:

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 на сегодняшний день), и эта архитектура имела огромное значение.

3 голосов
/ 22 декабря 2011

Самый простой способ масштабирования графического интерфейса - сделать все свободно связанным. События (Swing's и ваши собственные) - лучший способ сделать это. Если класс непосредственно не создает или не отображает элемент GUI, он не должен знать или заботиться о чем-либо еще в пользовательском интерфейсе.

Контроллер должен продолжать делать то, что он должен делать - запускать события в ответ на другие события. Но эти события должны быть событиями уровня приложения, определяемыми потребностями вашего приложения. Контроллер не должен напрямую манипулировать элементами GUI. Вместо этого вы должны создать компоненты (может быть, просто подклассы JW), которые регистрируются в Controller как заинтересованные событиями.

Например, создайте интерфейс TowerEventListener с функцией nameChanged(). Контроллер также имеет функцию changeTowerName(), которая при вызове обновляет модель (класс Tower), а затем вызывает nameChanged() для всех зарегистрированных TowerEventListeners.

Затем создайте класс TowerRenamer, который, например, подклассы JDialog (то есть всплывающее окно), который включает в себя текстовое поле и кнопку ОК, а также ссылку на контроллер. Когда пользователь нажимает кнопку ОК, вызывается Controller.changeTowerName(). Другие части вашего графического интерфейса, которые регистрируются как TowerEventListeners, будут получать событие и обновляться по мере необходимости (возможно, путем обновления JLabel в пользовательском интерфейсе).

Обратите внимание: если ваши потребности достаточно просты, вы можете просто использовать PropertyChangeEvents и не беспокоиться о структуре интерфейса всего события. PropertyChangeSupport может использоваться контроллером для запуска уведомлений о событиях.

2 голосов
/ 22 декабря 2011

В дополнение к хорошему совету, который я уже дал, я бы рекомендовал прочесть кое-что из того, что Trygve Reenskaug написал и / или записал на своей странице MVC .Он был там во время разработки этого архитектурного стиля в конце 70-х годов.Его двухстраничный технический отчет, озаглавленный Модели - виды - контроллеры от декабря 1979 года, представляет наиболее краткое описание модели, вида и контроллера.

Особого примечания, оба вида наблюдатели и манипуляторы модели.Контроллер в первую очередь занимается организацией (связыванием) представлений и преобразованием пользовательского ввода во взаимодействия с моделью.Некоторые из MVC-фреймворков имеют контроллер, передающий данные из модели в представление - это просто неправильно.В статье , опубликованной ранее в 1979 году , содержалась концепция редактора как совокупность связанных представлений.Редактор был отклонен;его функциональность была перенесена как в контроллер, так и в представление.

Еще одна статья, в которой хорошо описано, как применять это руководство, - Burbeck's Как использовать Model-View-Controller .Он написан с учетом Smalltalk, поэтому он не может быть легко переведен на Java, но это хорошее описание того, как применять рекомендации.

Я думаю, что самое важное, что следует учитывать, это то, что оригинальный стиль MVCбыл создан для пользовательских интерфейсов, включающих более одного представления (представления) одной и той же модели.Это действительно хорошо работает для пользовательских интерфейсов, но не очень хорошо переносится в мир веб-сервисов.Использование MVC для графического интерфейса позволяет вам по-настоящему увидеть и понять всю мощь этого стиля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...