开发者

JComponent is not visible, anyone knows why?

Here's my JFrame code:

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);
    // 开发者_Python百科just to set x and y
    widget.setLocation(40, 40);

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

and here's the code for 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;
    }
}

the thing is, the JComponent is not shown in the window, and I don't understand why. I even added a widget.setVisible(true) just to make sure it is visible. Nothing works. Can you spot what I'm doing wrong?

After the modifications you guys suggested, the code now is:

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

        });


    }

}

and:

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


Here is what happens here :

  • Default layout of your JFrame's content pane is BorderLayout. This means your component is resized to the whole size of content pane. To fix this anywhere before adding your component do
 jf.getContentPane().setLayout(null);
  • Background is not drawn automatically in direct descendants of JComponent. You can either make your component opaque (setOpaque(true)), extend from JPanel or override paintComponent method like this
 public void paintComponent (Graphics g) {
    super.paintComponent (g);
    g.setColor(getBackground());
    g.drawRect(0, 0, getWidth(), getHeight());
 }

EDIT:

To comply with Swing threading rules the code in main method should run on EDT thread. That mean it has to be wrapped into

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


By default JComponents are not opaque, so your background never gets painted. A call to setOpaque(true) should do the trick.

2 comments on your code:

  1. if you are going to write custom painting code, override paintComponent(), not paint()
  2. Any changes to UI components must be made on the EventDispatchThread (EDT) failing to do this will result in generally bad things ranging from inconsistent behavior to a full crash. So, in your main you need to wrap your code in an invokeLater:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