【问题标题】:Java Swing - Redrawing from handler classJava Swing - 从处理程序类重绘
【发布时间】:2019-10-26 21:18:20
【问题描述】:

所以我先把我的两个类的代码放在这里。

SquareSimp.java


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SquareSimp
{

    public static void main( String[] args )
    {
        FilledFrame frame = new FilledFrame();

        frame.setVisible( true );
    }
}

class FilledFrame extends JFrame
{
    int size = 400;

    public FilledFrame()
    {
        JButton butSmall   = new JButton("Small");
        JButton butMedium  = new JButton("Medium");
        JButton butLarge   = new JButton("Large");
        JButton butMessage = new JButton("Say Hi!");

        SquarePanel panel = new SquarePanel(this);
        JPanel butPanel = new JPanel();

        butSmall.addActionListener(new ButtonHandler1(this, 200){
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                size = 200;
                panel.repaint();
            }
        });

        butMedium.addActionListener(new ButtonHandler1(this, this.size){
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                size = 300;
                panel.repaint();
            }
        });

        butLarge.addActionListener(new ButtonHandler1(this, this.size){
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                size = 400;
                panel.repaint();
            }
        });



        butPanel.add(butSmall);
        butPanel.add(butMedium);
        butPanel.add(butLarge);
        butPanel.add(butMessage);
        add(butPanel, BorderLayout.NORTH);
        add(panel, BorderLayout.CENTER);

        setSize( size+100, size+100 );
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Exercise 2.
        //Anonymous implementations of listeners are very efficient when you do not need to pass parameters to the
        // constructor of the implemented listener.
        butMessage.addActionListener(new ActionListener()
                // An anonymous function. Creates an actionListener that shows a dialog.
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                JOptionPane.showMessageDialog(null, "Hiiii");
            }
        });

    }

}

class SquarePanel extends JPanel
{
    FilledFrame theApp;

    SquarePanel(FilledFrame app)
    {
        theApp = app;
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.green);
        g.fillRect(20, 20, theApp.size, theApp.size);
    }
}

ButtonHandler1.java

package Lab2;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// This is a class whose object will handle the event.
public class ButtonHandler1 implements ActionListener{
    private FilledFrame theApp;
    private int theSize;
    ButtonHandler1(FilledFrame app, int size){
        theApp = app;
        theSize = size;
    }

    public void actionPerformed(ActionEvent actionEvent) {
    }

}

到目前为止,一切正常,这很棒。但是,作为要求,我被要求为每个类制作一个按钮处理程序。有人可以向我解释一下我的 buttonHandler 到底在做什么吗?我觉得与其制作匿名函数并覆盖 actionPerformed 事件,不如用更好的方法来完成它(在 buttonhandler 类中创建事件并根据按下的按钮从那里影响大小)。我不知道该怎么做,所以任何解释的帮助都会很棒!

非常感谢!

布兰登

【问题讨论】:

    标签: java swing actionlistener actionevent


    【解决方案1】:

    *Listener 的任何处理程序都用于处理由正在侦听的对象生成的@​​987654322@。在主程序中,您似乎有几个按钮可以改变窗口的大小。

    如果你的类实现了 buttonHandler,你什么也没做,因为你的 actionPerformed 方法什么也没做。

    anonymous classes 是一种可接受的实现监听器的方式。但是,我更喜欢使用inner classes,因为它们更干净(恕我直言)并且仍然可以访问enclosing classstate

    这是您的处理程序类的外观:

    // This is a class whose object will handle the event.
    class ButtonHandler1 implements ActionListener {
       private FilledFrame theApp;
       private int         theSize;
    
       ButtonHandler1(FilledFrame app, int size) {
          theApp = app;
          theSize = size;
       }
    
       public void actionPerformed(ActionEvent actionEvent) {
          theApp.size = theSize;
          theApp.repaint();
       }
    }
    

    以下是将处理程序添加到按钮的调用。

          butSmall.addActionListener(new ButtonHandler1(this, 200));
          butMedium.addActionListener(new ButtonHandler1(this, 300));
          butLarge.addActionListener(new ButtonHandler1(this, 400));
    

    【讨论】:

    • 你说我应该如何修改代码?你会说我应该让 ButtonHandler1 成为 SquareSimp 的内部类吗?
    【解决方案2】:

    我不确定我是否理解了这个问题,但有两种方法可以重构您的代码:

    1. 完全删除您的ButtonHandler1 类并实现匿名类中的所有逻辑:
        //FilledFrame.java
    
        butSmall.addActionListener(new ActionListener(){
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                        FilledFrame.this.size = 200;
                        panel.repaint();
                    }
                });
    
    
    1. 您可以在 FilledFrame 类中添加一些 getter 和 setter 方法,并在 ButtonHandler1.actionPerformed 中调用这些方法来实现那里的逻辑,如下所示:
        package Lab2;
    
        import javax.swing.*;
        import java.awt.event.ActionEvent;
        import java.awt.event.ActionListener;
        // This is a class whose object will handle the event.
        public class ButtonHandler1 implements ActionListener{
            private FilledFrame theApp;
            private int theSize;
            ButtonHandler1(FilledFrame app, int size){
                theApp = app;
                theSize = size;
            }
    
            public void actionPerformed(ActionEvent actionEvent) {
                theApp.setSizeMember(200); //do not use theApp.setSize(), create a method with a different name
                theApp.getSquarePanel().repaint();
            }
    
        }
    

    我将在 FilledFrame 上创建 getter/setter 留给你。

    【讨论】:

      【解决方案3】:

      ButtonHandler1 并没有真正使用,因为传递给它的参数从未使用过,并且在构造它时会覆盖其单个方法。
      所以这个:

           butSmall.addActionListener(new ButtonHandler1(this, 200){
                  @Override
                  public void actionPerformed(ActionEvent actionEvent) {
                      size = 200;
                      panel.repaint();
                  }
            });
      

      可以不用构造ButtonHandler1

          butSmall.addActionListener(new ActionListener(){
              @Override
              public void actionPerformed(ActionEvent actionEvent) {
                  size = 200;
                  panel.repaint();
              }
          });
      

      或者使用 lambda 表达式:

          butSmall.addActionListener(actionEvent -> {
              size = 200;
              panel.repaint();
          });
      

      您可以通过多种方式实现您想要的功能。根据您写的内容,您可以像这样定义ButtonHandler1

      class ButtonHandler1 implements ActionListener{
          private final FilledFrame theApp;
          private final int theSize;
          ButtonHandler1(FilledFrame app, int size){
              theApp = app;
              theSize = size;
          }
      
          @Override
          public void actionPerformed(ActionEvent actionEvent) {
              theApp.size = theSize; //better use a setter in FilledFrame
              theApp.repaint();
          }
      }
      

      并像这样使用它:

          butSmall.addActionListener(new ButtonHandler1(this, 200));
      
          butMedium.addActionListener(new ButtonHandler1(this, 300));
      
          butLarge.addActionListener(new ButtonHandler1(this, 400));
      

      使ButtonHandler1 成为FilledFrame 中的内部类让事情变得更简单:

      class ButtonHandler1 implements ActionListener{
          private final int theSize;
          ButtonHandler1(int size){
              theSize = size;
          }
      
          @Override
          public void actionPerformed(ActionEvent actionEvent) {
              size = theSize;
              repaint();
          }
      }
      

      使用它:

          butSmall.addActionListener(new ButtonHandler1(200));
      
          butMedium.addActionListener(new ButtonHandler1(300));
      
          butLarge.addActionListener(new ButtonHandler1(400));
      

      【讨论】:

      • 谢谢,这有帮助。有很多方法可以做到这一点,尽管我被要求提供一个单独的按钮处理程序来处理所有三个按钮。你会说我应该使用内部类来创建按钮处理程序吗?
      • 如果您使用内部类,则无需传递引用即可访问 size 字段。但是你做的方式很好。
      • 还有一个注意事项,与您的实际问题无关。除非您覆盖某些内容,否则扩展 JFrame 被认为是不好的做法。通常最好在 JFrame 中放置一个 JPanel 并覆盖它并在该面板中进行绘画等。不用扩展 JFrame,只需使用它的一个实例。
      • @WJS 当然。我认为 OP 需要使用单独的类。这可能是一个错误的假设。我还假设关于扩展 JFrame 的评论是针对 OP 的。
      • @c0der 是的!有可能这就是 OP 所教的内容。
      猜你喜欢
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 2019-11-27
      相关资源
      最近更新 更多