首页 > 解决方案 > Java swing paint 不显示内部组件

问题描述

我创建了一个自定义的 JPanel,它的背景是固定的或动画的对角线。我想知道如果我将任何 jcomponent 添加到面板,它根本不会显示。我知道这个问题是因为我在组件上绘画,但我不知道如何解决它。这是我的完整代码。

一些帮助将不胜感激:)

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);
    }
}

标签: javaswing

解决方案


删除对的调用g2.dispose(),它将像一个魅力一样工作。您不应该将其处理为,相同Graphics的对象被进一步用于在面板内绘制组件。

主要的绘画方法是这样的:

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

因此,将图形置于paintComponent其中使其无法在下一个paintxxx方法中使用。

在更一般的思维方式中,您不应该清除/处置/关闭您没有所有权的任何对象。有人创建Graphics,传递给你,你可以使用它(这就是目的),但不能丢弃它。这是创造它的人的责任。


推荐阅读