【问题标题】:Inputting data to JTextField by pressing JButton通过按下 JButton 向 JTextField 输入数据
【发布时间】:2022-08-04 07:42:23
【问题描述】:

我编写了一个程序,根据用户选择的难度级别创建数独板。有一个使用 JFrame 和 JPanel 的基本 GUI。
板本身是使用 JTextField 的 2D 数组构建的,以允许用户进行编辑,我制作了一个代表数字 1-9 的 JButton 表。
我试图做到这一点,所以当我在光标位于相关文本字段上时按下数字按钮时,它会将该数字输入到该字段中。 我认为我定义按钮的方式存在问题,但我会喜欢手。

    /*Java Program to solve Sudoku problem using Backtracking*/
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.*;


public class Solver extends Board {

    Solver(int N, int K) {
        super(N, K);
    }

    private static void createWindow() {
        JFrame frame = new JFrame(\"Sudoku\");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        createUI(frame);
        frame.setSize(250, 80);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static void createUI(final JFrame frame) {
        JPanel panel = new JPanel();
        LayoutManager layout = new FlowLayout();
        panel.setLayout(layout);

        JButton button = new JButton(\"Play\");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String result = (String) JOptionPane.showInputDialog(
                    frame,
                    \"Difficulty Glossary:\\n\\n Hard - 50/81 blank spaces\\n Medium - 35/81 blank spaces\\n Easy - 20/81 blank spaces\\n\\nChoose your desired difficulty:\\n\\tHard: 1\\n\\tMedium: 2\\n\\tEasy: 3\\nIf your input doesn\'t match one of these digits, the board generated will be on easy mode.\",
                    \"Difficulty Glossary\",
                    JOptionPane.PLAIN_MESSAGE,
                    null,
                    null,
                    \"3\"
                );
                optionBoard();
                play(Integer.parseInt(result));
            }
        });

        panel.add(button);
        frame.getContentPane().add(panel, BorderLayout.CENTER);
    }
    public static void optionBoard(){

    }

    public static void play(int level) {
        int N = 9, K = 0;
        switch (level) {
            case 1:
                K = 50;
                break;
            case 2:
                K = 35;
                break;

            default:
                K = 20;
                break;
        }
        Solver sudoku = new Solver(N, K);
        sudoku.fillValues();
        createBoard(sudoku.puzzle);
    }

    public static void createBoard(int[][] puzzle) {
        final Border fieldBorder = BorderFactory.createLineBorder(Color.BLACK);

        final JPanel grid = new JPanel(new GridLayout(9, 9));
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                final JTextField field = new JTextField(2);
                if (puzzle[i][j] != 0) {
                    field.setText(puzzle[i][j] + \"\");
                } else {
                    field.setText(\"\");
                }
                field.setHorizontalAlignment(JTextField.CENTER); //Center text horizontally in the text field.
                field.setBorder(fieldBorder); //Add the colored border.
                grid.add(field);
            }
        }

        final JPanel digits = new JPanel(new GridLayout(3, 3));
        int num=1;
        for (int i = 1; i < 4; i++) {
            for (int j = 1; j < 4; j++) {
                final JButton digit = new JButton(num+\"\");
                num++;
                
                digits.add(digit);
            }
        }

        final JPanel centeredGrid = new JPanel(new GridBagLayout());
        centeredGrid.add(digits);
        centeredGrid.add(grid);
    
        final JFrame frame = new JFrame(\"Sudoku Board\");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(centeredGrid);
        frame.setSize(400,400);
        frame.setVisible(true);

        JButton button = new JButton(\"Check\");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                
            }
        });

       // centeredGrid.add(button);
    }


    // Driver code
    public static void main(String[] args) {
        createWindow();
    }
}

我只提供了相关的 GUI 类,因为构建电路板的数学逻辑部分是可靠的并且工作正常。这就是 Board 类。

  • 恐怕我分心了。您真正的问题是如何在按下 JButton 时更新一些 JTextField 吗?
  • 请参阅我的答案的编辑。如果您对此有任何疑问,请在答案中发表评论。

标签: java swing jbutton actionlistener jtextfield


【解决方案1】:

一种方法可能是:

  • 将 JTextFields 放入 ArrayList&lt;JTextField&gt; 以便稍后获取它们,因为您可能需要在游戏期间访问它们
  • 给类一个字段private JTextField selectedField = null;,最初设置为null。这将指向最后一个被点击的 JTextField(最后一个获得重点)
  • 在创建时提供 JTextFields FocusListeners。如果任何字段获得焦点,请将 selectedField 设置为引用它
  • 或者根据 Rob Camick,使用 TextAction 作为按钮的 ActionListener,它将跟踪最后一个保持焦点的文本组件。
  • 在你的号码 JButton 的 ActionListener 中,检查 selectedField 是否不为空
  • 如果不为 null,则将按钮的 actionCommand(其文本)设置为 selectedField 的文本。

此外,如果您需要更多帮助,请考虑创建并发布有效的MRE。您当前的代码无法为我们编译。

概念证明(以及MRE 的示例):

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

public class Solver2 extends JPanel {
    private static final float FONT_SIZE = 24f;
    private int gridEdgeSize = 9;
    private List<JTextField> fieldList = new ArrayList<>();
    private JTextField selectedField = null;

    public Solver2() {
        JPanel gridPanel = new JPanel(new GridLayout(gridEdgeSize, gridEdgeSize, 2, 2));
        gridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
        gridPanel.setBackground(Color.BLACK);

        for (int i = 0; i < gridEdgeSize; i++) {
            for (int j = 0; j < gridEdgeSize; j++) {
                JTextField textField = new JTextField(2);
                textField.setHorizontalAlignment(SwingConstants.CENTER);
                textField.setFont(textField.getFont().deriveFont(Font.BOLD, FONT_SIZE));
                textField.setBorder(null);
                textField.addFocusListener(new TextFieldFocusListener());
                gridPanel.add(textField);
                fieldList.add(textField);
            }
        }

        JPanel numberPanel = new JPanel(new GridLayout(0, 3));
        for (int i = 1; i < 10; i++) {
            String text = String.valueOf(i);
            JButton button = new JButton(text);
            button.setFont(button.getFont().deriveFont(Font.BOLD, FONT_SIZE));
            button.addActionListener(e -> buttonListener(e));
            numberPanel.add(button);
        }

        setLayout(new GridLayout(1, 2));
        add(gridPanel);
        add(numberPanel);

    }
    
    private void buttonListener(ActionEvent e) {
        String text = e.getActionCommand();
        if (selectedField != null) {
            selectedField.setText(text);
        }
    }

    private class TextFieldFocusListener extends FocusAdapter {
        @Override
        public void focusGained(FocusEvent e) {
            selectedField = (JTextField) e.getComponent();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Solver2 mainPanel = new Solver2();

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

}

边注

如果您想限制 JTextField 允许键盘或复制/粘贴输入,那么一种方法可能是使用添加到每个 JTextField 文档的 DocumentFilter。

你可以给类一个私有的布尔字段,比如说,

public class Solver2 extends JPanel {
    // .....
    private boolean blockTextInput = true;

和一个扩展 DocumentFilter 的私有嵌套类。只要 blockTextInput 为真,此类将阻止文档允许字符串插入、删除或替换:

private class MyDocFilter extends DocumentFilter {
    @Override
    public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
            throws BadLocationException {
        if (blockTextInput) {
            return;
        }
        super.insertString(fb, offset, string, attr);
    }
    
    @Override
    public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
        if (blockTextInput) {
            return;
        }
        super.remove(fb, offset, length);
    }
    
