Java 如何管理复杂gui应用程序中的类体系结构

Java 如何管理复杂gui应用程序中的类体系结构,java,swing,user-interface,Java,Swing,User Interface,我正在编写一个需要大量swing GUI组件的应用程序 当我将内部类事件处理程序放在单独的文件中时,我很难访问主类的组件 我组织这个班有很多困难。是否有一种方法来组织和整齐地布局类架构 此外,我有许多匿名类和内部类,我的主类变得臃肿 如何管理我的gui类,以便事件处理能够以调用其他应用程序类对象的方式轻松进行 public class MainScreen extends JFrame { // Variables declaration

我正在编写一个需要大量swing GUI组件的应用程序

当我将内部类事件处理程序放在单独的文件中时,我很难访问主类的组件

我组织这个班有很多困难。是否有一种方法来组织和整齐地布局类架构

此外,我有许多匿名类和内部类,我的主类变得臃肿

如何管理我的gui类,以便事件处理能够以调用其他应用程序类对象的方式轻松进行

public class MainScreen extends JFrame {

    // Variables declaration                     
    private JTree fileTree;
    private JScrollPane fileTreeScroll;
    private JSplitPane horSplit;
    private JTabbedPane textAreaPane;
    private JTabbedPane outputPane;
    private JSplitPane mainSplit;
    private JEditorPane textEditor;
    private JScrollPane textScroll;
    private JLabel log;

    private Controller controller;
    private String projectName;

    public static final String APP_NAME = "Smart Coder";
    public static final String IMAGE_PATH = "/ImageResources/";
    public static final int maxWidth = 1280;
    public static final int maxHeight = 720;
    public static final int minWidth = 800;
    public static final int minHeight = 450;
    public static final int divLen = 300;
    public static final int divLen2 = 150;

    protected JTextArea editor;
    javax.swing.JFrame frame;
    protected JFileChooser fileChooser;
    protected File currentFile;

    protected boolean textChanged = false;
    protected JToolBar toolBar;

    // End of variables declaration 
    public MainScreen() {
        super(APP_NAME);
        setSize(minWidth, minHeight);
        //DefaultSyntaxKit.initKit();
        jsyntaxpane.DefaultSyntaxKit.initKit();

        controller = new Controller();

        ///////////////////////////////////////////////////////////
        mainSplit = new JSplitPane();
        outputPane = new JTabbedPane();
        horSplit = new JSplitPane();
        fileTreeScroll = new JScrollPane();
        fileTree = new JTree();
        textAreaPane = new JTabbedPane();
        textScroll = new JScrollPane();
        textEditor = new JEditorPane();
        log = new JLabel("Status : ");

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMaximumSize(new java.awt.Dimension(maxWidth, maxHeight));
        setMinimumSize(new java.awt.Dimension(minWidth, minHeight));

        mainSplit.setDividerLocation(divLen);
        mainSplit.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        mainSplit.setToolTipText("Drag to change size.");
        mainSplit.setBottomComponent(outputPane);
        horSplit.setDividerLocation(divLen2);

        fileTreeScroll.setViewportView(fileTree);

        horSplit.setLeftComponent(fileTreeScroll);

        horSplit.setRightComponent(textAreaPane);

        mainSplit.setLeftComponent(horSplit);

        //////////////////////////////////////////////////////////////////////////////
        editor = new JTextArea();
        textScroll.add(editor);

        JMenuBar menuBar = createMenuBar();
        setJMenuBar(menuBar);
        getContentPane().add(log, BorderLayout.SOUTH);

        fileChooser = new JFileChooser();
        try {
            File dir = (new File(".")).getCanonicalFile();
            fileChooser.setCurrentDirectory(dir);
        } catch (IOException ex) {
        }

        updateEditor();
        //newDocument();

        WindowListener wndCloser = new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("Action event of window closing.");
                if (!promptToSave()) {
                    return;
                }
                System.exit(0);
            }
        };

        addWindowListener(wndCloser);
        getContentPane().add(mainSplit);
        frame = this;
        pack();
    }

    protected JMenuBar createMenuBar() {
        final JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic('f');

//        JMenu newMenu = new JMenu("New");
//        newMenu.setMnemonic('n');
        // Action for New Project
        ImageIcon iconNewPro = new ImageIcon(getClass().getResource(IMAGE_PATH + "newpack.png"));
        Action actionNewProject = new MyAction("New Project", iconNewPro, KeyEvent.VK_P,
                KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK + InputEvent.SHIFT_MASK));
        fileMenu.add(actionNewProject);
