JComponent不可见,有谁知道为什么?

时间:2010-02-19 19:10:27

标签: java swing custom-controls paint

这是我的JFrame代码:

public static void main(String[] args) {
    JFrame jf = new JFrame();
    jf.setSize(600,600);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    MyCustomWidget widget = MyCustomWidget.createWidget(400, 400);
    widget.setVisible(true);
    // just to set x and y
    widget.setLocation(40, 40);

    jf.getContentPane().add(widget);
    jf.setVisible(true);
}

这是MyCustomWidget的代码:

public class MyCustomWidget extends JComponent {

    public void paint(Graphics g)
    {
        super.paint(g);
    }

    public static MyCustomWidget createWidget(int width,int height)
    {
        MyCustomWidget tw = new MyCustomWidget();
        tw.setBounds(0,0,width,height);
        tw.setBackground(Color.RED);
        return tw;
    }
}
事实是,窗口中没有显示JComponent,我不明白为什么。我甚至添加了widget.setVisible(true)只是为了确保它是可见的。什么都行不通。你能发现我做错了吗?

经过你们建议的修改后,代码现在是:

package javaapplication2;

public class Main {

    public static void main(String[] args) throws IOException {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                JFrame jf = new JFrame();
                jf.setSize(600,600);
                jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                jf.setLayout(null);

                JComponent container = (JComponent) jf.getContentPane();
                container.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);
                DebugGraphics.setFlashColor(Color.RED);
                DebugGraphics.setFlashCount(2);
                DebugGraphics.setFlashTime(100);

                MyCustomWidget widget = MyCustomWidget.createTimeline(400, 400);

                container.add(widget);
                jf.setVisible(true);
            }

        });


    }

}

public class MyCustomWidget extends JComponent {

    public void paintComponent(Graphics g)
    {
        setForeground(Color.BLACK);
        drawLines(g);
    }

    // a little something to see that something is drawed
    private void drawLines(Graphics g)
    {
        int distanceBetween = getHeight() / numberOfLines;
        int start = 0;
        int colourIndex = 0;
        Color colours[] = {Color.BLUE,Color.WHITE,Color.YELLOW};

        for(int i = 0;i < distanceBetween;start+=distanceBetween,i++)
        {
            g.setColor(colours[colourIndex]);
            g.drawLine(0,start,40,40);
            colourIndex %= colours.length;
        }
    }

    private int numberOfLines = 4;

    public MyCustomWidget()
    {
        setOpaque(true);
    }

    public static MyCustomWidget createTimeline(int width,int height)
    {
        MyCustomWidget tw = new TimelineWidget();
        tw.setBounds(0,0,width,height);
        return tw;
    }
}

2 个答案:

答案 0 :(得分:2)

以下是这里发生的事情:

  • JFrame内容窗格的默认布局是BorderLayout。这意味着您的组件将调整为内容窗格的整个大小。要在添加组件之前在任何地方修复此问题,请执行
 jf.getContentPane().setLayout(null);
  • 在JComponent的直接后代中不会自动绘制背景。您可以使组件不透明(setOpaque(true)),从JPanel扩展或覆盖paintComponent方法,如此
 public void paintComponent (Graphics g) {
    super.paintComponent (g);
    g.setColor(getBackground());
    g.drawRect(0, 0, getWidth(), getHeight());
 }

编辑:

为了符合Swing线程规则,main方法中的代码应该在EDT线程上运行。这意味着它必须被包装成

SwingUtilities.invokeLater(new Runnable() {
     public void run() {
         // your code goes here
     } 
}

答案 1 :(得分:2)

默认情况下,JComponents不是不透明的,因此您的背景永远不会被绘制。拨打setOpaque(true)应该可以解决问题。

对您的代码的2条评论:

  1. 如果您要编写自定义绘画代码,请覆盖paintComponent(),而不是paint()
  2. 必须在EventDispatchThread(EDT)上对UI组件进行任何更改,如果不这样做,将导致从不一致的行为到完全崩溃等一般不好的事情。因此,在您的主要部分中,您需要将代码包装在invokeLater中:

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // your code goes here
        }
    }