Animation on Transparent-Background Jframe Linux

Animation on Transparent-background JFrame Linux

Basically this issue is OS-related. What works for Windows will not work for Linux and vice versa.

For some reason, Linux only allows animated per-pixel-transparency when setting up a BufferStrategy. However, this solution fails on Windows. As a result I have come up with the following code which picks the correct algorithm based on the OS:

static int a = 0;

public static void main(String[] args) {
JFrame f = new JFrame();
JPanel p = new JPanel() {
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, f.getWidth(), f.getHeight());
g2d.drawRect(a, a++, 2, 2);
}
};
f.add(p);
f.setUndecorated(true);
f.setBackground(new Color(255, 255, 255, 0));
f.setSize(512, 512);
f.setVisible(true);
f.createBufferStrategy(2);

BufferStrategy bs = f.getBufferStrategy();
while (true) {
try {
Thread.sleep(33);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (System.getProperty("os.name").contains("indows ")) {
p.repaint();
} else {
Graphics g = null;
do {
try {
g = bs.getDrawGraphics();
p.update(g);
} finally {
g.dispose();
}
bs.show();
} while (bs.contentsLost());
Toolkit.getDefaultToolkit().sync();
}
}
}

This code works for my Windows 7 x64 and my Lubuntu 15.04 x64. Please try out this code out yourself and see if it works for you. I myself don't own a Mac so if someone would please test it for me I would be very grateful. If it does not work for anyone, please let me know.

This is what you're supposed to see:

Sample Image

transparant background in a jframe but with window border etc

For a transparent/transuculent JFrame see here: http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html which explains translucent Windows in Java.

You need to call setOpacity().

Here is also a small example :

Screenshot for app

import java.awt.*;
import javax.swing.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;

public class TranslucentWindowDemo extends JFrame {

public TranslucentWindowDemo() {
super("TranslucentWindow");
setLayout(new GridBagLayout());

setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Add a sample button.
add(new JButton("I am a Button"));
}

public static void main(String[] args) {
// Determine if the GraphicsDevice supports translucency.
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();

//If translucent windows aren't supported, exit.
if (!gd.isWindowTranslucencySupported(TRANSLUCENT)) {
System.err.println(
"Translucency is not supported");
System.exit(0);
}

JFrame.setDefaultLookAndFeelDecorated(true);

// Create the GUI on the event-dispatching thread
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
TranslucentWindowDemo tw = new TranslucentWindowDemo();

// Set the window to 55% opaque (45% translucent).
tw.setOpacity(0.55f);

// Display the window.
tw.setVisible(true);
}
});
}
}

How to ignore JFrame opacity?

Don't use setOpacity, use setBackground on the JFrame and pass it a alpha based color. This will allow the frame to become transparent without affecting the other components.

You may, however, find that Canvas doesn't like alpha based colors (as it only has an opaque state)

How to properly work with transparent JPanel within a non-opaque JFrame?

Java components don't have a concept of transparency, they are either opaque or fully transparent (alright, the new transparency support for top level windows is an exception ;))

What you need to do is create a custom component that is fully transparent and the override it's paintComponent and fill the area of the component with your translucent color.

Also, don't modify the state of Swing components outside of the context of the Event Dispatching Thread, strange things begin to happen. A better solution might be to use a javax.swing.Timer

For example

  • Create rectangle with mouse drag, not draw
  • Java Swing: Transparent PNG permanently captures original background
  • How to make a transparent JFrame but keep everything else the same?

You may also want to take a look at Concurrency in Swing

Java Swing Graphical Glitches Dealing with Transparency and Images

I can see a number of issues with your example, but the most significant is the use of a color with an alpha value.

fader.setBackground(new Color(0, 0, 0, 40));

Swing doesn't render components with alpha based colors well (within this context). By making component opaque and then setting the background color to use an alpha value, you are telling Swing that it doesn't need to worry about painting what's underneath your component, which isn't true...

The Graphics context is also a shared resource, meaning that anything that was painted before your component is still "painted", you need to clear the Graphics context before painting.

Sample ImageSample Image

This example uses a rather nasty trick to get it's work done. Because all the painting occurs within the UI delegate, if we were simply to allow the default paint chain to continue, we wouldn't be able to render underneath the icon. Instead, we take over control of the "dirty" details and paint the background on the behalf the parent.

This would be simpler to achieve if we simple extended from something like JPanel and painted the image ourselves

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FadingIcon {

public static void main(String[] args) {
new FadingIcon();
}

public FadingIcon() {
startUI();
}

public void startUI() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

BufferedImage img = null;
try {
img = ImageIO.read(new File("C:\\Users\\swhitehead\\Documents\\My Dropbox\\Ponies\\SmallPony.png"));
} catch (IOException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setLayout(new GridBagLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FadingLabel(new ImageIcon(img)));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class FadingLabel extends JLabel {

private boolean mouseIn = false;
private MouseHandler mouseHandler;

public FadingLabel(Icon icon) {
super(icon);
setBackground(Color.RED);
super.setOpaque(false)(
}

@Override
public void setOpaque(boolean opaque) {
}

@Override
public final boolean isOpaque() {
return false;
}

protected MouseHandler getMouseHandler() {
if (mouseHandler == null) {
mouseHandler = new MouseHandler();
}
return mouseHandler;
}

@Override
public void addNotify() {
super.addNotify();
addMouseListener(getMouseHandler());
}

@Override
public void removeNotify() {
removeMouseListener(getMouseHandler());
super.removeNotify();
}

@Override
protected void paintComponent(Graphics g) {
if (mouseIn) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
}
getUI().paint(g, this);
}

public class MouseHandler extends MouseAdapter {

@Override
public void mouseEntered(MouseEvent e) {
mouseIn = true;
repaint();
}

@Override
public void mouseExited(MouseEvent e) {
mouseIn = false;
repaint();
}

}

}

}

I would also recommend that you take the time to learn how to use appropriate layout managers, they will save you a lot of hair pulling later

Check out A Visual Guide to Layout Managers and Laying Out Components Within a Container

Create a ImageIcon that is the mirror of another one

You might want to try and subclassing the ImageIcon class and paint the image reversed. Try this piece of code, it might do the trick (i haven't tried with animated transparent gif but it should work):

EDIT: I slightly changed the code and tested it with an animated gif. It works!

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


/**
* @author Savvas Dalkitsis
*/
public class Test {

public static void main(String[] args) {
JFrame f = new JFrame("Test");
JLabel l = new JLabel();
ImageIcon io = new MirrorImageIcon("test.gif");
l.setIcon(io);
f.getContentPane().add(l);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}

}

@SuppressWarnings("serial")
class MirrorImageIcon extends ImageIcon {

public MirrorImageIcon(String filename) {
super(filename);
}

@Override
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D)g.create();
g2.translate(getIconWidth(), 0);
g2.scale(-1, 1);
super.paintIcon(c, g2, x, y);
}

}


Related Topics



Leave a reply



Submit