JPanel показывает только первый добавленный пользовательский JComponent - PullRequest
0 голосов
/ 20 января 2019

Я написал программу, которая рисует треугольники на экране. Однако показан только первый треугольник. Как я могу сделать несколько пользовательских JComponents видимыми?

Я уже пытался создать что-то вроде draw() метода, но тогда я не могу выполнить никаких действий с этим объектом, как я. е. Мне бы хотелось, чтобы цвет треугольника менялся всякий раз, когда я нажимаю на него. Для этого мне понадобится MouseListener, но он не будет работать с методом draw().

Просмотр .java файла:

package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class View extends JPanel {

public View()
{


    setPreferredSize(new Dimension(300, 300));
    add(new Triangle(20, 50, Color.red)); //this one will react to mouseClicked
    add(new Triangle(100, 200, Color.pink)); //this one doesn't appear

}


public static void main(String []args)
{
    JFrame frame = new JFrame("Trianlge test");
    frame.add(new View());
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

}


public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    Triangle p3 = new Triangle(60, 120, Color.blue); //this one won't react to mouseClicked()
    p3.draw(g);
}
}

Файл Triangle.java:

    package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;

import javax.swing.JComponent;

public class Triangle extends JComponent implements MouseListener{

private int x,y;
private Color c;
public Triangle(int x, int y, Color c)
{
    this.x = x;
    this.y = y;
    this.c = c;
    setPreferredSize(new Dimension(100, 100));
    addMouseListener(this);
}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    GeneralPath path = new GeneralPath();

    g2d.setColor(c);
    path.moveTo(x, y);
    path.lineTo(x, y);
    path.lineTo(x+50, y);
    path.lineTo(x, y-50);
    path.closePath();
    g2d.fill(path);
    repaint();
}

public void draw(Graphics g)
{

    Graphics2D g2d = (Graphics2D) g;
    GeneralPath path = new GeneralPath();

    g2d.setColor(c);
    path.moveTo(x, y);
    path.lineTo(x, y);
    path.lineTo(x+50, y);
    path.lineTo(x, y-50);
    path.closePath();
    g2d.fill(path);
    repaint();
}

@Override
public void mouseClicked(MouseEvent e) {
    c = Color.cyan;
    repaint();

}

@Override
public void mousePressed(MouseEvent e) {
}

@Override
public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

}

}

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Установить границу для Triangle компонентов, таких как:

public Triangle(int x, int y, Color c)
{
  this.x = x;
  this.y = y;
  this.c = c;
  setPreferredSize(new Dimension(100, 100));
  addMouseListener(this);
  // Set this border to see the boundaries of this component.
  // When you are done, you may remove this.
  setBorder(BorderFactory.createLineBorder(Color.black));
}

Тогда вы сможете лучше понять границы компонентов.

Розовый треугольник не виден, поскольку он находится за границей компонента.

p3 треугольник не реагирует на щелчки мышью, потому что это просто рисунок. Только компоненты реагируют на мышь и другие события.

Обратите внимание, что компоненты имеют прямоугольную форму. Итак, прослушиватель мыши, который вы добавили, работает в любом месте компонента; не только в области треугольника.

В этой программе вы рисуете треугольники двумя способами.
1. Добавляя компоненты треугольника. (Например, «добавить (новый треугольник (20, 50, Color.red));»)
2. Рисуя p3 в paintComponent() метод.

С точки зрения разработки программного обеспечения лучше придерживаться одного подхода. В противном случае это может привести к путанице и ошибкам.

0 голосов
/ 20 января 2019
JFrame frame = new JFrame();

Прежде всего, это утверждение в вашем классе View совершенно не нужно.Вы не создали бы экземпляр JFrame в конструкторе компонента.Кроме того, ваш код никогда не ссылается на переменную, что является хорошим признаком того, что она не нужна.

Однако основная проблема в том, что ваша концепция создания пользовательских компонентов неверна:

setPreferredSize(new Dimension(100, 100));

Вы пытаетесьустановите предпочтительный размер компонента.

add(new Triangle(100, 200, Color.pink)); //this one doesn't appear

Но затем вы попытаетесь выполнить пользовательское рисование в (100, 200), который находится за пределами размера компонента.Таким образом, логика рисования обрезается по размеру компонента, поэтому вы не видите ничего нарисованного.

Пользовательское рисование должно выполняться относительно (0, 0) компонента, а не относительно родительского компонента.

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

  1. настроить родительскую панель на использование нулевого макета
  2. установить расположение* каждый компонент, добавляемый на панель
  3. устанавливает размер каждого компонента, добавляемого на панель.

в основном вам необходимо взять на себя функции менеджера компоновки.

Другие проблемы с вашим текущим кодом рисования:

  1. Не вызывайте repaint () в методе рисования.Это по существу вызовет бесконечный цикл рисования.Если вам нужна анимация, вы используете Swing Timer для планирования анимации.

  2. Не вызывайте paintComponent (...) напрямую.Swing вызовет paintComponent (), когда компонент должен быть перекрашен.

Однако я хотел бы предложить, чтобы, если вы хотите рисовать фигуры на панели, тогда вы забудете о создании пользовательских компонентов.Вместо этого вы сохраняете ArrayList тех фигур, которые хотите нарисовать, а затем в методе paintComponent () панели вы перебираете ArrayList для рисования каждой фигуры.

В качестве примера такого подхода рассмотрим пример Draw On Component, приведенный в Индивидуальные подходы к рисованию .

Примечание:

Если вы действительноЕсли вы хотите обрабатывать события мыши, вам нужно использовать объект Shape для представления ваших фигур для правильного обнаружения попадания.Если вы просто отображаете свою форму как компонент, то попадание мыши будет обнаружено, если вы щелкнете где-нибудь в прямоугольной области компонента, а не только в той части треугольника, которую вы фактически рисуете.Класс Shape имеет метод contains (...), который можно использовать, чтобы определить, действительно ли вы щелкаете в Shape или нет.

Проверьте Игра с формами для получения дополнительной информации оэто понятие.

...