JPanel只显示添加的第一个自定义JComponent


我写了一个在屏幕上画三角形的程序。然而,只显示了第一个三角形。如何使多个自定义JComponent可见?

我已经尝试过创建类似draw()方法的东西,但我不能对这个对象执行任何操作,比如,我希望每当我点击它时三角形的颜色都会改变。为此,我需要一个MouseListener,但它不适用于draw()方法。

View.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);
}
}

三角形.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
}
}
JFrame frame = new JFrame();

首先,View类中的语句是完全没有必要的。您不会在组件的构造函数中创建JFrame实例。此外,您的代码从不引用变量,这很好地表明不需要该变量。

然而,主要问题是您创建自定义组件的概念是错误的:

setPreferredSize(new Dimension(100, 100));

您尝试设置组件的首选大小。

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

但是,您尝试在组件大小之外的(100200)处进行自定义绘制。因此,绘制逻辑裁剪在组件的大小上,这样你就看不到任何正在绘制的东西。

自定义绘制应相对于零部件的(0,0)进行,而不是相对于父零部件。

如果你想在父面板上随机放置组件,那么你需要:

  1. 将父面板设置为使用空布局
  2. 设置添加到面板中的每个零部件的位置
  3. 设置添加到面板中的每个零部件的大小

基本上,您需要接管布局管理器的功能。

您当前绘画代码的其他问题:

  1. 不要在绘制方法中调用repaint()。这将导致一个无限的绘画循环。如果需要动画,可以使用"摆动计时器"来安排动画。

  2. 不要直接调用paintComponent(…)。当组件需要重新绘制时,Swing将调用paintComponent()。

但是,我建议如果你想在面板上绘制形状,那么你就忘记了创建自定义组件。相反,您保留要绘制的形状的ArrayList,然后在面板的paintComponent()方法中迭代ArrayList来绘制每个形状。

有关此方法的示例,请参阅自定义绘画方法中的Draw On Component示例。

注:

如果你真的想处理鼠标事件,那么你需要使用形状对象来表示你的形状,以进行正确的命中检测。如果您只是将形状显示为组件,那么如果您单击组件矩形区域中的任何位置,而不仅仅是实际绘制的三角形部分,则会检测到鼠标点击。Shape类有一个contains(…)方法,可以用来确定是否实际单击了Shape。

查看"玩形状"以了解有关此概念的更多信息。

设置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。用CCD_ 9法绘制CCD_。

从软件设计的角度来看,最好坚持一种方法。否则,它可能会令人困惑且容易出错。

最新更新