JPanel 仅显示添加的第一个自定义 JComponent
JPanel shows only the first custom JComponent added
我编写了一个在屏幕上绘制三角形的程序。但是只显示了第一个三角形。如何使多个自定义 JComponents 可见?
我已经尝试创建类似于 draw()
方法的东西,但是我无法像 i 那样对该对象执行任何操作。 e.我希望每当我点击它时三角形的颜色都会改变。为此,我需要一个 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);
}
}
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
}
}
JFrame frame = new JFrame();
首先,您视图中的声明 class 完全没有必要。您不会在组件的构造函数中创建 JFrame 实例。此外,您的代码从不引用该变量,这很好地表明不需要它。
但是,主要问题是您创建自定义组件的概念是错误的:
setPreferredSize(new Dimension(100, 100));
您试图设置组件的首选大小。
add(new Triangle(100, 200, Color.pink)); //this one doesn't appear
但是随后您尝试在超出组件尺寸的 (100, 200) 处进行自定义绘制。所以绘画逻辑被剪裁成组件的大小,所以你看不到任何被绘画的东西。
自定义绘制应该相对于组件的 (0, 0) 完成,而不是相对于父组件。
如果您想在父面板上随机放置组件,则需要:
- 将父面板设置为使用空布局
- 设置您添加到面板的每个组件的位置
- 设置您添加到面板的每个组件的大小。
基本上您需要接管布局管理器的功能。
您当前的绘画代码存在的其他问题:
不要在绘画方法中调用 repaint()。这基本上会导致无限绘画循环。如果您需要动画,您可以使用 Swing Timer 来安排动画。
不要直接调用 paintComponent(...)。当组件需要重新绘制时,Swing 将调用 paintComponent()。
但是,我建议如果你想在面板上绘制形状,那么你忘记创建自定义组件。相反,您保留要绘制的形状的 ArrayList,然后在面板的 paintComponent() 方法中遍历 ArrayList 以绘制每个形状。
有关此方法的示例,请查看 Custom Painting Approaches 中的 Draw On Component
示例。
注:
如果您真的希望能够处理鼠标事件,那么您需要使用 Shape 对象来表示您的形状以进行正确的点击检测。如果你只是将你的形状显示为一个组件,那么如果你点击组件矩形区域的任何地方,而不只是你实际绘制的三角形部分,鼠标点击就会被检测到。 Shape
class 有一个 contains(...) 方法,您可以使用它来确定您是否实际单击了形状。
查看 Playing With Shapes 了解有关此概念的更多信息。
为 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.通过在paintComponent()
方法中绘制p3
。
从软件设计的角度来看,最好坚持一种方法。否则它可能会令人困惑且容易出错。
我编写了一个在屏幕上绘制三角形的程序。但是只显示了第一个三角形。如何使多个自定义 JComponents 可见?
我已经尝试创建类似于 draw()
方法的东西,但是我无法像 i 那样对该对象执行任何操作。 e.我希望每当我点击它时三角形的颜色都会改变。为此,我需要一个 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);
}
}
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
}
}
JFrame frame = new JFrame();
首先,您视图中的声明 class 完全没有必要。您不会在组件的构造函数中创建 JFrame 实例。此外,您的代码从不引用该变量,这很好地表明不需要它。
但是,主要问题是您创建自定义组件的概念是错误的:
setPreferredSize(new Dimension(100, 100));
您试图设置组件的首选大小。
add(new Triangle(100, 200, Color.pink)); //this one doesn't appear
但是随后您尝试在超出组件尺寸的 (100, 200) 处进行自定义绘制。所以绘画逻辑被剪裁成组件的大小,所以你看不到任何被绘画的东西。
自定义绘制应该相对于组件的 (0, 0) 完成,而不是相对于父组件。
如果您想在父面板上随机放置组件,则需要:
- 将父面板设置为使用空布局
- 设置您添加到面板的每个组件的位置
- 设置您添加到面板的每个组件的大小。
基本上您需要接管布局管理器的功能。
您当前的绘画代码存在的其他问题:
不要在绘画方法中调用 repaint()。这基本上会导致无限绘画循环。如果您需要动画,您可以使用 Swing Timer 来安排动画。
不要直接调用 paintComponent(...)。当组件需要重新绘制时,Swing 将调用 paintComponent()。
但是,我建议如果你想在面板上绘制形状,那么你忘记创建自定义组件。相反,您保留要绘制的形状的 ArrayList,然后在面板的 paintComponent() 方法中遍历 ArrayList 以绘制每个形状。
有关此方法的示例,请查看 Custom Painting Approaches 中的 Draw On Component
示例。
注:
如果您真的希望能够处理鼠标事件,那么您需要使用 Shape 对象来表示您的形状以进行正确的点击检测。如果你只是将你的形状显示为一个组件,那么如果你点击组件矩形区域的任何地方,而不只是你实际绘制的三角形部分,鼠标点击就会被检测到。 Shape
class 有一个 contains(...) 方法,您可以使用它来确定您是否实际单击了形状。
查看 Playing With Shapes 了解有关此概念的更多信息。
为 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.通过在paintComponent()
方法中绘制p3
。
从软件设计的角度来看,最好坚持一种方法。否则它可能会令人困惑且容易出错。