【问题标题】:JComponent not Drawing to JPanelJComponent 不绘制到 JPanel
【发布时间】:2012-09-27 09:04:14
【问题描述】:

我有一个扩展 JComponent 的自定义组件,它覆盖了 paintComponent(Graphics g) 方法,但是当我尝试将它添加到我的 JPanel 时它不起作用,没有绘制任何内容。 这是我的代码:

public class SimpleComponent extends JComponent{

int x, y, width, height;

public SimpleComponent(int x, int y, int width, int height){
    this.x = x;
    this.y = y;
}

@Override
public void paintComponent(Graphics g){
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.BLACK);
    g2.fillRect(x, y, width, height);
}
}


public class TestFrame{
public static void main(String[] args){
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel.setPreferredSize(new Dimension(400, 400));
    frame.add(panel);
    frame.pack();
    frame.setResizable(false);

    SimpleComponent comp = new SimpleComponent(10, 10, 100, 100);
    panel.add(comp);
    frame.setVisible(true);
}
}

【问题讨论】:

    标签: java swing jpanel jcomponent


    【解决方案1】:

    它工作正常——组件被添加到 JPanel,但它有多大?如果您在 GUI 渲染后检查此内容,您可能会发现您的组件的大小为 0, 0。

    SimpleComponent comp = new SimpleComponent(10, 10, 100, 100);
    panel.add(comp);
    frame.setVisible(true);
    
    System.out.println(comp.getSize());
    

    考虑让您的 JComponent 覆盖 getPreferredSize 并返回一个有意义的 Dimension:

    public Dimension getPreferredSize() {
      return new Dimension(width, height);
    }
    

    如果您想使用 x 和 y,您可能还希望覆盖 getLocation()

    编辑
    您还需要设置宽度和高度字段!

    public SimpleComponent(int x, int y, int width, int height) {
      this.x = x;
      this.y = y;
      this.width = width; // *** added
      this.height = height; // *** added
    }
    

    【讨论】:

    • 这真的很奇怪,我在 windows 和 mac 上复制了这个问题,并且总是完全相同
    • 啊,宽高设置为零
    • 在记住设置宽度和高度字段后它仍然不起作用,但是当我覆盖 getPreferredSize() 方法时它起作用了。
    • @lilroo:是的,你需要两者都做。
    • 另外,请致电super.paintComponent
    【解决方案2】:

    哇!绝对不是正确的答案!

    你犯下的第一个绝对CARDINAL SIN就是在非EDT线程中完成所有这些!这里没有篇幅可以解释...网络上只有大约 300 亿个地方可以了解它。

    一旦所有这些代码在 EDT(事件调度线程)中的 Runnable 中执行,那么:

    不需要覆盖preferredSize(尽管您可以根据需要)...但您确实需要设置它。

    您绝对不应该直接设置尺寸(heightwidth,或setSize())!

    要做需要做的是让java.awt.Containerpanel,在你的例子中,“展示自己”......有一个方法Container.doLayout(),但是正如 API 文档中所说:

    使该容器布置其组件。大多数程序应该 不直接调用此方法,而应调用 validate 方法 而是。

    因此解决方案是:

    SimpleComponent comp = new SimpleComponent(10, 10, 100, 100);
    comp.setPreferredSize( new Dimension( 90, 90 ) );
    panel.add(comp);
    
    // the key to unlocking the mystery
    panel.validate();
    
    frame.setVisible(true);
    

    顺便说一句,请从我的经验中获益:我花了好几个小时努力理解所有这些 validate, invalidate, paintComponent, paint 等内容......但我仍然觉得我只是触及了表面。

    【讨论】:

    • 好的,谢谢...但是如果您是在这里对我的答案投反对票的人,那么这对未来的访问者来说并没有太大帮助:我的答案比公认的答案要好得多,而且关于setPreferredSize/getPreferredSize 的细微差别不会改变这一点。
    • 哦...我看到你是接受答案的回答者!但是有 214k 的代表你肯定知道我说的每一点都是正确的,而且你的回答真的,嗯,我该怎么说,还有改进的余地!
    猜你喜欢
    • 2013-03-28
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    相关资源
    最近更新 更多