Рисование прямоугольника по нажатию кнопки с помощью JPanel

1

Я пытаюсь рисовать прямоугольник с помощью JPanel. Проблема в том, что когда я нажимаю на элемент меню, он должен нарисовать новый прямоугольник. НО, когда я это делаю, только часть его расписана. Вот что я имею в виду:

    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            squares.addSquare(10, 10, 100, 100);
        }
    });

Является ли это:

Изображение 174551

но когда я помещаю squares.addSquare(...) НАРУШЕНИЕ из ActionListener, он дает правильную форму (просто не тогда, когда я этого хочу)

    squares.addSquare(10, 10, 100, 100);
    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            //nothing on click...
        }
    });

и вот правильный прямоугольник:

Изображение 174551

любая идея, почему она не рисует правильно, когда я помещаю ее в ActionListener? Благодарю.

Полный код

class UMLWindow extends JFrame {
Squares squares = new Squares();

private static final long serialVersionUID = 1L;

public UMLWindow() {
    addMenus();
}

public void addMenus() {

    getContentPane().add(squares);
    //squares.addSquare(10, 10, 100, 100);

    JMenuBar menubar = new JMenuBar();

    JMenu file = new JMenu("File");
    file.setMnemonic(KeyEvent.VK_F);

    JMenu shapes = new JMenu("Shapes");
    file.setMnemonic(KeyEvent.VK_F);

    JMenuItem rectangleMenuItem = new JMenuItem("New Rectangle");
    rectangleMenuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
            squares.addSquare(10, 10, 100, 100);
        }
    });

    shapes.add(rectangleMenuItem);

    menubar.add(shapes);

    setJMenuBar(menubar);

    setTitle("UML Editior");
    setSize(300, 200);
    setLocationRelativeTo(null);
}


}

class Squares extends JPanel {
private static final long serialVersionUID = 1L;

private List<Rectangle> squares = new ArrayList<Rectangle>();

public void addSquare(int x, int y, int width, int height) {
    Rectangle rect = new Rectangle(x, y, width, height);
    squares.add(rect);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setOpaque(true);
    this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    for (Rectangle rect : squares) {
        g2.draw(rect);
    }
}

}
  • 0
    @ Бен: пожалуйста, сделайте это ответ. Bene? Куда ты пошел?
  • 0
    Да, это сработало. Если это станет ответом, я приму
Показать ещё 4 комментария
Теги:
swing
jpanel
paintcomponent

1 ответ

3
Лучший ответ

Swing использует пассивный движок рендеринга, поэтому он не знает, когда он должен обновлять/перекрашивать компонент, если вы не сообщите об этом.

Начните с вызова repaint из вашего метода addSquare...

public void addSquare(int x, int y, int width, int height) {
    Rectangle rect = new Rectangle(x, y, width, height);
    squares.add(rect);
    repaint();
}

Это сделает запрос менеджеру перерисовывания, сообщив, что текущий компонент необходимо перекрасить.

Вы также должны указать подсказку для размера для своего компонента, чтобы менеджеры макетов установили размер до 0x0.

Рассмотрите возможность переопределения метода getPreferredSize класса Squares и возврата соответствующего размера по умолчанию...

@Override
public Dimension getPreferredSize() {
    return new Dimension(300, 200);
}

Это также означает, что вы можете вызвать pack в главном окне, и он будет "упаковывать" себя вокруг содержимого, очень аккуратно.

Кроме того, не вызывайте методы, которые либо изменят состояние компонента, либо другие компоненты, либо планируют дополнительный запрос на repaint, так как это может создать бесконечный цикл ретрансляции, который истощит ваш компьютер ресурсов....

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // This is bad...
    //this.setOpaque(true);
    // This is bad...
    //this.setBackground(Color.WHITE);
    Graphics2D g2 = (Graphics2D) g;
    for (Rectangle rect : squares) {
        g2.draw(rect);
    }
}

Такие вещи, как непрозрачность и цвет, должны быть определены за пределами цикла краски. Кроме того, компоненты, которые простираются от JPanel, по умолчанию непрозрачны;)

  • 0
    Спасибо за помощь :)
  • 0
    @ Гарри, не беспокойся, рад, что это было полезно

Ещё вопросы

Сообщество Overcoder
Наверх
Меню