JTextField появляется в 2 местах при создании внутри paintComponent () - PullRequest
2 голосов
/ 06 июня 2019

Я создаю игру тральщика, и я хочу, чтобы у меня был JTextField, где пользователь вводит свое имя для сохранения своего счета в файле.

Моя проблема в том, что когда я создаю JTextField и добавляю его в свою Jpanel, он появляется в 2 местах. Вот изображение того, что происходит (https://i.imgur.com/Ao8dRo1.jpg)

Это мой код слишком упрощен. Я считаю, что не совсем правильно понимаю, как работает механизм графического интерфейса.

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

}

Ответы [ 2 ]

2 голосов
/ 06 июня 2019

Я использую команду textField.setBounds (290, 80, 135, 40);разместить его там, где я хочу, но это не работает.Почему это могло произойти?

Swing был разработан для использования с менеджерами компоновки.Диспетчером макетов по умолчанию для JPanel является FlowLayout.FlowLayout будет игнорировать оператор setBounds (...) и устанавливать размер / расположение текстового поля на основе правил FlowLayout.

Поэтому не пытайтесь использовать нулевой макет и неиспользуйте 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 должен переопределить метод Board getPreferredSize(), чтобы вернуть желаемый размер, чтобы метод pack () работал правильно.

Менеджер компоновки по умолчанию для JFrame:BorderLayout.Итак, теперь верхняя часть фрейма будет содержать текстовое поле по центру, а основная часть фрейма будет содержать ваш класс Board.Прочтите раздел из учебника Swing по Как использовать BorderLayout , чтобы понять, как работает приведенный выше код.

Кроме того, MouseListener должен быть добавлен в Board, а не в JFrame.

2 голосов
/ 06 июня 2019

Я думаю, что проблема в том, что вы переопределили paintComponent в вашем классе Board. Этот метод вызывается каждый раз, когда необходимо нарисовать компонент, поэтому каждый раз будет добавляться новое текстовое поле.

Было бы лучше добавить текстовое поле в конструктор для вашего класса доски.

...