多个自定义 JComponents,只显示一个

Multiple custom JComponents, only one displayed

我正在尝试制作一个可以在我的程序中反复使用的自定义 JComponent。我已经设置了一个简单的测试来测试我需要做什么,但我什至无法让它工作。

class MyComponent extends JComponent {
    private String string = "";
    private int x;
    private int y;

    public MyComponent(String string, int x, int y){
        this.string = string;
        this.x = x;
        this.y = y;
    }
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString(string, x, y);
    }

}

public class GObject {
    public static void main(String[] args) {
        JFrame Window = new JFrame();
        Window.setBounds(30, 30, 300, 300);
        Window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MyComponent com1 = new MyComponent("test123", 100, 100);
        MyComponent com2 = new MyComponent("test456", 20, 20);
        Window.add(com1);
        Window.add(com2);

        Window.setVisible(true);
    }
}

从技术上讲,我创建的是一个可以放置在任何位置的 JLabel。您会希望在这些坐标处看到显示的两个字符串,"test123" 和 "test456"。但是我只看到显示的最后一个字符串。

JFrame with only one string of text displayed.

编辑:

让我上传我的实际代码。我试图通过简化我的实际代码来简化事情。

这是我的:

import java.awt.Graphics;

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

public class HeatG2 {
    public static JFrame frame = new JFrame("Test");

    public static void main(String[] args){
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Sheet sheet = new Sheet();
        frame.add(sheet);
        frame.setSize(1000, 800);
        frame.setVisible(true);
    }

}

@SuppressWarnings("serial")
class Sheet extends JPanel{
    public Heat test1;
    public Heat test2;

    public Sheet(){
        test1 = new Heat();
        test1.setPosition(10, 10);
        test1.setHeat(1);
        test1.setHeight(150);
        add(test1);

        test2 = new Heat();
        test2.setPosition(10, 310);
        test2.setHeat(2);
        test2.setHeight(150);
        add(test2);
    }
}

@SuppressWarnings("serial")
class Heat extends JComponent{
    private int x;
    private int y;
    private int height;
    private int heat;
    private String driver1 = "";
    private String driver2 = "";

    public String getDriver1(){
        return driver1;
    }

    public String getDriver2(){
        return driver2;
    }

    public void setDriver1(String driver1){
        this.driver1 = driver1;
        System.out.println(this.driver1);
    }

    public void setDriver2(String driver2){
        this.driver2 = driver2;
        System.out.println(this.driver2);
    }

    public void setPosition(int x, int y){
        this.x = x;
        this.y = y;
    }

    public void setHeight(int height){
        this.height = height;
    }

    public void setHeat(int heat){
        this.heat = heat;
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawString(driver1, x, y);
        g.drawLine(x, y, x+250, y);
        g.drawLine(x+250, y, x+250, y+height);
        g.drawString(driver2, x, y+height);
        g.drawLine(x, y+height, x+250, y+height);
    }
}

需要在 sheet (JPanel) 的指定位置添加多个加热。然后 Jpanel 将被添加到 JWindow。

编辑 2:

我最终通过不扩展组件解决了这个问题。我使用 class 作为可绘制对象的模板。

您需要检查布局。如果它是 BorderLayout(Default),它将只显示最后一个尝试使用不同的布局。类似于 GridLayout 或 FlowLayout

I need to use absolute positioning because the components will eventually be added to a scroll pane

滚动不适用于绝对定位,因为滚动窗格及其相关滚动条仅在面板的首选大小大于滚动窗格大小时才有效。如果您不使用布局管理器,那么您需要自己管理首选尺寸。

您需要使用 Drag Layout 之类的工具来为您管理面板的首选大小。

Technically what I have created is a JLabel that can be positioned anywhere.

那么从技术上讲,您应该使用 JLabel,这样您就不会重新发明轮子。您对组件如何工作的概念是错误的。组件有一个 size 和一个 location。因此自定义绘画将相对于组件的 (0, 0) 绘制文本。然后使用 setLocation(...) 方法在父面板中定位组件。

如果您想进行自定义绘画,则您有责任确定每个组件的首选大小,并且大小会根据您指定为参数的文本而有所不同,因此您需要使用 FontMetrics。这是只使用 JLable 的另一个原因。