为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ITMISS 2022-05-12 16:26:24
我编写了一个在屏幕上绘制三角形的程序。然而,只显示了第一个三角形。如何使多个自定义 JComponent 可见?我已经尝试创建类似draw()方法的东西,但是我无法对这个对象执行任何操作,例如,我希望在单击它时更改三角形的颜色。为此,我需要 aMouseListener但它不适用于该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);}}三角.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();}
查看完整描述

2 回答

?
墨色风雨

TA贡献1853条经验 获得超6个赞

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。

查看Playing With Shapes了解有关此概念的更多信息。


查看完整回答
反对 回复 2022-05-12
?
GCT1015

TA贡献1827条经验 获得超4个赞

为组件设置边框,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. 通过添加三角形组件。(如“add(new Triangle(20, 50, Color.red));”)

2.通过绘制方法p3。paintComponent()


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


查看完整回答
反对 回复 2022-05-12
  • 2 回答
  • 0 关注
  • 191 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号