簡體   English   中英

通過按下 JButton 向 JTextField 輸入數據

[英]Inputting data to JTextField by pressing JButton

我編寫了一個程序,根據用戶選擇的難度級別創建數獨板。 有一個使用 JFrame 和 JPanel 的基本 GUI。 該板本身是使用 JTextFields 的 2D 數組構建的,以允許用戶進行編輯,我制作了一個代表數字 1-9 的 JButtons 表。 我正在努力做到這一點,所以當我的 cursor 在相關文本字段上時按下數字按鈕時,它會將該數字輸入到該字段中。 我認為我定義按鈕的方式存在問題,但我會喜歡手。 順便說一句,這是我的第一個官方堆棧溢出問題,所以提前感謝所有幫助的人:)

    /*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 class,因為構建電路板的數學邏輯部分是可靠的並且工作正常。 這就是板子 class 是什么。

一種方法可能是:

  • 將 JTextFields 放在ArrayList<JTextField>中,以便稍后獲取它們,因為您可能需要在游戲期間訪問它們
  • 給class一個字段, private JTextField selectedField = null; ,最初設置為null 這將指向最后一個被點擊的 JTextField(最后一個獲得焦點
  • 創建時提供 JTextFields FocusListeners。 如果任何字段獲得焦點,請將 selectedField 設置為引用它
  • 或者按照 Rob Camick 的說法,使用 TextAction 作為按鈕的 ActionListener,它將跟蹤保持焦點的最后一個文本組件。
  • 在你的號碼 JButton 的 ActionListener 中,檢查 selectedField 是否不是 null
  • 如果不是 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。

你可以給 class 一個私有的 boolean 字段,比如說,

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

以及擴展 DocumentFilter 的私有嵌套 class。 只要 blockTextInput 為真,此 class 將阻止文檔允許字符串插入、刪除或替換:

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);
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM