【问题标题】:JAVA Swing JButton ActionPerformed method implementation .getSource methodJAVA Swing JButton ActionPerformed 方法实现 .getSource 方法
【发布时间】:2017-12-16 19:46:41
【问题描述】:

我是 Java Swing 的初学者。我试图创建一个只有 + 和 - 的简单计算器。我使用 JButtons 来表示“+”和“-”,并添加了 actionListener 来响应每个按钮。但是,我真的不明白为什么 e.getSource() 不起作用。是动态调度问题吗?非常感谢您的帮助!

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.*;

import javax.swing.*;

class MenuExample implements ActionListener {
    // JMenu menu1, menu2, menu3;
    // JMenuItem i1, i2, i3, i4, i5;
    JTextArea t1, t2;
    JTextField t3;
    JButton b1, b2;

    MenuExample() {
        JFrame f = new JFrame("Menu and MenuItem EX");
        final JButton b1 = new JButton("+"); 
        final JButton b2 = new JButton("-");
        t3 = new JTextField();t3.setBounds(50, 350, 200, 30); t3.setEditable(false);
        t1 = new JTextArea(); t1.setBounds(50,100,200,30);
        t2 = new JTextArea(); t2.setBounds(50,250,200,30);
        b1.addActionListener(this);
        b2.addActionListener(this); 
        b1.setBounds(50, 450, 30, 30); b2.setBounds(100, 450, 30, 30); 
        f.add(b1); f.add(b2);f.add(t1); f.add(t2); f.add(t3);

        f.setSize(800, 800);
        f.setLayout(null);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JButton button;
        int answer=0;
        String s1 = t1.getText(); 
        String s2 = t2.getText();
        int a = Integer.parseInt(s1);
        int b = Integer.parseInt(s2);

        Object source = e.getSource();
        if (source instanceof JButton) {
            button = (JButton) source;
            System.out.println("called here at least?");
            System.out.println(button.getClass());
            if (button == b1) {
                answer = a + b;
            }
            else if (button == b2) {
                answer = a - b;
            }
        }
        String result = String.valueOf(answer);
        t3.setText(result);
    }
}

public class JMenuPractice {
    public static void main (String[] args) {
        new MenuExample();
    }
}

【问题讨论】:

    标签: java swing


    【解决方案1】:

    您通过在构造函数中重新声明 b1 和 b2 JButton 字段来隐藏它们:

    class MenuExample implements ActionListener {
        JTextArea t1, t2;
        JTextField t3;
        JButton b1, b2;  // these stay null!!!
    
        MenuExample() {
            JFrame f = new JFrame("Menu and MenuItem EX");
    
            // Don't re-declare the variables here!
            final JButton b1 = new JButton("+");  
            final JButton b2 = new JButton("-");
    

    这会使字段为空,并且您在侦听器中的相等性测试将不起作用。解决方案:不要阴影!而是使用您已有的字段:

    class MenuExample implements ActionListener {
        JTextArea t1, t2;
        JTextField t3;
        JButton b1, b2;  // these are no longer null
    
        MenuExample() {
            JFrame f = new JFrame("Menu and MenuItem EX");
    
            // final JButton b1 = new JButton("+"); 
            // final JButton b2 = new JButton("-");
            b1 = new JButton("+");
            b2 = new JButton("-");
    

    注意到巨大的不同了吗?

    其他问题:

    • 不要使用空布局和setBounds。虽然空布局和setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整您的组件大小,它们是增强或维护的皇家女巫,放置在滚动窗格中时它们完全失败,在与原始不同的所有平台或屏幕分辨率上查看时它们看起来很糟糕.
    • 考虑为您的听众使用匿名内部类。那么你甚至不需要使用.getSource()

    由于您使用空布局和setBounds,这就是我运行时您的 GUI 的样子:

    如果您使用布局和匿名侦听器,代码可能类似于下面的 GUI。请注意,我喜欢使用 JSpinners 而不是 JTextFields 进行输入,因为这会将输入限制为数字:

    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.Insets;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class SimpleCalc extends JPanel {
        private static final int GAP = 4;
        private JSpinner spinner1 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000, 1));
        private JSpinner spinner2 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000, 1));
        private JTextField resultField = new JTextField(10);
        private JButton addButton = new JButton("+");
        private JButton subtractButton = new JButton("-");
    
        public SimpleCalc() {
            // add anonymous listeners to each JButton
            addButton.addActionListener(e -> add());
            subtractButton.addActionListener(e -> subtract());
    
            // put both buttons within a JPanel that uses grid layout
            // 1 row, variable number of columns, gap between components
            JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
            buttonPanel.add(addButton);
            buttonPanel.add(subtractButton);
    
            resultField.setFocusable(false);
            resultField.setEditable(false);
    
            setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
            // use GridBagLayout
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            // start at x position is 0, and stay there
            gbc.gridx = 0;
            // y position increments each time
            gbc.gridy = GridBagConstraints.RELATIVE;
            // stretch components horizontally not vertically
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.weightx = 1.0;
            gbc.weighty = 1.0;
            // gap between componentns
            gbc.insets = new Insets(GAP, GAP, GAP, GAP);
    
            add(spinner1, gbc);
            add(spinner2, gbc);
            add(resultField, gbc);
            add(buttonPanel, gbc);
        }
    
        public void add() {
            int value1 = (int) spinner1.getValue();
            int value2 = (int) spinner2.getValue();
            int result = value1 + value2;
            resultField.setText(String.valueOf(result));
        }
    
        public void subtract() {
            int value1 = (int) spinner1.getValue();
            int value2 = (int) spinner2.getValue();
            int result = value1 - value2;
            resultField.setText(String.valueOf(result));
        }
    
        private static void createAndShowGui() {
            SimpleCalc mainPanel = new SimpleCalc();
    
            JFrame frame = new JFrame("SimpleCalc");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    显示为:

    【讨论】:

    • 非常感谢这个有用的答案!对于使用 setBounds 和 null 布局的替代方案,您是否只使用布局管理器?像 flowLayout 和 BorderLayout 一样?
    • @ChatSev:是的,您可以使用 BorderLayout 和 FlowLayout。我经常嵌套 JPanel,每个都使用自己的布局。上面的示例同时使用了 GridLayout 和 GridBagLayout。阅读Layout Manager Tutorial了解更多信息。
    【解决方案2】:

    actionPerformed 函数中,您使用JButtons b1b2 声明为Class members,这没问题,但您应该注意到您声明了新的JButtons b1 和@ 987654328@ 在您的Constructor 中:

     final JButton b1 = new JButton("+"); 
     final JButton b2 = new JButton("-");
    

    ActionListener 附加到这两个,而不是您在 actionPerformed() 中使用的声明为 Class members 的那些。

    因此,与其遮蔽他们,不如这样做:

    b1 = new JButton("+"); 
    b2 = new JButton("-");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      相关资源
      最近更新 更多