自定义 JComponent(一行)未显示在 JPanel 上
Custom JComponent (A Line) Doesn't Show Up On JPanel
它在jframe上显示没有jpanel的行,但是当我把它添加到jpanel时却没有。我尝试将 jpanel 的布局管理器设置为 null 但没有结果。我想使用 JComponents 来绘制线条,因为我希望它们可以点击。
Main.java 文件:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}
class Line extends JComponent {
private final Point2D start, end;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
});
}
}
在 Line 构造函数中添加自定义尺寸。
public Line( Point2D start, Point2D end){ ...
this.setSize(200, 200); }
已更新以适应 painted Graph
建议从 JComponent
更改为 JPanel
以便查看 background
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setSize(300,300);
frame.add(panel);
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
frame.setVisible(true);
}
}
class Line extends JPanel {
private final Point2D start, end;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.RED);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
Rectangle r = g2.getClipBounds();
System.out.println(r.x+":"+r.y);
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked at "+e.getX()+":"+e.getY());
}
});
int max_x = (int) Math.max(start.getX(), end.getX());
int max_y = (int) Math.max(start.getY(), end.getY());
System.out.println("max x="+max_y+",y="+max_y);
setSize(max_x,max_y);
setVisible(true);
setBackground(Color.GREEN);
}
}
注意:只允许 inside_green 次点击!
It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel
Swing 组件负责确定它们自己的首选大小。
当您将组件添加到面板时,布局管理器将根据布局管理器的规则设置组件的 size/location。
当您将组件添加到框架时,实际上是将其添加到框架的内容窗格中,该框架是 Jpanel
,默认情况下使用 BorderLayout
。因此组件的大小可以填充框架中可用的 space。
panel.setLayout(null);
然后您将组件添加到具有空布局的面板。现在您负责设置组件的 size/location 。如果您不这样做,则大小为 (0, 0),因此没有什么可绘制的。
您应该将 class 的 getPreferredSize()
方法重写为 return 组件的首选大小。然后布局管理器就可以完成他们的工作了。
如果您确实需要一个空布局,那么应该在应用程序代码中设置组件的大小,而不是行 class 本身。
But now my line has a big container that listens for any clicks,
如果你想要命中检测,那么你重写 contains(...)
方法。
下面是一个实现上述建议的基本示例:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Line extends JComponent
{
private Line2D.Double line;
public Line( Point2D start, Point2D end)
{
line = new Line2D.Double(start, end);
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
System.out.println("mouse clicked");
}
});
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor( Color.BLUE );
g2.setStroke( new BasicStroke(2.0F) );
g2.draw( line );
}
@Override
public Dimension getPreferredSize()
{
Rectangle bounds = line.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
return new Dimension(width, height);
}
@Override
public boolean contains(int x, int y)
{
double distance = line.ptSegDist( new Point2D.Double(x, y) );
return distance < 2;
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}
它在jframe上显示没有jpanel的行,但是当我把它添加到jpanel时却没有。我尝试将 jpanel 的布局管理器设置为 null 但没有结果。我想使用 JComponents 来绘制线条,因为我希望它们可以点击。
Main.java 文件:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}
class Line extends JComponent {
private final Point2D start, end;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
});
}
}
在 Line 构造函数中添加自定义尺寸。
public Line( Point2D start, Point2D end){ ...
this.setSize(200, 200); }
已更新以适应 painted Graph
建议从 JComponent
更改为 JPanel
以便查看 background
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setSize(300,300);
frame.add(panel);
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
frame.setVisible(true);
}
}
class Line extends JPanel {
private final Point2D start, end;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.RED);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
Rectangle r = g2.getClipBounds();
System.out.println(r.x+":"+r.y);
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked at "+e.getX()+":"+e.getY());
}
});
int max_x = (int) Math.max(start.getX(), end.getX());
int max_y = (int) Math.max(start.getY(), end.getY());
System.out.println("max x="+max_y+",y="+max_y);
setSize(max_x,max_y);
setVisible(true);
setBackground(Color.GREEN);
}
}
注意:只允许 inside_green 次点击!
It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel
Swing 组件负责确定它们自己的首选大小。
当您将组件添加到面板时,布局管理器将根据布局管理器的规则设置组件的 size/location。
当您将组件添加到框架时,实际上是将其添加到框架的内容窗格中,该框架是 Jpanel
,默认情况下使用 BorderLayout
。因此组件的大小可以填充框架中可用的 space。
panel.setLayout(null);
然后您将组件添加到具有空布局的面板。现在您负责设置组件的 size/location 。如果您不这样做,则大小为 (0, 0),因此没有什么可绘制的。
您应该将 class 的 getPreferredSize()
方法重写为 return 组件的首选大小。然后布局管理器就可以完成他们的工作了。
如果您确实需要一个空布局,那么应该在应用程序代码中设置组件的大小,而不是行 class 本身。
But now my line has a big container that listens for any clicks,
如果你想要命中检测,那么你重写 contains(...)
方法。
下面是一个实现上述建议的基本示例:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Line extends JComponent
{
private Line2D.Double line;
public Line( Point2D start, Point2D end)
{
line = new Line2D.Double(start, end);
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
System.out.println("mouse clicked");
}
});
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor( Color.BLUE );
g2.setStroke( new BasicStroke(2.0F) );
g2.draw( line );
}
@Override
public Dimension getPreferredSize()
{
Rectangle bounds = line.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
return new Dimension(width, height);
}
@Override
public boolean contains(int x, int y)
{
double distance = line.ptSegDist( new Point2D.Double(x, y) );
return distance < 2;
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}