简体   繁体   English

自定义 JComponent(一行)不显示在 JPanel 上

[英]Custom JComponent (A Line) Doesn't Show Up On JPanel

It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel.它在 jframe 上显示了没有 jpanel 的行,但是当我将它添加到 jpanel 时却没有。 I've tried setting the layout manager of jpanel to null but no result.我尝试将 jpanel 的布局管理器设置为 null 但没有结果。 I want to use JComponents for drawing lines because I want them clickable.我想使用 JComponents 来绘制线条,因为我希望它们可点击。

Main.java file: 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");
            }
        });
    }
}

It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel它在 jframe 上显示了没有 jpanel 的行,但是当我将它添加到 jpanel 时却没有

Swing components are responsible for determining their own preferred size. Swing 组件负责确定自己的首选尺寸。

When you add a component to a panel, the layout manager will then set the size/location of the component based on the rules of the layout manager.当您将组件添加到面板时,布局管理器将根据布局管理器的规则设置组件的大小/位置。

When you add a component to the frame you really add it to the content pane of the frame which is a Jpanel which uses a BorderLayout by default.当您将组件添加到框架时,您实际上将其添加到框架的内容窗格中,这是一个默认使用BorderLayoutJpanel So the component is sized to fill the space available in the frame.因此,组件的大小可以填充框架中的可用空间。

panel.setLayout(null);

You then added the component to a panel with a null layout.然后,您将该组件添加到具有 null 布局的面板中。 Now you are responsible for setting the size/location of the component.现在您负责设置组件的大小/位置。 If you don't the size is (0, 0) so there is nothing to paint.如果你不知道大小是 (0, 0) 所以没有什么可以画的。

You should override the getPreferredSize() method of your class to return the preferred size of the component.您应该覆盖 class 的getPreferredSize()方法以返回组件的首选大小。 Then layout managers can do their job.然后布局管理器可以完成他们的工作。

If you really need a null layout, then the size of the component should be set in the application code, not it the Line class itself.如果您确实需要 null 布局,则应在应用程序代码中设置组件的大小,而不是 Line class 本身。

But now my line has a big container that listens for any clicks,但是现在我的线路有一个大容器可以监听任何点击,

If you want hit detection then you override the contains(...) method.如果你想要命中检测,那么你覆盖contains(...)方法。

Here is a basic example implementing the above suggestions:这是实现上述建议的基本示例:

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

Add custom size in Line constructor.在 Line 构造函数中添加自定义大小。

public Line( Point2D start, Point2D end){...
this.setSize(200, 200); }

在此处输入图像描述

Updated to fit also with painted Graph更新以适应painted Graph

Advice to change from JComponent to JPanel in order to see background建议从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);
    } 
}

在此处输入图像描述

Note: Only inside_green clicks allowed !注意:只允许 inside_green 点击!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM