组件呈现一种不寻常的方式



我有一个自定义的JPanel类,我想在它的子组件前面画几个矩形和文本。我已经重写了这个方法:

public void paint(Graphics g){
    g = getComponentGraphics(g);
    super.paint(g);
    //paint my custom content
}

super.paint调用绘制子组件的paintChildren。但是子组件出现在我的自定义内容前面,它们有时也会相互争斗。

我完全不知道是什么原因引起的。

注意:我在我的代码中使用setComponentZOrder,而我的JPanel发生在JScrollPane中。

编辑:组件ZFight,即使我从未调用setComponentZOrder方法。

编辑2:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import javax.accessibility.Accessible;
    import javax.accessibility.AccessibleSelection;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    public class Example extends JPanel{
        private static final long serialVersionUID = 1L;
        public static void main(String[] atgs){
            JFrame frame = new JFrame("ZFightingExample");
            frame.setSize(new Dimension(500,500));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ExamplePanel panel = new ExamplePanel();
            frame.add(panel);
            Example a = new Example(new Rectangle(5,5,50,50)),
                    b = new Example(new Rectangle(40,40,50,50));
                    panel.add(a);
            panel.add(b);
            frame.setVisible(true);
        }
        public Example(Rectangle bounds){
            super();
            setBounds(bounds);
        }
        public void paint(Graphics g){
            super.setBackground(Color.GREEN);
            g.fillRect(0, 0, getWidth()-1, getHeight()-1);
            super.paint(g);
            g.setColor(Color.BLACK);
            g.drawRect(0, 0, getWidth()-1, getHeight()-1);
        }
    }
    class ExamplePanel extends JPanel{
        private static final long serialVersionUID = 1L;
        public ExamplePanel(){
            super(null);
            accessibleContext = new Accessiblecontext();
        };
        protected class Accessiblecontext extends AccessibleJPanel implements AccessibleSelection{
            private static final long serialVersionUID = 1L;
            public int getAccessibleSelectionCount() {return 2;}
            public Accessible getAccessibleSelection(int i) {return (Accessible)getComponent(i);}
            public boolean isAccessibleChildSelected(int i) {return true;}
            public void addAccessibleSelection(int i) {}
            public void removeAccessibleSelection(int i) {}
            public void clearAccessibleSelection() {}
            public void selectAllAccessibleSelection() {}
        }
        public void paint(Graphics g){
            super.paint(g);
            g.setColor(Color.BLUE);//Should be in front of the Green boxes...
            g.drawRect(10, 10, 75, 75);
        }
    }

我想在它的子组件前面画几个矩形和文本。

通常你重写paintcomponent()来做自定义绘制。

问题是"在前面"对你意味着什么?如果它的意思和我想的一样,那么你需要在子组件被绘制之后再进行绘制。所以你重写paint()的基本方法是正确的。

public void paint(Graphics g){
    g = getComponentGraphics(g);
    super.paint(g);
    //paint my custom content
}

上面代码的问题是,您没有使用传递给绘画方法的Graphics对象。所以你的代码应该是:

public void paint(Graphics g)
{
    //g = getComponentGraphics(g);
    super.paint(g);  // use the Graphics object passed to the method
    //paint my custom content
    g.drawRect(10, 10, 20, 20);
}

我使用setComponentZOrder在我的代码,

你为什么玩ZOrder?

编辑:

g.setColor(Color.BLUE);//应该在绿色盒子的前面…

正如我在回答中第一次提到的,通常(99%的情况下)自定义绘制是通过重写面板的paintComponent()方法来完成的。

问题在于示例类:

  1. override paintComponent() not paint()
  2. 重写绘画方法时的第一个语句应该是super.???
  3. 不要在绘画方法中设置类的属性。
所以代码可能看起来像这样:
public Example(Rectangle bounds){
    super();
    setBounds(bounds);
    setBackground(Color.GREEN);
}
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth()-1, getHeight()-1);
    g.setColor(Color.BLACK);
    g.drawRect(0, 0, getWidth()-1, getHeight()-1);
}

注意,您不需要对Example类进行任何自定义绘制。相反,你的代码可以像这样:

ExamplePanel panel = new ExamplePanel();
panel.setLayout( null ); // now you set the size/location of any component you add to the panel
JPanel example1 = new JPanel();
example1.setBackground( Color.GREEN );
example1.setBorder( new LineBorder(Color.BLACK) );
example1.setBounds( new Rectangle(....) );
panel.add(example1);

另外,ExamplePanel类的另一个解决方案可能是使用JLayer。JLayer类允许您向组件添加各种花哨的装饰。查看Swing教程如何使用JLayer类装饰组件

最新更新