关于java:JComponent不能绘制到JPanel

JComponent not Drawing to JPanel

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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);
}
}

它工作正常-组件已添加到JPanel中,但是它有多大?如果在呈现GUI后检查此选项,则可能会发现组件的大小为0、0。

1
2
3
4
5
SimpleComponent comp = new SimpleComponent(10, 10, 100, 100);
panel.add(comp);
frame.setVisible(true);

System.out.println(comp.getSize());

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

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

如果要使用x和y,则可能希望也覆盖getLocation()

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

1
2
3
4
5
6
public SimpleComponent(int x, int y, int width, int height) {
  this.x = x;
  this.y = y;
  this.width = width; // *** added
  this.height = height; // *** added
}


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

您提交的第一个绝对的CARDINAL SIN是在非EDT线程中完成所有这些操作!!!这里没有足够的空间来解释这一点...网上只有大约300亿个地方可以学习。

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

您无需覆盖preferredSize(尽管您可以根据需要设置)...但是您需要对其进行设置。

绝对不应该直接设置大小(heightwidthsetSize())!

在您的示例中,您要做的是获取java.awt.Containerpanel以"布局自身" ...有一种方法Container.doLayout(),但正如API文档中所述:

Causes this container to lay out its components. Most programs should
not call this method directly, but should invoke the validate method
instead.

因此,解决方案是:

1
2
3
4
5
6
7
8
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等内容,但我仍然觉得自己只是在刮擦表面。