只有在JFrame中发生改变时,才能使JButton可点击。

3

我有一个包含JTextFields、JComboBoxes和JLabels的JFrame。我希望只有在窗口中的某些内容(字段)被更改时,才能使按钮“UPDATE”可点击。


button.setEnabled(true) - Aditya Ramkumar
1个回答

5
如果在窗口中有内容发生改变(fields),你需要监听这些"fields"的变化,然后在监听器中对你感兴趣的JButton调用setEnabled(true)或setEnabled(false)方法--或者更好的是对其Action进行操作,具体取决于fields的状态。为什么Action更好?因为你可以让多个按钮和菜单项共享同一个Action,并通过调用Action上的方法来同时禁用它们。
例如,如果fields是JTextFields,则向fields添加DocumentListener,根据监听器中的fields状态调用上述方法。
如果需要更具体的帮助,您需要提供更具体的信息和代码。
以下是一个包含5个JTextFields和一个JButton的示例,其中只有在每个 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相同的操作。请注意,菜单项和按钮都是同时处于活动/非活动状态:
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);
        }

    }
}

我不能同时监听所有组件吗?您提出的解决方案需要我为每个组件添加一个监听器,是这样吗? - HeXMaN
1
如果您这样做,您可以为所有元素使用相同的侦听器。这意味着您只需要将 foo.addActionListener(bar); 添加到您的元素中即可。一个很好的例子是https://dev59.com/KG025IYBdhLWcg3wjGxO - Stephen Buttolph
1
@SainandShinde:没什么大不了的,你可以在for循环中为所有字段(如果是JTextFields或所有相同类型的字段)添加单个监听器,就像我上面展示的那样(请参见答案的编辑)。但是,如果您需要更具体的帮助,请通过告诉我们“字段”是什么并显示相关代码来改进您的问题。您的问题缺少重要细节。 - Hovercraft Full Of Eels
非常抱歉提出这样抽象的问题。时间不多了,需要提交项目。您的示例解决了我的问题。对于 putValue(MNEMONIC_KEY, mnemonic); 给予加分。我会立即添加此功能。 - HeXMaN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接