仅当 JFrame 中的某些内容发生更改时才使 JButton 可单击

Make a JButton clickable only if something is changed in JFrame

我有一个带有 JTextFields、JComboBoxes 和 JLabel 的 JFrame。我想让按钮 "UPDATE" 仅在 window.

中的某些内容已更改(字段)时才可单击

I want to make the button "UPDATE" clickable only if something has been changed(fields) in the window.

您需要监听 "fields" 中的变化(无论它们应该是什么),并在您感兴趣的 JButton 上调用 setEnabled(true)setEnabled(false) -- 或更好的行动,取决于你的领域的状态。为什么 Action 更好?您可以让多个按钮和 JMenuItems 共享相同的 Action,并且通过调用 Actions 上的方法,您可以同时禁用两者。

例如,如果字段是 JTextFields,则向您的字段添加一个 DocumentListener,并根据侦听器中字段的状态,调用我上面提到的方法。

如果您需要更多具体帮助,那么您需要向我们提供更具体的信息和代码。


对于具有 5 个 JTextField 和一个 JButton 的示例,其中仅当文本出现在 every JTextField 中时 JButton 才处于活动状态:

package pkg;

import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

@SuppressWarnings("serial")
public class ButtonActiveTest extends JPanel {
    private static final int FIELD_COUNT = 5;

    private MyAction myAction = new MyAction("My Button"); // The Action
    private JButton myButton = new JButton(myAction);  // the button 
    private JTextField[] textFields = new JTextField[FIELD_COUNT];


    public ButtonActiveTest() {
        myAction.setEnabled(false); // initially disable button's Action

        // create single Doc listener
        MyDocumentListener myDocumentListener = new MyDocumentListener();
        // create jtext fields in a loop
        for (int i = 0; i < textFields.length; i++) {
            textFields[i] = new JTextField(5); // create each text field

            // add document listener to doc
            textFields[i].getDocument().addDocumentListener(myDocumentListener);

            // add to gui
            add(textFields[i]);
        }
        add(myButton);

    }

    private static void createAndShowGui() {
        ButtonActiveTest mainPanel = new ButtonActiveTest();

        JFrame frame = new JFrame("ButtonActiveTest");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }

    private class MyAction extends AbstractAction {
        public MyAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic); // to give button an alt-key hotkey
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JOptionPane.showMessageDialog(ButtonActiveTest.this, "Button Pressed");
        }
    }

    private class MyDocumentListener implements DocumentListener {

        @Override
        public void changedUpdate(DocumentEvent e) {
            checkFields();
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            checkFields();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            checkFields();
        }

        // if any changes to any document (any of the above methods called)
        // check if all JTextfields have text. If so, activate the action
        private void checkFields() {
            boolean allFieldsHaveText = true;
            for (JTextField jTextField : textFields) {
                if (jTextField.getText().trim().isEmpty()) {
                    allFieldsHaveText = false;
                }
            }

            myAction.setEnabled(allFieldsHaveText);
        }

    }
}

显示相似的代码,但现在 JMenuItem 与 JButton 共享相同的 Action。注意菜单项和按钮都是active/inactive并列的:

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

@SuppressWarnings("serial")
public class ButtonActiveTest extends JPanel {
    private static final int FIELD_COUNT = 5;

    private MyAction myAction = new MyAction("Process Data in Fields"); // The Action
    private JButton myButton = new JButton(myAction);  // the button 
    private JTextField[] textFields = new JTextField[FIELD_COUNT];
    private JMenuBar menuBar = new JMenuBar();


    public ButtonActiveTest() {
        myAction.setEnabled(false); // initially disable button's Action

        // create single Doc listener
        MyDocumentListener myDocumentListener = new MyDocumentListener();
        // create jtext fields in a loop
        for (int i = 0; i < textFields.length; i++) {
            textFields[i] = new JTextField(5); // create each text field

            // add document listener to doc
            textFields[i].getDocument().addDocumentListener(myDocumentListener);

            // add to gui
            add(textFields[i]);
        }
        add(myButton);

        // create menu item with our action
        JMenuItem menuItem = new JMenuItem(myAction);
        JMenu menu = new JMenu("Menu");
        menu.setMnemonic(KeyEvent.VK_M);
        menu.add(menuItem);
        menuBar.add(menu);
    }

    public JMenuBar getMenuBar() {
        return menuBar;
    }

    private static void createAndShowGui() {
        ButtonActiveTest mainPanel = new ButtonActiveTest();

        JFrame frame = new JFrame("ButtonActiveTest");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.setJMenuBar(mainPanel.getMenuBar());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }

    private class MyAction extends AbstractAction {
        public MyAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic); // to give button an alt-key hotkey
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JOptionPane.showMessageDialog(ButtonActiveTest.this, "Action Performed!");
        }
    }

    private class MyDocumentListener implements DocumentListener {

        @Override
        public void changedUpdate(DocumentEvent e) {
            checkFields();
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            checkFields();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            checkFields();
        }

        // if any changes to any document (any of the above methods called)
        // check if all JTextfields have text. If so, activate the action
        private void checkFields() {
            boolean allFieldsHaveText = true;
            for (JTextField jTextField : textFields) {
                if (jTextField.getText().trim().isEmpty()) {
                    allFieldsHaveText = false;
                }
            }

            myAction.setEnabled(allFieldsHaveText);
        }

    }
}