Home > Enterprise >  Java swing paint don't show internal components
Java swing paint don't show internal components

Time:09-17

I've created a custom JPanel that has background with diagonal lines fixed or animated. I wondered that if I add any jcomponent to panel, it is not shown at all. I understand that problem is because I paint over components, but I don't know how solve it. Here is my complete code.

Some help will be appreciated :)

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;

import javax.swing.JPanel;
import javax.swing.Timer;

public class JStripedPanel extends JPanel {

    int space = 20;
    float thickness = 2f;
    int xpos = 0;
    float progress = 0f;
    Float th = 2f;
    int dir = 1;
    Timer timer;
    Timer cbt = null;
    Paint lineColor = new Color(255,50,50,50);
    
    public JStripedPanel() {
        super();
    }

    public JStripedPanel(LayoutManager l) {
        super(l);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setPaint(getBackground());
        g2.fill(getShape());
        //g2.setClip(getShape());
        if(thickness > 0) {
            // draw diagonal lines
            g2.setPaint(getLineColor());
            g2.setStroke(new BasicStroke(thickness));

            int h = 0;
            int max = Math.max(this.getSize().width, this.getSize().height)   getSpace();
            int x = - max - getSpace();
            while( x < this.getSize().width   getSpace() ) {
                g2.drawLine(xpos   x, max,  xpos   x   max, h);
                x  = getSpace();
            }
        }
//      g2.setColor(Color.black);
//      g2.setStroke(new BasicStroke(5));
//      g2.drawLine(0, this.getSize().height/2, this.getSize().width, this.getSize().height/2);
        g2.dispose();
    }

    public void setLineColor(Paint lineColor) {
        this.lineColor = lineColor;
    }

    private Paint getLineColor() {
        return lineColor;
    }

    public void setStripe(int space, float thikness) {
        this.space = space;
        this.thickness = thikness;
    }

    public int getSpace() {
        return space;
    }

    private void setXpos(int xpos) {
        if(xpos > getSpace())
            xpos = 0;
        this.xpos = xpos;
    }
    
    private int getXpos() {
        return xpos;
    }

    private Shape getShape() {
        Shape s = new Rectangle(getBounds());
        return s;
    }

    public void startAnim(float thickness) {
        this.thickness = thickness;

        timer = new Timer(100, (e) -> {
            setXpos(getXpos()  1);
            repaint();
            setStripe(20, th);
            th = th  = .5f * dir;
            if(th > 35.5f)
                dir = -1;
            else if(th < 1.5f)
                dir = 1;
        });
        timer.start();
    }
    
    public void stopAnim(boolean now) {
        if(now) {
            stopNow();
            return;
        }
        try {
            cbt = new Timer(50, (e) -> {
                timer.setDelay(timer.getDelay() 150);
                if(thickness > 0) {
                    thickness -= 0.5f;
                }
                repaint();
                if(timer.getDelay() >= 2500) {
                    cbt.stop();
                    cbt = null;
                    return;
                }
            });
            cbt.start();
        } catch (Exception e) { }
        stopNow();
    }

    public void stopNow() {
        if(timer != null)
            timer.stop();
        timer = null;
        thickness = 0;
        System.gc();
    }

    public static void main(String[] args) throws InterruptedException {
//      this panel works!
//      JPanel t = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
//      my panel don't
        JStripedPanel t = new JStripedPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
        t.setBackground(Color.pink);
        t.setOpaque(true);
        t.setBorder(
                javax.swing.BorderFactory.createCompoundBorder(
                        new javax.swing.border.EmptyBorder(1, 1, 1, 1),
                        new javax.swing.border.LineBorder(Color.blue, 2, true))
        );
        t.add(new javax.swing.JLabel("test"));
        t.add(new javax.swing.JTextField("test2"));
        javax.swing.JFrame f = new javax.swing.JFrame();
        f.setBounds(10,10,400,300);

//      f.getContentPane().setLayout(new java.awt.GridLayout(3,3));
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
        f.getContentPane().add(t, java.awt.BorderLayout.CENTER);
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
//      f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
        
        f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        t.startAnim(2);
        Thread.sleep(10000);
        t.stopAnim(false);
        Thread.sleep(5000);
        t.startAnim(2);
    }
}

CodePudding user response:

Remove the call to g2.dispose() and it will work like a charm. You should not dispose it as, that same Graphics object is used further to draw the components inside the panel.

The main painting method works like this:

public void paint(Graphics g) {
  paintComponent(g);
  paintBorder(g);
  paintChildren(g);
}

Thus disposing the graphics in paintComponent makes it non-functional into the next paintxxx methods.

In a more general way of thinking, you should not clear/dispose/close any object you don't have the ownership. Someone creates the Graphics, pass it to you , you can use it (that's the purpose), but not dispose it. It is the responsability of the one that creates it.

  • Related