JComponent не виден, кто-нибудь знает почему? - PullRequest
1 голос
/ 19 февраля 2010

Вот мой код 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), чтобы убедиться, что он виден. Ничего не работает Можете ли вы определить, что я делаю не так?

После изменений, которые вы, ребята, предложили, код теперь выглядит так:

пакет 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 ]

2 голосов
/ 19 февраля 2010

По умолчанию JComponents не являются непрозрачными, поэтому ваш фон никогда не будет окрашен. Звонок на setOpaque(true) должен помочь.

2 комментария к вашему коду:

  1. если вы собираетесь написать собственный код рисования, переопределите paintComponent(), а не paint()
  2. Любые изменения в компонентах пользовательского интерфейса должны быть внесены в EventDispatchThread (EDT), в противном случае это может привести к плохим результатам, начиная от противоречивого поведения до полного сбоя. Итак, в вашем основном вам нужно обернуть ваш код в invokeLater:

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // your code goes here
        }
    }
    
2 голосов
/ 19 февраля 2010

Вот что здесь происходит:

  • Макет по умолчанию панели содержимого вашего 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());
 }

EDIT:

Чтобы соответствовать правилам потоков Swing, код в методе main должен выполняться в потоке EDT. Это означает, что оно должно быть заключено в

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