2012-02-13 3 views
1

У меня есть компонент, расширяющий JPanel. Он сохраняет себя как bufferedimage при каждом вызове метода paintComponent. Компонент не полностью прозрачен, только его фон. Проблема в том, что фон не прозрачен. Я использую setOpaque (false);Компонент с прозрачным фоном для BufferedImage?

Вот мой соответствующий код;

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) {} 
} 
+0

Я не думаю, что создание BufferedImage автоматически делает его прозрачным. Вам все равно нужно нарисовать фон прозрачным цветом, используя метод 'fillRect (...)'. Отправьте свой SSCCE, если вам нужна дополнительная помощь. – camickr

+0

2 вещи, вы должны использовать print() для создания изображения, и вы не должны создавать изображение внутри paintComponent. Печать почти такая же, как paint(), но она включает/выключает некоторые флаги. Поэтому использование краски -> не будет работать. Использование печати внутри paintComponent -> не будет работать, потому что вы уже находитесь внутри метода рисования, что предотвратит настройку флажков печати. См. Мой ответ ниже. –

+0

Я видел ваш ответ, но я не мог понять, почему мой путь неправильный. Сейчас он работает, но какая проблема может возникнуть в будущем? Я использовал этот проект в качестве основы; http://www.leepoint.net/notes-java/examples/mouse/paintdemo.html. Из-за того, что вы позволяете пользователю рисовать, я должен перекрасить после каждого движения и сохранить это. Я думал, что это хороший способ. Как я могу это сделать в обстоятельствах, которые вы сказали? –

ответ

2

попробовать это:

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

Ключ использовать печать()

Edit: я попытался следующие и прозрачность работы как шарм:

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(); 
       } 
      } 
     }); 
    } 
} 
+0

Ничего не изменилось? Я отправлю SSCCE через минуту. –

+0

Кроме того, я бы выполнил операцию за пределами paintComponent (используя SwingUtilities.invokeLater()), потому что во время перерисовки включаются и выключаются все виды флагов. –

+0

Я просто добавляю g2.setColor (this.getForeground()); к моему методу drawCurrentShape. В любом случае, мне это нужно. Прозрачность в порядке, и я могу выбрать цвет. Спасибо за помощь. –

1

createImage(w, h) создаст «пустое» изображение с указанной шириной и высотой. При этом вам нужно будет указать createGraphics на экземпляр BufferedImage и нарисуйте непосредственно на возвращаемом объекте Graphics.

Смежные вопросы