Hallo Leute!
Ich bin wieder bei einem Problem steckengelieben und komme bisher alleine nicht weiter.
Ich möchte auf einem JPanel (das in einem JLayeredPane liegt) malen, das einen transparenten Hintergrund hat. Der einzige Weg auf den ich gekommen bin ist mir das Image das ich in meiner überschriebenen paintComponent Methode nutze zu schnappen und mit folgendem Code den Hintergrund Transparent zu machen:
Wenn ich irgendwas beim initialisieren male funktioniert das wunderbar. Wenn ich jedoch aktiv (z.B. über einen Button) Grafiken dazumalen möchte wird nichts gemalt.
Ich habe ein kleines Beispielprojekt gemacht bei dem das ganze deutlich wird, hier mal der Reihe nach die drei übrigen Klassen(im Anhang auch das Projekt, wenn es sich jemand in seiner IDE angucken/ausführen möchte).
Die Hauptframe:
Die Leinwand (das JLayeredPane):
Und zum Schluss die Malflaeche,also das JPanel auf dem letzendlich gemalt werden soll:
So wie es jetzt im Code steht wird erstmal keine Transparenz gesetzt, das Malen funktioniert wie es soll. Wenn man in der draw() Methode der hier zuletzt aufgeführten Klasse Malflaeche die Zeile "image = Transparency.makeColorTransparent(image, this.getBackground());" wieder entkommentiert wird die Transparenz richtig gesetzt, malen funktioniert aber nicht.
Ich hoffe hier weiss jemand Rat.
Ich bin wieder bei einem Problem steckengelieben und komme bisher alleine nicht weiter.
Ich möchte auf einem JPanel (das in einem JLayeredPane liegt) malen, das einen transparenten Hintergrund hat. Der einzige Weg auf den ich gekommen bin ist mir das Image das ich in meiner überschriebenen paintComponent Methode nutze zu schnappen und mit folgendem Code den Hintergrund Transparent zu machen:
Java:
import java.awt.*;
import java.awt.image.*;
/**
* Code aus Reals How to
* @author Real's How to
*
*/
public class Transparency {
public static Image makeColorTransparent
(Image im, final Color color) {
ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFF000000;
public final int filterRGB(int x, int y, int rgb) {
if ( ( rgb | 0xFF000000 ) == markerRGB ) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
}
else {
// return
return rgb;
}
}
};
ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(ip);
}
}
Wenn ich irgendwas beim initialisieren male funktioniert das wunderbar. Wenn ich jedoch aktiv (z.B. über einen Button) Grafiken dazumalen möchte wird nichts gemalt.
Ich habe ein kleines Beispielprojekt gemacht bei dem das ganze deutlich wird, hier mal der Reihe nach die drei übrigen Klassen(im Anhang auch das Projekt, wenn es sich jemand in seiner IDE angucken/ausführen möchte).
Die Hauptframe:
Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainFrame extends JFrame
{
Leinwand leinwand ;
JButton move;
public static void main(String[] args)
{
new MainFrame();
}
public MainFrame()
{
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
move = new JButton("move");
this.setBounds(100,100,200,200);
leinwand = new Leinwand();
leinwand.setBounds(this.getBounds());
this.add(BorderLayout.CENTER,leinwand);
this.add(BorderLayout.SOUTH,move);
MyListener ml = new MyListener();
move.addActionListener(ml);
this.setVisible(true);
leinwand.init();
}
class MyListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0)
{
leinwand.moveIt();
}
}
}
Die Leinwand (das JLayeredPane):
Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JLayeredPane;
public class Leinwand extends JLayeredPane
{
Malflaeche malflaeche;
private Image image;
private Graphics2D g2d;
private Color background = Color.GREEN;
public void moveIt()
{
malflaeche.moveIt();
}
public void init()
{
malflaeche = new Malflaeche();
malflaeche.setBounds(this.getBounds());
this.add(malflaeche);
malflaeche.setVisible(true);
malflaeche.setOpaque(false);
malflaeche.draw();
}
@Override
public void paintComponent(final Graphics g)
{
super.paintComponent(g);
// initialises the image with the first paint
// or checks the image size with the current panelsize
if (image == null || image.getWidth(this) < getSize().width
|| image.getHeight(this) < getSize().height)
{
resetImage();
}
Rectangle r = g.getClipBounds(); // das ClipRectangle holen um zu
// wissen, welcher Bereich erneuert
// werden soll
g.drawImage(image, r.x, r.y, r.width + r.x, r.height + r.y, r.x, r.y,
r.width + r.x, r.height + r.y, null);
}
private void resetImage()
{
Image saveImage = image;
Graphics2D saveG2d = g2d;
image = this.createImage(getWidth(), getHeight());
g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setBackground(background);
// g2d.setBackground(Color.GREEN);
g2d.clearRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
if (saveG2d != null)
{
g2d.setColor(saveG2d.getColor());
g2d.drawImage(saveImage, 0, 0, this);
saveG2d.dispose();
}
}
public Graphics2D getGraphics2D()
{
return g2d;
}
}
Und zum Schluss die Malflaeche,also das JPanel auf dem letzendlich gemalt werden soll:
Java:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JPanel;
public class Malflaeche extends JPanel
{
private Image image;
private Graphics2D g2d;
int movevalue = 1;
public void draw()
{
image = createImage(this.getWidth(), this.getHeight());
g2d = (Graphics2D) image.getGraphics();
//TODO Hier Transparenz setzen
//image = Transparency.makeColorTransparent(image, this.getBackground());
getGraphics2D().setPaintMode();
getGraphics2D().setColor(Color.BLACK);
int pensize = 3;
getGraphics2D().setStroke(
new BasicStroke(pensize, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
getGraphics2D().drawRoundRect(10, 10, 50 - 6, 50 - 6, 5, 5);
repaint();
}
public void moveIt()
{
movevalue++;
getGraphics2D().setPaintMode();
getGraphics2D().setColor(Color.BLACK);
int pensize = 3;
getGraphics2D().setStroke(
new BasicStroke(pensize, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
getGraphics2D().drawRoundRect(10+movevalue, 10+movevalue, 50 - 6, 50 - 6, 5, 5);
repaint();
}
private void resetImage()
{
Image saveImage = image;
Graphics2D saveG2d = g2d;
image = this.createImage(getWidth(), getHeight());
g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.clearRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
if (saveG2d != null)
{
g2d.setColor(saveG2d.getColor());
g2d.drawImage(saveImage, 0, 0, this);
saveG2d.dispose();
}
}
@Override
public void paintComponent(final Graphics g)
{
super.paintComponent(g);
if (image == null || image.getWidth(this) < getSize().width
|| image.getHeight(this) < getSize().height)
{
resetImage();
}
Rectangle r = g.getClipBounds();
g.drawImage(image, r.x, r.y, r.width + r.x, r.height + r.y, r.x, r.y,
r.width + r.x, r.height + r.y, null);
}
public Graphics2D getGraphics2D()
{
return g2d;
}
}
So wie es jetzt im Code steht wird erstmal keine Transparenz gesetzt, das Malen funktioniert wie es soll. Wenn man in der draw() Methode der hier zuletzt aufgeführten Klasse Malflaeche die Zeile "image = Transparency.makeColorTransparent(image, this.getBackground());" wieder entkommentiert wird die Transparenz richtig gesetzt, malen funktioniert aber nicht.
Ich hoffe hier weiss jemand Rat.