Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从按钮/鼠标释放调用Java AbstractAction_Java_Swing_Jbutton_Actionlistener_Abstract Action - Fatal编程技术网

从按钮/鼠标释放调用Java AbstractAction

从按钮/鼠标释放调用Java AbstractAction,java,swing,jbutton,actionlistener,abstract-action,Java,Swing,Jbutton,Actionlistener,Abstract Action,在一个简单的计算器应用程序中,我使用抽象动作来处理用鼠标单击的按钮和相应的数字键盘键(带有键绑定)。我希望在使用键盘时发生某些外观上的变化,例如当我按下1号键时,改变1号按钮的边框。并在发布时将其更改回。这一切都有效。然后,我又开始用鼠标按下JButtons,意识到键释放动作永远不会被调用,显然是因为我没有使用键绑定。所以我的问题是,当鼠标释放/按钮启动时,有没有一种方法可以调用适当的已发布抽象操作 当我发现这一点时,我开始尝试: Abstract action(){ set border to

在一个简单的计算器应用程序中,我使用抽象动作来处理用鼠标单击的按钮和相应的数字键盘键(带有键绑定)。我希望在使用键盘时发生某些外观上的变化,例如当我按下1号键时,改变1号按钮的边框。并在发布时将其更改回。这一切都有效。然后,我又开始用鼠标按下JButtons,意识到键释放动作永远不会被调用,显然是因为我没有使用键绑定。所以我的问题是,当鼠标释放/按钮启动时,有没有一种方法可以调用适当的已发布抽象操作

当我发现这一点时,我开始尝试:

Abstract action(){
set border to this..
code..
code..
code..
set border to this..
}
所以不管是按键还是鼠标,它都会改变。然而,它并没有改变,或者可能发展得太快以至于无法检测到

在此实例中注册鼠标侦听器没有意义。无论如何我都试过了,但我似乎无法将抽象动作注册为鼠标侦听器

谢谢你的意见和建议

我注册actionlistener:

    btnMultiplication.addActionListener( operatorAction );
    btnDivision.addActionListener( operatorAction );
    btnAddition.addActionListener( operatorAction );
    btnSubtraction.addActionListener( operatorAction );
    btnSix.addActionListener( numberAction );
    btnSeven.addActionListener( numberAction );
    btnEight.addActionListener( numberAction );
*动作是抽象动作

我用这个键盘输入

im.put( KeyStroke.getKeyStroke( KeyEvent.VK_NUMPAD0, 0, false ), "Number" );
im.put( KeyStroke.getKeyStroke( KeyEvent.VK_NUMPAD0, 0, true ), "Number Released" );
am.put( "Number", numberAction );
am.put( "Number Released", numberActionR );
我使用Number操作来更改相应jbutton的边框。然后我使用Number Released再次更改边框


显然,当我用鼠标单击时,边框会高亮显示。但是发布的数字不会调用。就像我说的,将已发布的方面全部删除,并将第一个边界更改放在抽象操作的开始处,然后在抽象操作的结束处进行最后一个边界更改,显然速度太快,以至于您无法看到边界更改。

在处理键绑定时,许多人都会忽略一件事,您可以注册“按下”或“释放”事件(按下是默认设置)。所以在你的情况下,你需要两者兼而有之。“按下”事件应“启用”和“按下”按钮,“释放”应“取消启用”和“取消启用”按钮(顺序很重要),例如

我也会改变你的注意力。与其让键绑定触发所需的操作,不如让
JButton
操作
执行此操作,这将使您能够集中精力让键绑定更改按钮的状态,最好是通过使用按钮模型,这将允许触发按钮并调用相关的
操作

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.NAME;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridLayout(4, 3));
            add(createButton(7, KeyEvent.VK_7, KeyEvent.VK_NUMPAD7));
            add(createButton(8, KeyEvent.VK_8, KeyEvent.VK_NUMPAD8));
            add(createButton(9, KeyEvent.VK_9, KeyEvent.VK_NUMPAD9));
            add(createButton(4, KeyEvent.VK_4, KeyEvent.VK_NUMPAD4));
            add(createButton(5, KeyEvent.VK_5, KeyEvent.VK_NUMPAD5));
            add(createButton(6, KeyEvent.VK_6, KeyEvent.VK_NUMPAD6));
            add(createButton(1, KeyEvent.VK_1, KeyEvent.VK_NUMPAD1));
            add(createButton(2, KeyEvent.VK_2, KeyEvent.VK_NUMPAD2));
            add(createButton(3, KeyEvent.VK_3, KeyEvent.VK_NUMPAD3));
            add(createButton(0, KeyEvent.VK_0, KeyEvent.VK_NUMPAD0));
        }

        protected JButton createButton(int number, int... virtualKeys) {

            NumberAction na = new NumberAction(Integer.toString(number));
            JButton btn = new JButton(na);

            InputMap im = btn.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
            ActionMap am = btn.getActionMap();

            for (int virtualKey : virtualKeys) {

                im.put(KeyStroke.getKeyStroke(virtualKey, 0, false), "number-pressed");
                im.put(KeyStroke.getKeyStroke(virtualKey, 0, true), "number-released");

            }

            am.put("number-pressed", new NumberKeyPressedAction(btn, true));
            am.put("number-released", new NumberKeyPressedAction(btn, false));

            return btn;

        }

        public class NumberAction extends AbstractAction {

            public NumberAction(String name) {
                super(name);
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(getValue(NAME) + " was clicked");
            }

        }

        public class NumberKeyPressedAction extends AbstractAction {

            private final JButton btn;
            private final boolean pressed;

            public NumberKeyPressedAction(JButton btn, boolean pressed) {
                // You could just pass the button model, but this was easier...
                this.btn = btn;
                this.pressed = pressed;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                if (pressed) {
                    btn.getModel().setArmed(pressed);
                    btn.getModel().setPressed(pressed);
                } else {
                    btn.getModel().setPressed(pressed);
                    btn.getModel().setArmed(pressed);
                }
            }

        }

    }

}


