【问题标题】:Component with transparent background to BufferedImage?具有 BufferedImage 透明背景的组件?
【发布时间】:2012-03-05 03:51:33
【问题描述】:

我有一个组件扩展了 JPanel。它在每次调用paintComponent 方法时将自己保存为缓冲图像。组件不是完全透明的,只有它的背景。问题是背景不透明。我正在使用 setOpaque(false);

这是我的相关代码;

private BufferedImage bufImage = null;

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;

    // if first time call
    if (bufImage == null) {
        int w = this.getWidth();
        int h = this.getHeight();
        bufImage = (BufferedImage)this.createImage(w, h);
    }

    g2.drawImage(bufImage, null, 0, 0);

    // draw sth
    g2.draw(sth);
}

--

我也试过了

bufImage =  new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

而不是

bufImage = (BufferedImage)this.createImage(w, h);

当我这样做时;背景透明效果有效,但我只能用白色绘制。我不知道是什么原因造成的。

注意: 我用那个代码来检查它是否工作;

File outputfile = new File("saved.png");
ImageIO.write(bufImage, "png", outputfile);

saved.png 具有透明背景,但图纸只有白色。


这是组件,只能用鼠标画矩形;

class PaintPanel extends JPanel implements MouseListener, MouseMotionListener {
    private BufferedImage _bufImage = null;
    private boolean dragging = false;
    private Point _start = null, _end = null;

    public PaintPanel() {
        setOpaque(false);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;

        if (_bufImage == null) {
            int w = this.getWidth();
            int h = this.getHeight();
            _bufImage =  new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            //_bufImage = (BufferedImage)this.createImage(w, h);
        }

        g2.drawImage(_bufImage, null, 0, 0);

        if (dragging) {
            drawCurrentShape(g2);
        }
    }

    private void drawCurrentShape(Graphics2D g2) {
        int startx = (int) _start.getX();
        int starty = (int) _start.getY();
        int stopx = (int) _end.getX();
        int stopy = (int) _end.getY();

        int width = Math.abs(startx - stopx);
        int height = Math.abs(starty - stopy);
        int x = startx, y = starty;
        if(x > stopx)
            x = stopx;
        if(y > stopy)
            y = stopy;

        Rectangle r = new Rectangle(x, y, width, height);
        g2.draw(r);
    }

    public void mousePressed(MouseEvent e) {
        dragging = true;       
        _start = e.getPoint();
        _end   = _start;
    }

    public void mouseDragged(MouseEvent e) {
        _end = e.getPoint();
        this.repaint();
    }

    public void mouseReleased(MouseEvent e) {
        _end = e.getPoint();
        if (dragging) {
            dragging = false;
            drawCurrentShape(_bufImage.createGraphics());  
            this.repaint();
        }
    }

    public void mouseMoved  (MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited (MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
}

【问题讨论】:

  • 我不认为创建 BufferedImage 会自动使其透明。您仍然需要使用fillRect(...) 方法以透明颜色绘制背景。如果您需要更多帮助,请发布您的 SSCCE。
  • 两件事,你应该使用 print() 来创建图像,你不应该在paintComponent中创建图像。 Print 与 paint() 几乎相同,但它会打开/关闭一些标志。因此使用paint--> 将不起作用。在paintComponent--> 中使用print 将不起作用,因为您已经在paint 方法中,这将阻止设置打印标志。请参阅下面的答案。
  • 我看到了你的回答,但我不明白为什么我的方式是错误的。它现在正在工作,但是这会在未来引起什么样的问题?我以这个项目为基础; leepoint.net/notes-java/examples/mouse/paintdemo.html 。由于让用户绘制,我必须在每次移动后重新绘制并保存。我认为这是一个好方法。在你说的情况下,我该怎么做?

标签: java swing transparency bufferedimage paintcomponent


【解决方案1】:

试试这个:

bufImage = new BufferedImage(w,h,java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufImage.createGraphics();
this.print(graphics);
graphics.dispose();

关键是使用print()

编辑:我尝试了以下方法,透明度就像一个魅力:

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test2 {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JPanel p = new JPanel();
        p.setPreferredSize(new Dimension(400, 400));
        p.setOpaque(false);
        JButton button = new JButton("Hello world");
        p.add(button);
        frame.add(p);
        frame.pack();
        frame.setVisible(true);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                BufferedImage bufImage = new BufferedImage(p.getWidth(), p.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
                Graphics2D graphics = bufImage.createGraphics();
                p.print(graphics);
                graphics.dispose();
                try {
                    ImageIO.write(bufImage, "png", new File("d:/tmp/tmp.png"));
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }
}

【讨论】:

  • 什么都没有改变?我会在一分钟内发布一个 SSCCE。
  • 另外,还有一件事,我会在 paintComponent 之外执行操作(使用 SwingUtilities.invokeLater()),因为在重绘期间会打开和关闭各种标志。
  • 我只是添加了 g2.setColor(this.getForeground());到我的 drawCurrentShape 方法。无论如何我都会需要它。透明度还可以,我可以选择颜色。感谢您的帮助。
【解决方案2】:

createImage(w, h) 将创建一个具有指定宽度和高度的“空白”图像。话虽如此,您需要做的是在 BufferedImage 实例上调用 createGraphics 并直接绘制到返回的 Graphics 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多