How to add JLabel with a transparent background on top of vlcj MediaPlayer?
I put source below, but it is not working as it should, because JLabel doesn't have transparent background set.
import com.sun.jna.NativeLibrary;
import javax.swing.*;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
class VideoExample extends JFrame {
private EmbeddedMediaPlayerComponent mediaPlayerComponent;
public VideoExample(String path) {
super("Простой видео плеер");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(640, 480);
//Create JLayeredPane
JLayeredPane mainLayer = new JLayeredPane();
mainLayer.setSize(640,480);
//Create MediaPlayer on background
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
mediaPlayerComponent.setLocation(0, 0);
mediaPlayerComponent.setSize(mainLayer.getSize());
//Create MediaPlayer on foreground
JLabel label = new JLabel("LABEL", JLabel.CENTER);
label.setBounds(100, 100, 200, 100);
label.setOpaque(false);
mainLayer.add(mediaPlayerComponent, JLayeredPane.DEFAULT_LAYER); //add mediaPlayer in DEFAULT_LAYER
mainLayer.add(label, JLayeredPane.PALETTE_LAYER); //add label in PALETTE_LAYER
add(mainLayer); // add JLayeredPane in JFrame
setVisible(true);
mediaPlayerComponent.getMediaPlayer().playMedia(path);
}
public static void main(String[] args) {
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), System.getProperty("user.dir") + "/lib/vlc64");
final String mrl = "D:\\Candlelight_QT.mov";
new VideoExample(mrl);
}
}
This is the result:
MadProgrammer is right. VLCJ attaches a native video surface to a java.awt.Canvas. You can supply your own Canvas with overridden paint(..) method but that won't help. This is what happens internally on Linux in LinuxVideoSurfaceAdapter
:
public void attach(LibVlc libvlc, MediaPlayer mediaPlayer, long componentId) {
Logger.debug("attach(componentId={})", componentId);
libvlc.libvlc_media_player_set_xwindow(mediaPlayer.mediaPlayerInstance(), (int)componentId);
}
The native java.awt.Canvas X11 window is used as a target for VLC output.
My best bet is to use the overlay mechanism like madprogrammer mentioned. Basically you'll need to supply a Window or JWindow by subclassing EmbeddedMediaPlayerComponent. As transparency is quite platform dependent you'll want to check if the desired type of transparency/transluncency is supported by your target environment (careful: complex graphics configurations might have different capabilities for each screen device!):
final boolean perPixelTranslucencySupported = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency.PERPIXEL_TRANSLUCENT);
Create a subclass of EmbeddedMediaPlayerComponent:
mediaPlayerComponent = new EmbeddedMediaPlayerComponent() {
@Override
protected Window onGetOverlay() {
final JWindow transparentWindow = new JWindow();
// Set basic window opacity if required - the window system must support WindowTranslucency (i.e. PERPIXEL_TRANSLUCENT)!
transparentWindow.setOpacity(0.8f);
// White with transparent alpha channel - WindowTranslucency is required for translucency.
transparentWindow.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));
final JLabel superImposedLightweigtLabel = new JLabel("Hello, VLC.", JLabel.CENTER);
superImposedLightweigtLabel.setOpaque(false);
transparentWindow.getContentPane().add(superImposedLightweigtLabel);
return transparentWindow;
}
...
}
After making the main JFrame visible, enable the overlay:
mediaPlayerComponent.getMediaPlayer().enableOverlay(true);
I couldn't verify the results as I am working in a virtual machine without transparency features right now so my actual JWindow overlay is NOT transparent for obvious reasons. Please let us know if it works as desired and if there are any other pitfalls.