因此,我想根据MadProgrammer给出的所选解决方案发布我的有效实现

我删除了jbutton的显式创建。我现在这样创建它们:

createButton( 3, 5, 1, 1, ".", "btnDecimal", KeyEvent.VK_DECIMAL );
    createButton( 1, 5, 1, 2, "0", "btnZero", KeyEvent.VK_0, KeyEvent.VK_NUMPAD0 );
    createButton( 1, 4, 1, 1, "1", "btnOne", KeyEvent.VK_1, KeyEvent.VK_NUMPAD1 );
    createButton( 2, 4, 1, 1, "2", "btnTwo", KeyEvent.VK_2, KeyEvent.VK_NUMPAD2 );
    createButton( 3, 4, 1, 1, "3", "btnThree", KeyEvent.VK_3, KeyEvent.VK_NUMPAD3 );
    createButton( 1, 3, 1, 1, "4", "btnFour", KeyEvent.VK_4, KeyEvent.VK_NUMPAD4 );
    createButton( 2, 3, 1, 1, "5", "btnFive", KeyEvent.VK_5, KeyEvent.VK_NUMPAD5 );
    createButton( 3, 3, 1, 1, "6", "btnSix", KeyEvent.VK_6, KeyEvent.VK_NUMPAD6 );
    createButton( 1, 2, 1, 1, "7", "btnSeven", KeyEvent.VK_7, KeyEvent.VK_NUMPAD7 );
    createButton( 2, 2, 1, 1, "8", "btnEight", KeyEvent.VK_8, KeyEvent.VK_NUMPAD8 );
    createButton( 3, 2, 1, 1, "9", "btnNine", KeyEvent.VK_9, KeyEvent.VK_NUMPAD9 );
createButton方法执行以下操作:

private void createButton( int x, int y, int h, int w, String actionCommand, String name, int... keys ) {

    nAction na = new nAction( actionCommand );
    JButton btn = new JButton( na );
    btn.setName( name );
    InputMap im = btn.getInputMap( WHEN_IN_FOCUSED_WINDOW );
    ActionMap am = btn.getActionMap();

    for ( int virtualKey : keys ) {

        im.put( KeyStroke.getKeyStroke( virtualKey, 0, false ), "number-pressed" );
        im.put( KeyStroke.getKeyStroke( virtualKey, 0, true ), "number-released" );

    }

    am.put( "number-pressed", new NumberKeyPressedAction( btn, true ) );
    am.put( "number-released", new NumberKeyPressedAction( btn, false ) );

    GridBagConstraints gbc_btn = new GridBagConstraints();
    // gbc_btnEquals.anchor = GridBagConstraints.WEST;
    gbc_btn.fill = GridBagConstraints.BOTH;
    gbc_btn.insets = new Insets( 0, 0, 5, 5 );
    gbc_btn.gridheight = h;
    gbc_btn.gridwidth = w;
    gbc_btn.gridx = x;
    gbc_btn.gridy = y;
    frame.getContentPane().add( btn, gbc_btn );
    btn.setBackground( new Color( 225, 225, 225 ) );
    btn.setBorder( BorderFactory.createLineBorder( Color.BLACK ) );

如您所见,我创建了MadProgrammer在其示例中所示的实例,并创建了对AbstractActions的引用。然后设置各种swing属性的属性,然后设置边框和背景。这大大减少了代码和变量的使用。旁注。createButton中的参数name及其用于命名按钮的名称将不再使用,并将被删除。

您如何实际注册针对按钮的关键操作?考虑提供一个说明你的问题的方法。这不是一个代码转储,而是您正在做的一个示例,它突出了您所遇到的问题。这将减少混乱和更好的反应,改变你的注意力。键绑定应该关注于修改按钮的状态,并通过按钮的模型(启用和按下)更新其状态。然后,应使用单独的
操作
,设置为执行所需操作的
JButton
。如果您更改按钮型号右侧的状态(按下/待命、手无寸铁/未按下),这将触发按钮操作事件并调用相关的
操作
…好的,我想我理解您的意思。我正在研究这一点,我想除了你如何动态地创建你的按钮之外,我完全理解了。你能解释一下使用NumberAction操作创建按钮时发生了什么吗?基本上,我创建了一个NumberAction,它使用传递的int值并将其转换为Strong,按钮使用该值设置按钮的文本。相反,您可以将int值传递给它,并在内部将其转换为NAME属性的字符串,并将int值用作操作的一部分。然后,该方法为每个虚拟键代码创建一个按下和释放键事件(我使用数字键和数字键盘键),然后创建“按下”操作,该操作根据按钮是否应按下或释放来更改按钮的状态。这些键绑定被附加到我使用窗口生成器在该项目视图中创建的按钮。您可以动态创建按钮。我没有。现在,根据您的示例,我基本上需要放弃整个视图类,重新开始。我已经把这个东西拆了好几次,并且已经重建了它,所以我现在要停止这个计算器项目的工作,在以后的某个时候重新访问它。好吧,与其创建按钮,不如改进方法来配置它们。我试着用这种方式实现它。然而,似乎我所有的按键都显示我点击了第九个。以下是我的实现: