简体   繁体   English

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

[英]JTextField appears in 2 locations when created inside paintComponent()

I am creating a minesweeper game, and what I want to do is to have a JTextField where the user inputs his name in order for his score to be saved in a file. 我正在创建一个扫雷游戏,我想要做的是拥有一个JTextField,用户可以在其中输入他的名字,以便将其分数保存在文件中。

My problem is that when I create a JTextField and add it to my Jpanel it appears in 2 locations. 我的问题是,当我创建JTextField并将其添加到Jpanel时,它会出现在2个位置。 Here is an image of what is happening ( https://i.imgur.com/Ao8dRo1.jpg ) 这是正在发生的事情的图像( https://i.imgur.com/Ao8dRo1.jpg

This is my code over-simplified. 这是我的代码过于简化。 I believe that I don't properly understand something about how the mechanism of the GUI works. 我相信我对GUI的工作原理不了解。

GUI.java 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 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();
        }
    }

}

I think the problem is that you have overridden paintComponent in your Board class. 我认为问题在于您在Board类中重写了paintComponent。 This method gets called every time the component needs to be drawn so a new text field will be added each time. 每次需要绘制组件时都会调用此方法,因此每次都会添加一个新的文本字段。

It would be better to add the text field in the constructor for your board class. 最好在董事会类的构造函数中添加文本字段。

I use the command textField.setBounds(290, 80, 135, 40); 我使用命令textField.setBounds(290,80,135,40); to place it where I want but it doesn't work. 将其放置在我想要的位置,但不起作用。 Why could this happen? 为什么会发生这种情况?

Swing was designed to used with layout managers. Swing旨在与布局管理器一起使用。 The default layout manager for a JPanel is the FlowLayout. JPanel的默认布局管理器是FlowLayout。 The FlowLayout will ignore the setBounds(...) statement and set the size/location of the text field based on the rules of the FlowLayout. FlowLayout将忽略setBounds(...)语句,并根据FlowLayout的规则设置文本字段的大小/位置。

So don't attempt to use a null layout and don't use setBounds(). 因此,请勿尝试使用null布局,也不要使用setBounds()。 Instead let the layout manager do its job. 而是让布局管理器完成其工作。

Also, you should be adding the components to the frame BEFORE you make the frame visible. 另外,在使框架可见之前,应将组件添加到框架。

I would suggest your code should be something like: 我建议您的代码应类似于:

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

The Board class should override the getPreferredSize() method of the Board to return your desired size so that the pack() method works properly. Board类应重写Board的getPreferredSize()方法以返回所需的大小,以便pack()方法正常工作。

The default layout manager for a JFrame is the BorderLayout . JFrame的默认布局管理器是BorderLayout So, now the top part of the frame will contain the text field centered and the main part of the frame will contain your Board class. 因此,现在框架的顶部将包含居中的文本字段,框架的主要部分将包含Board类。 Read the section from the Swing tutorial on How to Use BorderLayout to understand how the above code works. 阅读Swing教程中有关如何使用BorderLayout的部分,以了解上述代码的工作方式。

Also, the MouseListener should be added to the Board, not the JFrame. 另外,应该将MouseListener添加到开发板,而不是JFrame。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM