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

时间:2016-06-24 18:10:34

标签: java swing jframe layout-manager

我正在尝试创建一个可以在我的程序中反复使用的自定义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”。但是我只看到显示的最后一个字符串。

enter image description here

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

需要在工作表(JPanel)上的指定位置添加多个加热。 Jpanel将被添加到JWindow。

编辑2:

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

2 个答案:

答案 0 :(得分:4)

您需要检查布局。如果是BorderLayout(默认),它将仅显示最后一个尝试使用不同的布局。像GridLayout或FlowLayout

之类的东西

答案 1 :(得分:2)

  

我需要使用绝对定位,因为组件最终会被添加到滚动窗格

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

您需要使用Drag Layout之类的内容,以便为您管理面板的首选尺寸。

  

从技术上讲,我创建的是一个可以定位在任何地方的JLabel。

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

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