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

时间:2016-08-20 13:26:53

标签: java swing graphics

我有一个自定义JPanel类,我希望它在它的子组件前面绘制几个矩形和文本。我已经覆盖了这个方法:

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

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

我完全不知道可能导致这种情况的原因。

注意:我在代码中使用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);
        }
    }

1 个答案:

答案 0 :(得分:2)

  

我希望它在它的子组件前面绘制几个矩形和文本。

通常你会覆盖paintCompnent()来进行自定义绘画。

问题是"在前面"对你意味着什么?如果它意味着我的意思,那么你需要在绘制子组件后进行绘画。所以你覆盖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()方法完成的。

问题在于Example类:

  1. 覆盖paintComponent()而不是paint()
  2. 覆盖绘画方法时的第一个语句应该是super。???。
  3. 不要在绘画方法中设置类的属性。
  4. 因此代码可能类似于:

    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类允许您向组件添加各种奇特的装饰。查看How to Decorate Components With The JLayer Class上的Swing教程。