1

这是我的 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;
    }
}
4

2 回答 2

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
     } 
}
于 2010-02-19T19:37:46.810 回答
2

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

对您的代码有 2 条评论:

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

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // your code goes here
        }
    }
    
于 2010-02-19T19:40:46.673 回答