//        newMenu.add(actionNewProject);

        // Action for New File
        ImageIcon iconNewFile = new ImageIcon(getClass().getResource(IMAGE_PATH + "new.png"));
        Action actionNew = new MyAction("New Java File", iconNewFile, KeyEvent.VK_J, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        fileMenu.add(actionNew);
//        newMenu.add(actionNew);

//        fileMenu.add(newMenu);
        // Action for Open Project
        ImageIcon iconOpen = new ImageIcon(getClass().getResource(IMAGE_PATH + "openpack.png"));
        Action actionOpen = new MyAction("Open", iconOpen, KeyEvent.VK_O,
                KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
        fileMenu.add(actionOpen);

        // Action for Save Project
        ImageIcon iconSave = new ImageIcon(getClass().getResource(IMAGE_PATH + "save.png"));
        Action actionSave = new MyAction("Save", iconSave, KeyEvent.VK_S,
                KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
        fileMenu.add(actionSave);
        fileMenu.addSeparator();

        // Action for Exit Project
        ImageIcon iconExit = new ImageIcon(getClass().getResource(IMAGE_PATH + "exit.png"));
        Action actionExit = new MyAction("Exit", iconExit, KeyEvent.VK_X,
                KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK));
        fileMenu.add(actionExit);
        menuBar.add(fileMenu);

        // Edit menu starts 
        JMenu editMenu = new JMenu("Edit");
        editMenu.setMnemonic('e');

        // undo action
        ImageIcon iconUndo = new ImageIcon(getClass().getResource(IMAGE_PATH + "undo.png"));
        Action actionUndo = new MyAction("Undo", iconUndo, KeyEvent.VK_U,
                KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK));
        editMenu.add(actionUndo);

        // redo action
        ImageIcon iconRedo = new ImageIcon(getClass().getResource(IMAGE_PATH + "redo.png"));
        Action actionRedo = new MyAction("Redo", iconRedo, KeyEvent.VK_R,
                KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK));
        editMenu.add(actionRedo);
        editMenu.addSeparator();

        // cut action
        ImageIcon iconCut = new ImageIcon(getClass().getResource(IMAGE_PATH + "cut.png"));
        Action actionCut = new MyAction("Cut", iconCut, KeyEvent.VK_X,
                KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
        editMenu.add(actionCut);

        // copy action
        ImageIcon iconCopy = new ImageIcon(getClass().getResource(IMAGE_PATH + "copy.png"));
        Action actionCopy = new MyAction("Copy", iconCopy, KeyEvent.VK_C,
                KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
        editMenu.add(actionCopy);

        // paste action
        ImageIcon iconPaste = new ImageIcon(getClass().getResource(IMAGE_PATH + "paste.png"));
        Action actionPaste = new MyAction("Paste", iconPaste, KeyEvent.VK_V,
                KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
        editMenu.add(actionPaste);
        editMenu.addSeparator();

        // find action
        ImageIcon iconFind = new ImageIcon(getClass().getResource(IMAGE_PATH + "find.png"));
        Action actionFind = new MyAction("Find", iconFind, KeyEvent.VK_F,
                KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK));
        editMenu.add(actionFind);

        // Replace action
        ImageIcon iconReplace = new ImageIcon(getClass().getResource(IMAGE_PATH + "findreplace.png"));
        Action actionReplace = new MyAction("Replace", iconReplace, KeyEvent.VK_R,
                KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK + InputEvent.SHIFT_MASK));
        editMenu.add(actionReplace);

        menuBar.add(editMenu);

        // Run menu starts 
        JMenu runMenu = new JMenu("Run");
        runMenu.setMnemonic('r');

        ImageIcon iconRun = new ImageIcon(getClass().getResource(IMAGE_PATH + "play.png"));
        Action actionRun = new MyAction("Run", iconRun, KeyEvent.VK_R,
                KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK));
        runMenu.add(actionRun);

        menuBar.add(runMenu);

        // Create toolbar
        toolBar = new JToolBar("File Commands");
        JButton bNewPro = toolBar.add(actionNewProject);
        bNewPro.setToolTipText("New Project");

        JButton bNew = toolBar.add(actionNew);
        bNew.setToolTipText("New Java File");

        JButton bOpen = toolBar.add(actionOpen);
        bOpen.setToolTipText("Open Project");

        JButton bSave = toolBar.add(actionSave);
        bSave.setToolTipText("Save file");

        getContentPane().add(toolBar, BorderLayout.NORTH);
        return menuBar;
    }

    protected String getDocumentName() {
        return currentFile == null ? "Untitled"
                : currentFile.getName();
    }

    protected void newDocument() {
        editor.setText("");
        currentFile = null;
        setTitle(APP_NAME + " [" + getDocumentName() + "]");
        textChanged = false;
        editor.getDocument().addDocumentListener(new UpdateListener());
    }

    protected void openDocument() {
        if (fileChooser.showOpenDialog(MainScreen.this)
                != JFileChooser.APPROVE_OPTION) {
            return;
        }
        File f = fileChooser.getSelectedFile();
        if (f == null || !f.isFile()) {
            return;
        }
        currentFile = f;
        try {
            FileReader in = new FileReader(currentFile);
            editor.read(in, null);
            in.close();
            setTitle(APP_NAME + " [" + getDocumentName() + "]");
        } catch (IOException ex) {
            showError(ex, "Error reading file " + currentFile);
        }
        textChanged = false;
        editor.getDocument().addDocumentListener(new UpdateListener());
    }

    protected boolean saveFile() {
        if (currentFile == null) {
            if (fileChooser.showSaveDialog(MainScreen.this)
                    != JFileChooser.APPROVE_OPTION) {
                return false;
            }
            File f = fileChooser.getSelectedFile();
            if (f == null) {
                return false;
            }
            currentFile = f;
            setTitle(APP_NAME + " [" + getDocumentName() + "]");
        }

        try {
            FileWriter out = new FileWriter(currentFile);
            editor.write(out);
            out.close();
        } catch (IOException ex) {
            showError(ex, "Error saving file " + currentFile);
            return false;
        }
        textChanged = false;
        return true;
    }

    protected boolean promptToSave() {
        if (!textChanged) {
            return true;
        }
        int result = JOptionPane.showConfirmDialog(this,
                "Save changes to " + getDocumentName() + "?",
                APP_NAME, JOptionPane.YES_NO_CANCEL_OPTION,
                JOptionPane.INFORMATION_MESSAGE);
        switch (result) {
            case JOptionPane.YES_OPTION:
                if (!saveFile()) {
                    return false;
                }
                return true;
            case JOptionPane.NO_OPTION:
                return true;
            case JOptionPane.CANCEL_OPTION:
                return false;
        }
        return true;
    }

    protected void updateEditor() {
        editor.repaint();
    }

    public void showError(Exception ex, String message) {
        ex.printStackTrace();
        JOptionPane.showMessageDialog(this,
                message, APP_NAME,
                JOptionPane.WARNING_MESSAGE);
    }

    public void disableAll() {
        fileTree.setEnabled(false);
        fileTreeScroll.setEnabled(false);
        textAreaPane.setEnabled(false);
        outputPane.setEnabled(false);
        textEditor.setEnabled(false);
    }

    public void showNewProDialog() {
        System.out.println("Action event of New Project button.");
        NewProject dialogPro = new NewProject(frame, true);
        System.out.println(dialogPro.getSize());
        dialogPro.setVisible(true);
        if (dialogPro.getSucceeded()) {
            log.setText("Status : Creating Files . . .");
dialogPro.getPackName(), dialogPro.getClName());
controller.getClassName(0), controller.getCode(0));

        addTab(dialogPro.getClName(), dialogPro.getClName());
        projectName = dialogPro.getProName();
            Thread work = new Thread() {
                public void run() {
                    createNewPro(dialogPro.getProName(), dialogPro.getPackName(), dialogPro.getClName());
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            updateTab(0,controller.getCode(0));
                            setFileTree();
                        }
                    });
                }
            };
            work.start();

        }
    }

    private void createNewPro(String proName, String packName, String clName) {
        controller.createNewProject(proName, packName, clName);
        log.setText("Status : " + controller.getMessage());
    }


    private void updateTab(int index, String text){

        Component comp = textAreaPane.getComponentAt(index);
        if (comp instanceof JScrollPane) {
            JScrollPane pane = (JScrollPane) comp;
            Component comp2 = pane.getComponent(0);
            JViewport viewport = pane.getViewport();  
            if(viewport.getView() instanceof JEditorPane){
                JEditorPane edit = (JEditorPane) viewport.getView();
                edit.setText(text);
            }
        }
    }

    private void addTab(String name, String desc) {
        // TODO think about the text or direct from file
        JEditorPane edit = new JEditorPane();
        JScrollPane scrollPane = new JScrollPane(edit);
        edit.setContentType("text/java");
        ImageIcon icon = new ImageIcon(getClass().getResource(IMAGE_PATH + "new16.gif"));
        textAreaPane.addTab(name, icon, scrollPane, desc);
        textAreaPane.setTabComponentAt(textAreaPane.getComponentCount()-1,new ButtonTabComponent(textAreaPane,icon));
    }

    private void setFileTree(){
        DefaultTreeModel model;
        DefaultMutableTreeNode top = new DefaultMutableTreeNode("Projects");
        top.add(FileHandling.listFiles(new DefaultMutableTreeNode(projectName), Config.getPath()+projectName, ".java"));
        model = new DefaultTreeModel(top);
        fileTree = new JTree(model);
        fileTreeScroll.setViewportView(fileTree);
        horSplit.setLeftComponent(fileTreeScroll);
    }

    public void showNewFileDialog() {
        System.out.println("Action event of New File button.");
        NewJavaFile dialogFile = new NewJavaFile(frame, true);
        System.out.println(dialogFile.getSize());
        dialogFile.setVisible(true);
    }

    public void showOpenProDialog() {
        System.out.println("Action event of open button.");
        OpenProject dialogOpen = new OpenProject(frame, true);
        dialogOpen.setVisible(true);
        if (dialogOpen.getNewClicked()) {
            showNewProDialog();
        }
    }


    class UpdateListener implements DocumentListener {

        public void insertUpdate(DocumentEvent e) {
            textChanged = true;
        }

        public void removeUpdate(DocumentEvent e) {
            textChanged = true;
        }

        public void changedUpdate(DocumentEvent e) {
            textChanged = true;
        }
    }

    private class MyAction extends AbstractAction {

        String name;

        public MyAction(String name, Icon icon) {
            super(name, icon);
            this.name = name;
        }

        public MyAction(String name, Icon icon,
                Integer mnemonic, KeyStroke accelorator) {
            super(name, icon);
            putValue(Action.MNEMONIC_KEY, mnemonic);
            putValue(Action.ACCELERATOR_KEY, accelorator);
            this.name = name;
        }

        public MyAction(String name, Icon icon, String desc,
                Integer mnemonic, KeyStroke accelorator) {
            super(name, icon);
            putValue(Action.SHORT_DESCRIPTION, desc);
            putValue(Action.MNEMONIC_KEY, mnemonic);
            putValue(Action.ACCELERATOR_KEY, accelorator);
            this.name = name;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            switch (name) {
                case "New Project":
                    showNewProDialog();
                    break;
                case "New Java File":
                    showNewFileDialog();
                    break;
                case "Open":
                    showOpenProDialog();
                    break;
                case "Save":
                    System.out.println("Action event of save button.");
                    break;
                case "Exit":
                    System.out.println("Action event of exit button.");
                    System.exit(0);
                    break;
                case "Undo":
                    System.out.println("Action event of Undo button.");
                    break;
                case "Redo":
                    System.out.println("Action event of Redo button.");
                    break;
                case "Cut":
                    System.out.println("Action event of Cut button.");
                    break;
                case "Copy":
                    System.out.println("Action event of Copy button.");
                    break;
                case "Paste":
                    System.out.println("Action event of Paste button.");
                    break;
                case "Find":
                    System.out.println("Action event of Find button.");
                    break;
                case "Replace":
                    System.out.println("Action event of Replace button.");
                    break;
                case "Run":
                    System.out.println("Action event of Run button.");
                    compileCode();
                    break;

            }
        }
    }
}
将具有对MainScreen.this对象的引用。这就是为什么可以从MyAction类内部调用它。当您将其移动到新文件时,您将无法再访问MainScreen.this

当您将MyAction类提取到一个新文件时,给它一个构造函数,该构造函数接受一个MainScreen对象(或者更好的是,一个MainScreen实现的接口),并将其保存在一个成员变量中。例如,该接口将具有方法
showNewFileDialog()

然后,调用该成员变量上的方法,例如
mainScreen.showNewFileDialog()

通过此实现,您可以重用MyAction类

MyAction类示例:

public class MyAction extends AbstractAction {

    String name;

    MainScreen mainScreen;

    public MyAction(String name, Icon icon, MainScreen s) {
        super(name, icon);
        this.name = name;
        this.mainScreen = s;
    }

    public MyAction(String name, Icon icon,
            Integer mnemonic, KeyStroke accelorator,) {
        super(name, icon);
        putValue(Action.MNEMONIC_KEY, mnemonic);
        putValue(Action.ACCELERATOR_KEY, accelorator);
        this.name = name;
        this.mainScreen = s;
    }

    public void actionPerformed(ActionEvent e) {
        switch (name) {
            case "New Project":
                mainScreen.showNewProDialog();
                break;
            case "New Java File":
                mainScreen.showNewFileDialog();
                break;
            case "Open":
                showOpenProDialog();
                break;
            case "Save":
                System.out.println("Action event of save button.");
                break;
            case "Exit":
                System.out.println("Action event of exit button.");
                System.exit(0);
                break;
            case "Undo":
                System.out.println("Action event of Undo button.");
                break;
            case "Redo":
                System.out.println("Action event of Redo button.");
                break;
            case "Cut":
                System.out.println("Action event of Cut button.");
                break;
            case "Copy":
                System.out.println("Action event of Copy button.");
                break;
            case "Paste":
                System.out.println("Action event of Paste button.");
                break;
            case "Find":
                System.out.println("Action event of Find button.");

考虑一下程序的体系结构是很好的。您的问题的答案是MVC模式。可能链接会对您有所帮助。感谢您的回答,但MainScreem扩展了jframe,它向用户显示了主界面,而myAction类用于添加菜单项和带有单个实例的工具栏。我将如何将其分离并在iti更新我的响应中定义MainScreen的变量,以向您展示如何引用myAction中的MainScreen对象类再次感谢MainScreen类有哪些变化我用过的选项卡式窗格如何处理它们还有请编译器帮助您。实现我在MyAction类中显示的更改,并从MainScreen文件中删除该类。然后编译器将在需要额外内容的行上显示错误(当您创建MyAction的新实例时)
public class MyAction extends AbstractAction {

    String name;

    MainScreen mainScreen;

    public MyAction(String name, Icon icon, MainScreen s) {
        super(name, icon);
        this.name = name;
        this.mainScreen = s;
    }

    public MyAction(String name, Icon icon,
            Integer mnemonic, KeyStroke accelorator,) {
        super(name, icon);
        putValue(Action.MNEMONIC_KEY, mnemonic);
        putValue(Action.ACCELERATOR_KEY, accelorator);
        this.name = name;
        this.mainScreen = s;
    }

    public void actionPerformed(ActionEvent e) {
        switch (name) {
            case "New Project":
                mainScreen.showNewProDialog();
                break;
            case "New Java File":
                mainScreen.showNewFileDialog();
                break;
            case "Open":
                showOpenProDialog();
                break;
            case "Save":
                System.out.println("Action event of save button.");
                break;
            case "Exit":
                System.out.println("Action event of exit button.");
                System.exit(0);
                break;
            case "Undo":
                System.out.println("Action event of Undo button.");
                break;
            case "Redo":
                System.out.println("Action event of Redo button.");
                break;
            case "Cut":
                System.out.println("Action event of Cut button.");
                break;
            case "Copy":
                System.out.println("Action event of Copy button.");
                break;
            case "Paste":
                System.out.println("Action event of Paste button.");
                break;
            case "Find":
                System.out.println("Action event of Find button.");