简体   繁体   English

您如何在另一个面板上绘制一个JPanel?

[英]How do you draw a JPanel on top of another?

So I have 2 JPanels, StopWatchDial, which are basically just circles with their constructor being (topleftX, topleftY, diameter, and last parameter doesn't affect the dimensions). 因此,我有2个JPanels,StopWatchDial,它们基本上只是圆形,其构造函数为(topleftX,topleftY,直径和last参数不影响尺寸)。 I'm trying to have it so there's a large outer circle drawn with a smaller inner circle drawn inside of it, but I'm having issues with that. 我正在尝试使用它,因此在其中绘制了一个较大的外部圆圈,在其内部绘制了一个较小的内部圆圈,但是我对此有疑问。 I had assumed the process was suppose to be pretty simple with just overwriting the paintComponent method, but am I just overlooking something? 我以为只覆盖了paintComponent方法就可以使过程很简单,但是我只是忽略了什么吗?

import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Stopwatch extends JPanel
{
    private StopWatchDial innerDial;
    private StopWatchDial outerDial;
    public Stopwatch(int x1, int y1, int width1, int x2, int y2, int width2)
    {
        innerDial = new StopWatchDial(x1, y1, width1, 60);
        outerDial = new StopWatchDial(x2, y2, width2, 1);
        this.add(outerDial);
        this.add(innerDial);
    }
    public void paintComponent(Graphics g)
    {
        outerDial.paintComponents(g);
        innerDial.paintComponents(g);
    }
    public static void main(String[] args) 
    {
        JFrame starter = new JFrame("test");
        starter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Stopwatch test = new Stopwatch( 150, 20, 300, 0, 0, 600);
        starter.add(test);
        starter.setSize(1000, 1000);
        starter.setVisible(true);
    }
}

The issue I'm currently having is instead of being created on top of each other it produces this: 我当前遇到的问题不是在彼此之上创建,而是产生了以下问题:

https://i.imgur.com/RGZbGtq.png

When StopWatchDial is a Component, one can stack them using a JLayeredPane . 当StopWatchDial是一个Component时,可以使用JLayeredPane堆叠它们。

public class Stopwatch extends JLayeredPane
{
    private StopWatchDial innerDial;
    private StopWatchDial outerDial;
    public Stopwatch(int x1, int y1, int width1, int x2, int y2, int width2)
    {
        innerDial = new StopWatchDial(x1, y1, width1, 60);
        outerDial = new StopWatchDial(x2, y2, width2, 1);
        add(outerDial, JLayeredPane.DEFAULT_LAYER);
        add(innerDial, Integer.valueOf(10));
    }

    public static void main(String[] args) 
    {
        final JFrame starter = new JFrame("test");
        starter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Stopwatch test = new Stopwatch( 150, 20, 300, 0, 0, 600);
        starter.add(test);
        starter.setSize(1000, 1000);
        starter.pack(); // Could be used to do optimal layouting.
        EventQueue.invokeLater(() -> starter.setVisible(true));
    }
}

The issue I'm currently having is instead of being created on top of each other it produces this: 我当前遇到的问题不是在彼此之上创建,而是产生了以下问题:

A JPanel uses a FlowLayout by default. JPanel默认使用FlowLayout。 So your Stopwatch panel uses a FlowLayout. 因此,您的秒表面板使用FlowLayout。 When you add two components to the panel they are displayed on a single line. 将两个组件添加到面板时,它们将显示在一行上。

If you want the components on top of one another (using the Z axis) then you need to: 如果要使组件彼此重叠(使用Z轴),则需要:

  1. make the top panel non-opaque, by using innerDial.setOpaque(false). 通过使用innerDial.setOpaque(false)使顶部面板不透明。
  2. Use a layout manager that displays component on the Z axis, like the OverlayLayout . 使用在Z轴上显示组件的布局管理器,例如OverlayLayout I think you will need to set the alignmentX/Y values to 0.5f to make sure the components are centered on one another. 我认为您需要将alignmentX / Y值设置为0.5f,以确保组件彼此居中。 Swing paints components in the reverse order they are added to a panel, so you would add the innerDial and then the outerDial to the stopwatch panel, so the outerDial gets painted before the innerDial. 将组件以相反的顺序进行绘制,将它们添加到面板中,这样您就可以向秒表面板中添加innerDial,然后再将externalDial添加到秒表面板,这样可以在innerDial之前绘制externalDial。

The above answer is for information only. 以上答案仅供参考。 It should not be your final solution. 它不应该是您的最终解决方案。 Having 3 components is not the best design approach. 具有3个组件并不是最佳的设计方法。 You should only have a single Stopwatch component that is created so the programmer doesn't have to deal with layout issues every time they want to use the component. 您应该只创建一个Stopwatch组件,所以程序员不必每次想使用该组件时都要处理布局问题。

I had assumed the process was suppose to be pretty simple with just overwriting the paintComponent method, 我以为只覆盖了paintComponent方法就可以使过程非常简单,

The paintComponent() method is used for painting the Graphics of a component. paintComponent()方法用于绘制组件的图形。 It is NOT used to paint other components. 它不用于喷涂其他组件。 You should not invoke paintComponents() on another component. 您不应在另一个组件上调用paintComponents()。

So instead of having 3 components, you can add all the painting code to the paintComponent(...) method of the StopWatch class. 因此,您可以将所有绘画代码添加到StopWatch类的paintComponent(...)方法中,而不用拥有3个组件。 This would be a better design as all the logic related to displaying a stopwatch is in one class and is not dependent on the other classes being added to the stopwatch with a proper layout. 这将是一个更好的设计,因为与显示秒表有关的所有逻辑都在一个类中,而不依赖于其他类以适当的布局添加到秒表中。

Read the section from the Swing tutorial on Custom Painting for more information and examples. 阅读Swing教程上有关自定义绘画的部分,以获取更多信息和示例。

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

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