首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GUI‘简单记事本’

GUI‘简单记事本’
EN

Code Review用户
提问于 2015-05-27 08:57:46
回答 2查看 3.3K关注 0票数 9

请对代码的所有方面给予反馈,无论是注释、方法的使用、语义或任何可以改进的内容。

在我看来,这段代码完美无缺,所以任何改进建议都会产生影响。

代码语言:javascript
复制
//  Imports packages for AWT, Events, Scanner, File, PrintWriter,
//  exceptions and Swing components.
import java.util.Scanner;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * This class extends JFrame to inherit all methods for active use.
 * This class implements the interface ActionListener to handle user actions
 */
public class SchultzTobias extends JFrame implements ActionListener {

    //  Declaring all swing components for access throughout multiple methods
    private         JMenuBar      menuBar;
    private         JTextArea     txtArea;
    private final   JMenu[]       menu = new JMenu[4];
    private final   JMenuItem[]   menuItem = new JMenuItem[7];
    private         JMenu         fontMenu;
    private final   JMenuItem[]   fontItem = new JMenuItem[10];

    /**
     * This constructor initializes all components, sets the workspace
     * preferences and connects everything to the JFrame superclass
     */
    public SchultzTobias() {

        //  Assigns a title to the notepad
        super("Simple Notepad");

        //  Initializes the text area for user input
        txtArea = new JTextArea(24, 54);

        //  Sets formatting to break line at whole words, and adding
        //  some border to the JTextArea.
        txtArea.setLineWrap(true);
        txtArea.setWrapStyleWord(true);
        txtArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // If content exceeds size of viewport, make scrolling through the
        // content possible
        JScrollPane scrollPane = new JScrollPane(txtArea);

        //  initializes all menus, menuItems and corresponding key bindings
        initializeMenus();
        initializeKeyBindings();

        //  adding menus and JTextArea to the JFrame
        add(menuBar);
        add(scrollPane, BorderLayout.SOUTH);

        //  Presenting the JFrame, and stating the programs close operation
        setVisible(true);
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    /**
     * This method constructs and adds names and actionListener's to
     * JMenu's and JMenuItem's, which are then added to the JMenuBar.
     */
    public void initializeMenus() {

        //  Declaring the menu bar
        menuBar = new JMenuBar();

        //  Assigns names to the main menu and adding them to
        //  actionListener's and the menu bar
        String[] menuNames = {"File", "Edit", "Format", "Help"};

        for (int i = 0; i < menu.length; i++) {
            menu[i] = new JMenu(menuNames[i]);
            menu[i].addActionListener(this);
            menuBar.add(menu[i]);
        }

        //  Assigns names to the menu items and adding them to
        //  actionListener's and the main menu
        String[] itemString = {"Open", "Save", "Exit", "Text Wrap",
                "No Text Wrap", "Clear", "About Simple Notepad"};

        for (int i = 0; i < menuItem.length; i++) {
            menuItem[i] = new JMenuItem(itemString[i]);
            menuItem[i].addActionListener(this);

            if (i < 3)      { menu[0].add(menuItem[i]);} // Adding to 'File'
            else if (i < 5) { menu[1].add(menuItem[i]);} // Adding to 'Edit'
            else if (i < 6) { menu[2].add(menuItem[i]);} // Adding to 'Format'
            else            { menu[3].add(menuItem[i]);} // Adding to 'Help'
        }

        // Initializing the menu for fonts and adding
        // menu items with font sizes
        fontMenu = new JMenu("Font");

        for (int i = 0; i < fontItem.length; i++) {
            fontItem[i] = new JMenuItem(String.valueOf((i + 1) * 2));
            fontItem[i].addActionListener(this);
            fontMenu.add(fontItem[i]);
        }

        //  Adding the 'Font' menu to the 'Edit' menu
        menu[1].add(fontMenu);
    }

    /**
     * This method assigns a mnemonic character for each menu and menuItem.
     * If the program is viewed on a Mac, alt(option) key must be pressed
     * to view the mnemonic icon.
     */
    public void initializeKeyBindings() {

        //  The assignment had mnemonic icons on different indexes in its
        //  presentation. To deliver exactly what the assignment specified,
        //  and to keep the code readable, i wrote each mnemonic statement
        //  separately.
        menu[0].setMnemonic(KeyEvent.VK_F);     //  File
        menu[1].setMnemonic(KeyEvent.VK_E);     //  Edit
        menu[2].setMnemonic(KeyEvent.VK_O);     //  Format
        menu[3].setMnemonic(KeyEvent.VK_H);     //  Help

        menuItem[0].setMnemonic(KeyEvent.VK_O); //  Open
        menuItem[1].setMnemonic(KeyEvent.VK_S); //  Save
        menuItem[2].setMnemonic(KeyEvent.VK_E); //  Exit
        menuItem[3].setMnemonic(KeyEvent.VK_W); //  Text Wrap
        menuItem[4].setMnemonic(KeyEvent.VK_N); //  No Text Wrap
        menuItem[5].setMnemonic(KeyEvent.VK_C); //  Clear
        menuItem[6].setMnemonic(KeyEvent.VK_A); //  About

        fontMenu.setMnemonic(KeyEvent.VK_F);    //  Font
    }

    /**
     * This method prompts user to enter name of file that will be attempted
     * to be opened
     *
     * @exception FileNotFoundException On input error.
     */
    public void openFile() {

        //  Prompts user for the name of the file to read
        String fileOutput = "";
        String fileName = JOptionPane.showInputDialog(txtArea, "Oppgi filnavn");

        //  If the user has typed anything, attempt to open file
        if (fileName != null) {
            try {

                //  Read everything from file until the end-anchor is found: \Z
                Scanner content = new Scanner(new File(fileName));
                content.useDelimiter("\\Z");

                while (content.hasNext()) {
                    fileOutput += content.next();
                }

                //  Store content read from file in text area and close dialog
                //  box.
                txtArea.setText(fileOutput);
                content.close();

                //  If file was not found, print the exception that was thrown
            } catch (FileNotFoundException fnfe) {
                System.out.println("This error was thrown: " + fnfe);
            }
        }
    }

    /**
     * This method  prompts user to enter name of file that will be attempted
     * to be stored
     *
     * @exception IOException On output error.
     */
    public void saveFile() {

        //  Prompts user for the name of the file to be stored
        String fileName = JOptionPane.showInputDialog(txtArea, "Oppgi filnavn");

        //  If user has typed in anything, attempt to save file
        if (fileName != null) {

            //  Copy content from the text area into the file being created
            try {
                PrintWriter content = new PrintWriter(new File(fileName));
                content.write(txtArea.getText());
                content.close();

                //  If there was an error, print the exception
            } catch (IOException ioe) {
                System.out.println("This error was thrown: " + ioe);
            }
        }
    }

    /**
     *  This method prompts user with three options
     *      - Save text area to file through method saveFile()
     *      - Exit the program without storing file
     *      - Go back to superclass JFrame
     *
     * @param clear handles what to do after a user has selected an option.
     *              If clear is true, do not exit program after statement.
     *              If clear is false, exit program after statement.
     */
    public void exitFile(boolean clear) {

        //  Prompts user with options to store file, not to store file or
        int options = JOptionPane.showConfirmDialog(
                txtArea, "Vil du lagre først?");

        //  If user acted on the YES option
        if (options == JOptionPane.YES_OPTION) {
            saveFile();

            // And first acted on the 'Clear' menuItem
            if (clear) {
                txtArea.setText("");

            // And first acted on the 'Exit' menuItem
            } else {
                System.exit(0);
            }
        }

        //  If user acted on the NO option
        else if (options == JOptionPane.NO_OPTION) {

            // And first acted on the 'Clear' menuItem
            if (clear) {
                txtArea.setText("");

            // And first acted on the 'Exit' menuItem
            } else {
                System.exit(0);
            }
        }
    }

    /**
     * This method handles user actions on the menu's
     *
     * @param e handles actionListeners
     */
    @Override
    public void actionPerformed(ActionEvent e) {

        //  Stores a variable with the source of the action event for
        //  readable event handling
        Object source = e.getSource();

        //  Names of menuItems that the user can act on is a comment to its
        //  preceding code
        //  Open:
        if (source == menuItem[0]) {
            openFile();
        }

        //  Save:
        if (source == menuItem[1]) {
            saveFile();
        }

        //  Exit:
        if (source == menuItem[2]) {

            //  Exit's the file directly if JTextArea is empty
            if (txtArea.getText().equals("")){
                System.exit(0);
            }
            else {
                exitFile(false);
            }
        }

        //  Text Wrap:
        if (source == menuItem[3]) {
            txtArea.setLineWrap(true);
            txtArea.setWrapStyleWord(true);
        }

        //  No Text Wrap:
        if (source == menuItem[4]) {
            txtArea.setLineWrap(false);
            txtArea.setWrapStyleWord(false);
        }

        //  Font:
        //  Assigns new font size to match the users size preference entered
        for (int i = 0; i < fontItem.length; i++) {
            if (source == fontItem[i]) {
                txtArea.setFont(new Font("Serif", Font.PLAIN,
                        ((i + 1) * 2)));
            }
        }

        //  Clear:
        //  If there is content in JTextArea, prompt user to save content
        if (source == menuItem[5] && !txtArea.getText().equals("")) {
                exitFile(true);
        }

        //  About:
        if (source == menuItem[6]) {
            JOptionPane.showMessageDialog(txtArea,
                    "Denne applikasjonen er laget av\nTobias Goulden Schultz" +
                            "\n\nDet er en enkel tekstbehandler.");
        }
    }

    /**
     * This method is main, it declares and initializes a new Object of
     * the class SchultzTobias
     */
    public static void main(String[] args) {
        SchultzTobias st = new SchultzTobias();
    }
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2015-05-27 18:31:54

自动资源管理

扫描器是可关闭的,所以您可以使用自动资源:

代码语言:javascript
复制
try (Scanner content = new Scanner(new File(fileName))) {
    ... rest of code goes here, don't need a content.close();
} catch (FileNotFoundException fnfe) {
    System.out.println("This error was thrown: " + fnfe);
}

菜单

有很多实现菜单的选项。使用数组和引用索引来确定它们位于哪个菜单下,并找出选择哪个菜单对于小型应用程序是可行的,但是在您决定重新组织菜单时,它不需要缩放,并且需要多个位置来更改索引引用。

如果使用javax.swing.AbstractAction的子类,则可以将操作的逻辑保持为单独的。另外,稍后还可以将相同的操作添加到菜单项和工具栏中。有关可以放入操作的属性,请参见行动javadoc。您可以使用多个构造函数和帮助方法创建AbstractAction的子类,用于设置和获取描述、图标、助记符等。

注释

您不需要以“这个类.”作为JavaDoc注释的开头。或者“这个方法.”请参阅方法描述以动词短语开头。部分。

有些样板不需要评论。例如,“导入”部分实际上不需要注释。另外,有些评论描述了发生了什么,而不是为什么(例如,“设置格式设置为整个单词的行.”),您只需有一个注释“”,除非有一行您认为会特别忘记为什么会出现这种情况。

不是什么大问题,但英语中的复数不使用撇号(例如菜单可以是菜单)。

编辑后添加:

可以在保持相同功能的同时缩短exitFile()。您的选项只有YES_OPTION和NO_OPTION,而且它们之间有重复的代码,不管如何,它们都可以执行:

代码语言:javascript
复制
public void exitFile(boolean clear) {

    //  Prompts user with options to store file, not to store file or
    int options = JOptionPane.showConfirmDialog(
            txtArea, "Vil du lagre først?");

    //  If user acted on the YES option
    if (options == JOptionPane.YES_OPTION) {
        saveFile();
    }

    // And first acted on the 'Clear' menuItem
    if (clear) {
        txtArea.setText("");

    // And first acted on the 'Exit' menuItem
    } else {
        System.exit(0);
    }
}
票数 3
EN

Code Review用户

发布于 2015-05-27 20:37:56

对代码的所有方面给予反馈

因此,这里有一个简短的反馈:

我注意到的东西很少,

  • 几乎所有的方法都是公开的(这需要吗?)
  • initializeMenus()是从ctor内部调用的,但is不是final
  • SchultzTobias可以子类(它不是final)
  • 大多数方法都可以被重写(当子类.)
  • menuItem[3]menu[2]是什么?(你只有很少的静态菜单项,也许你应该考虑使用mnuItmSavemnuItmOpen,.(为了更好地阅读)
  • exitFile(boolean clear)可以缩短(看看它,里面有重复的代码!)
  • exitFile(boolean clear)仅由MenuItem操作调用,而不是在关闭窗口时调用(例如,使用windows X-Button)。
  • setVisible()中调用ctor可以工作,但这是不寻常的(当子类化时可能是意外的)
  • 在出现异常时不关闭Closeables (如:PrintWriter)

干杯!

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/91911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档