在 paintComponent() 中创建时,JTextField 出现在 2 个位置

JTextField appears in 2 locations when created inside paintComponent()

我正在创建一个扫雷游戏,我想要做的是有一个 JTextField,用户可以在其中输入他的名字,以便将他的分数保存在一个文件中。

我的问题是,当我创建 JTextField 并将其添加到我的 Jpanel 时,它出现在 2 个位置。这是正在发生的事情的图像 (https://i.imgur.com/Ao8dRo1.jpg)

这是我过于简化的代码。我相信我没有正确理解 GUI 的机制是如何工作的。

GUI.java

public class GUI extends JFrame {
  //..
  //some variables here
  //...

  public GUI() {
        this.setTitle("Minesweeper Game");
        this.setSize(WIDTH, HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setResizable(false);
        this.setLayout(null);

        //This method does not involve any drawing, it only places data in some arrays that I later use in paintComponent() to draw stuff accordingly to what the data is
        setMinefield();


        Board board = new Board();
        this.setContentPane(board);

        Click click = new Click();
        this.addMouseListener(click);
    }

    public class Board extends JPanel {
        public void paintComponent (Graphics g) {
        //...    
        //Drawing tiles, smiley, counters
        //...

        //And now I draw the area for the JTextField, and I also create it and add it in the Jpanel
        JTextField textField = new JTextField();
        textField.setFont(new Font("Tahoma", Font.PLAIN, 35));
        textField.setBounds(290, 80, 135, 40); //<-- This correctly places the textField where I want. The second textField seems to appear in the exact center of the X axis of my window

        add(textField); //<-- Adding the textField to the Jpanel

        } //End of paintComponent()
    }//End of Board class
}//End of GUI class

Main.java

public class Main implements Runnable {

    GUI gui = new GUI();

    public static void main(String[] args) {
        new Thread (new Main()).start();
    }

    @Override
    public void run() {
        while (true) {
            gui.repaint();
        }
    }

}

我认为问题在于您已经覆盖了 Board 中的 paintComponent class。每次需要绘制组件时都会调用此方法,因此每次都会添加一个新的文本字段。

最好在开发板的构造函数中添加文本字段 class。

I use the command textField.setBounds(290, 80, 135, 40); to place it where I want but it doesn't work. Why could this happen?

Swing 旨在与布局管理器一起使用。 JPanel 的默认布局管理器是 FlowLayout。 FlowLayout 将忽略 setBounds(...) 语句并根据 FlowLayout 的规则设置文本字段的 size/location。

所以不要尝试使用空布局,也不要使用 setBounds()。而是让布局管理器完成它的工作。

此外,在使框架可见之前,您应该将组件添加到框架中。

我建议您的代码应该是这样的:

JTextField textField = new JTextField(10);
JPanel top = new JPanel();
top.add( textField );

Board board = new Board();

add(top, BorderLayout.PAGE_START);
add(board, BorderLayout.CENTER);
setResizable( false );
pack();
setVisible( true );

Board class 应该将 Board 的 getPreferredSize() 方法覆盖到 return 您想要的大小,以便 pack() 方法正常工作。

JFrame 的默认布局管理器是 BorderLayout。因此,现在框架的顶部将包含居中的文本字段,框架的主要部分将包含您的 Board class。阅读 How to Use BorderLayout 上的 Swing 教程部分,了解上述代码的工作原理。

此外,MouseListener 应该添加到 Board,而不是 JFrame。