    @Override
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
            throws BadLocationException {
        if (blockTextInput) {
            return;
        }
        super.replace(fb, offset, length, text, attrs);
    }
}

然后在 JTextField 创建循环中,设置过滤器:

for (int i = 0; i < gridEdgeSize; i++) {
    for (int j = 0; j < gridEdgeSize; j++) {
        JTextField textField = new JTextField(2);
        textField.setHorizontalAlignment(SwingConstants.CENTER);
        textField.setFont(textField.getFont().deriveFont(Font.BOLD, FONT_SIZE));
        textField.setBorder(null);
        textField.addFocusListener(new TextFieldFocusListener());
        
        // ***** here ****
        ((PlainDocument) textField.getDocument()).setDocumentFilter(new MyDocFilter());  
        
        gridPanel.add(textField);
        fieldList.add(textField);
    }
}

然后在设置JTextField的文本前后改变JButton的ActionListeners的数量来改变blockTextInput:

private void buttonListener(ActionEvent e) {
    String text = e.getActionCommand();
    if (selectedField != null) {
        blockTextInput = false;
        selectedField.setText(text);
        blockTextInput = true;
    }
}

完毕


该程序的最新迭代使用单个 FocusListener 和 DocumentFilter,并结合了 Rob Camick 的建议,即使用 TextAction 作为按钮的 ActionListener:

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
import javax.swing.text.TextAction;

@SuppressWarnings("serial")
public class Solver3 extends JPanel {
    private static final float FONT_SIZE = 24f;
    private int gridEdgeSize = 9;
    private List<JTextField> fieldList = new ArrayList<>();
    private boolean blockTextInput = true;
    private MyTextAction myTextAction = new MyTextAction("");
    private JPanel outerGridPanel = new JPanel(new GridLayout(3, 3, 3, 3));
    private JPanel[][] innerGridPanels = new JPanel[3][3];

    public Solver3() {
        outerGridPanel.setBackground(Color.BLACK);
        outerGridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 4));
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                innerGridPanels[i][j] = new JPanel(new GridLayout(3, 3, 1, 1));
                innerGridPanels[i][j].setBackground(Color.BLACK);
                outerGridPanel.add(innerGridPanels[i][j]);
            }
        }

        for (int i = 0; i < gridEdgeSize; i++) {
            for (int j = 0; j < gridEdgeSize; j++) {
                JTextField textField = new JTextField(2);
                textField.setHorizontalAlignment(SwingConstants.CENTER);
                textField.setFont(textField.getFont().deriveFont(Font.BOLD, FONT_SIZE));
                textField.setBorder(null);
                ((PlainDocument) textField.getDocument()).setDocumentFilter(new MyDocFilter());
                innerGridPanels[i / 3][j / 3].add(textField);
                fieldList.add(textField);
            }
        }

        JPanel numberPanel = new JPanel(new GridLayout(0, 3));
        for (int i = 1; i < 10; i++) {
            String text = String.valueOf(i);
            JButton button = new JButton(text);
            button.setFont(button.getFont().deriveFont(Font.BOLD, 2 * FONT_SIZE));
            button.addActionListener(myTextAction);
            numberPanel.add(button);
        }

        setLayout(new GridLayout(1, 2));
        add(outerGridPanel);
        add(numberPanel);
    }

    private class MyTextAction extends TextAction {

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

        @Override
        public void actionPerformed(ActionEvent e) {
            String text = e.getActionCommand();
            JTextComponent selectedComponent = getFocusedComponent();
            
            if (selectedComponent != null) {
                blockTextInput = false;
                selectedComponent.setText(text);
                blockTextInput = true;
            }
        }
    }

    private class MyDocFilter extends DocumentFilter {
        @Override
        public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
                throws BadLocationException {
            if (blockTextInput) {
                return;
            }
            super.insertString(fb, offset, string, attr);
        }

        @Override
        public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
            if (blockTextInput) {
                return;
            }
            super.remove(fb, offset, length);
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
                throws BadLocationException {
            if (blockTextInput) {
                return;
            }
            super.replace(fb, offset, length, text, attrs);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Solver3 mainPanel = new Solver3();

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-11
    • 2017-04-26
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多