代码之家  ›  专栏  ›  技术社区  ›  Kevin Griffin

打开字符串/执行按钮操作

  •  1
  • Kevin Griffin  · 技术社区  · 17 年前

    完整免责声明:我是一名CS学生,这个问题与最近分配的面向对象编程Java程序有关。虽然我们已经做了一些控制台的工作,但这是我们第一次使用GUI和Swing或Awt。我们得到了一些代码,这些代码创建了一个包含一些文本的窗口和一个按钮,该按钮在文本的不同颜色之间旋转。然后我们被要求修改程序,为颜色创建单选按钮,而不是这也是为了让我们练习研究API。我已经交了作业,并且得到了老师的许可,可以在这里发布代码。

    在Java中实现按钮操作的最佳方法是什么?在做了一些修改之后,我创建了如下按钮:

    class HelloComponent3 extends JComponent
        implements MouseMotionListener, ActionListener
    {
        int messageX = 75, messageY= 175;
    
        String theMessage;
        String redString = "red", blueString = "blue", greenString = "green";
        String magentaString = "magenta", blackString = "black", resetString = "reset";
    
        JButton resetButton;
        JRadioButton redButton, blueButton, greenButton, magentaButton, blackButton;
        ButtonGroup colorButtons;
    
        public HelloComponent3(String message) {
    
        theMessage = message;
    
        //intialize the reset button
        resetButton = new JButton("Reset");
        resetButton.setActionCommand(resetString);
        resetButton.addActionListener(this);
    
        //intialize our radio buttons with actions and labels
        redButton = new JRadioButton("Red");
        redButton.setActionCommand(redString);
        ...
    

    并添加了动作侦听器。。。

    redButton.addActionListener(this);
    blueButton.addActionListener(this);
    ...
    

    已经为actionPerformed方法创建了一个存根,让我们了解如何使用它,但是由于模板中只有一个按钮,因此不清楚如何实现多个按钮。我试着打开一个字符串,但很快意识到,因为字符串不是一个基本类型,所以我不能将它用于switch语句。我本可以用if-else链即兴创作,但这正是我想到的。这似乎远远不够优雅,一定有更好的办法。如果有,是什么?有办法打开字符串吗?或者以更具可伸缩性的方式选择一个动作?

    public void actionPerformed(ActionEvent e){
    
        if (e.getActionCommand().equals(resetString)) {
            messageX = 75; messageY = 175;
            setForeground(Color.black);
            blackButton.setSelected(true);
            repaint();
            return;
        }
    
        if ( e.getActionCommand().equals(redString) ) {
            setForeground(Color.red);
            repaint();
            return;
        }
    
        if ( e.getActionCommand().equals(blueString) ) {
            setForeground(Color.blue);
            repaint();
            return;
        }
    
        if ( e.getActionCommand().equals(greenString) ) {
            setForeground(Color.green);
            repaint();
            return;
        }
    
        if ( e.getActionCommand().equals(magentaString) ) {
            setForeground(Color.magenta);
            repaint();
            return;
        }
    
        if ( e.getActionCommand().equals(blackString) ) {
            setForeground(Color.black);
            repaint();
            return;
        }
    }
    
    5 回复  |  直到 17 年前
        1
  •  1
  •   Patrick Huizinga    17 年前

    而不是写这封信:

    resetButton.addActionListener(this);
    

    你也可以这样写:

    resetButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            resetButtonActionPerformed(evt);
        }
    });
    

    public void resetButtonActionPerformed(ActionEvent evt) {
        messageX = 75; messageY = 175;
        setForeground(Color.black);
        blackButton.setSelected(true);
        repaint();
    }
    

    我不知道这是否是最优雅的解决方案,但至少你不再有那么大的if构造。

        2
  •  0
  •   finnw    17 年前

    1. 创建一个实现Action接口的新类,该类具有一个颜色字段和一个设置颜色的actionPerformed方法
    2. Mantain从命令名到颜色实例的哈希映射,并在映射中查找命令名
        3
  •  0
  •   plinth    17 年前

    一个足够体面的方法是声明 enum whose elements match your strings

    避免匿名内部类的原因可能是因为该类尚未具有该构造,即使这可能是最好的解决方案。

        4
  •  0
  •   Draemon    17 年前

    如前所述,您可以使用匿名内部类来实现ActionListener接口。或者,您不必使用匿名内部类,但可以使用简单的嵌套类:

    resetButton = new JButton(new ResetAction());
    redButton = new JButton(new ColorAction("Red", Color.red));
    

    然后。。。

    private class ResetAction extends AbstractAction {
        public ResetAction() {
            super("Reset");
        }
    
        public void actionPerformed(ActionEvent e) {
            messageX = 75; messageY = 175;
            setForeground(Color.black);
            blackButton.setSelected(true);
            repaint();
        }
    }
    
    private class ResetAction extends AbstractAction {
        private Color color;
    
        public ColorAction(String title, Color color) {
            super(title);
            this.color = color;
        }
    
        public void actionPerformed(ActionEvent e) {
            setForeground(color);
            repaint();
        }
    }
    

    有关此方法(或任何涉及内部类的方法)优于在外部类中实现ActionListener的原因,请参阅“设计模式”:

    “偏爱‘对象组合’而非‘类继承’”(四人帮1995:20)

    在匿名内部类和这些命名内部类之间进行选择在很大程度上是一个风格问题,但我认为这个版本更容易理解,并且在有大量操作时更清晰。

        5
  •  -1
  •   Tom Hawtin - tackline    17 年前

    在您的示例中,您似乎将JComponent用作JPanel。没有太大的区别,但是使用JPanel来收集一块小部件。此外,不太可能需要对它进行子类化,所以不要这样做。

    例如:

       addColorButton("Green" , Color.GREEN );
       addColorButton("Red"   , Color.RED   );
       addColorButton("Yellow", Color.YELLOW);
       addColorButton("Blue"  , Color.BLUE  );
       ...
    
    private void addColorButton(String label, Color color) {
        JRadioButton button = new JRadioButton(label);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                target.setForeground(color);
                target.repaint();
            } 
        });
        colorGroup.add(button);
        panel.add(button);
    }
    
    推荐文章