Я пытаюсь нарисовать поверх панели vlcj (java-привязка библиотеки VLC), чтобы я мог воспроизвести видео и нарисовать поверх него. И у меня возникли некоторые проблемы. Вот полный базовый код:
Список кодов 1: AppOverlay.java
package app;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.sun.jna.platform.WindowUtils;
@SuppressWarnings("serial")
public class AppOverlay extends Window implements Runnable {
private final boolean isRunning;
private final int fps;
private BufferedImage graphics;
private BufferedImage img;
private int x, y;
private boolean ltr;
public AppOverlay(Window owner) {
super(owner, WindowUtils.getAlphaCompatibleGraphicsConfiguration());
setBackground(new Color(0,0,0,0));
graphics = new BufferedImage(1280,800, BufferedImage.TYPE_INT_ARGB);
isRunning = true;
img = null;
ltr = true;
fps = 60;
x = 0;
y = 0;
}
@Override
public void run(){
while(isRunning){
try{
Thread.sleep(1000/fps);
} catch(InterruptedException e){
e.printStackTrace();
}
if(ltr) {
if(x < 1280) x++;
else ltr = false;
} else {
if(x < 0) ltr = true;
else x--;
}
repaint();
}
}
public void createAndShowGUI() {
setVisible(true);
Thread thread = new Thread(this);
thread.start();
String path = "Drive:\\path\\to\\image.png";
try {
img = ImageIO.read(new java.io.FileInputStream(path));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
Graphics2D gfx = graphics.createGraphics();
gfx.setColor(new Color(255,255,255,0));
gfx.clearRect(0, 0, 1280, 800);
if(img != null) gfx.drawImage(img, x, y, null);
gfx.dispose();
g2d.drawImage(graphics, 0, 0, null);
}
}
Список кодов 2: AppPlayer.java
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
@SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
Листинг 3: AppFrame.java
package app;
import java.awt.Dimension;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class AppFrame extends JFrame {
private AppPlayer appPlayer;
private AppOverlay overlay;
public AppFrame(){
super();
}
public void createAndShowGUI() {
appPlayer = new AppPlayer();
appPlayer.setPreferredSize(new Dimension(1280,800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("App");
setVisible(true);
pack();
overlay = new AppOverlay(this);
appPlayer.mediaPlayer().overlay().set(overlay);
appPlayer.mediaPlayer().overlay().enable(true);
overlay.createAndShowGUI();
}
}
Листинг 4: Main.java
package main;
import javax.swing.SwingUtilities;
import app.AppFrame;
public class Main {
public static void main(String[] args) {
final AppFrame app = new AppFrame();
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
app.createAndShowGUI();
}
});
}
}
с этим и библиотекой vlcj-4 вы сможете самостоятельно протестировать мой код. Моя проблема в том, что Overlay (класс AppOverlay, который расширяет класс Window) не отображает и не обновляет анимацию, если я не отменил выбор окна (я щелкаю по другому окну или на рабочем столе или на панели инструментов ОС), чтобы окно (приложение)неактивен, затем снова выберите окно (приложение). Он будет загружать только один кадр и все. Я должен отменить выбор и повторно выбрать окно, чтобы загрузить другой кадр (это только в случае с наложением, т. Е. Если я воспроизведу видео в классе AppPlayer, видео будет воспроизводиться очень хорошо.
Что яхочу иметь возможность рисовать анимированную графику на оверлее. Я знаю, что с классом JPanel есть метод paintComponent (), но класс Window не имеет этого метода (только методы paint () и repaint ()доступно).
Что мне нужно сделать, чтобы это исправить?
РЕДАКТИРОВАТЬ:
Я попытался добавить JPanel, на котором я рисую, вместо того, чтобы рисовать напрямуюна AppOverlay
Code-листинг 5: AppPanel.java
package app;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class AppPanel extends JPanel implements Runnable {
private int x, y;
private boolean ltr;
public AppPanel() {
x = 0;
y = 0;
ltr = true;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0,0,0,0));
g.clearRect(0, 0, 1280, 800);
g.setColor(Color.RED);
g.fillRect(x, y, 100, 100);
}
@Override
public void run() {
while(true){
try{
Thread.sleep(1000/60);
} catch(InterruptedException e){
e.printStackTrace();
}
if(ltr) {
if(x < 1280) x++;
else ltr = false;
} else {
if(x < 0) ltr = true;
else x--;
}
repaint();
}
}
}
и добавление его в AppOverlay.
Code-листинг 6: AppOverlay.java с частичной модификацией
public class AppOverlay extends Window implements Runnable {
//previous field declaration above ...
AppPanel panel;
AppPlayer player = null;
public AppOverlay(Window owner) {
//previous constructor instructions above...
panel = new AppPanel();
add(panel);
}
public void createAndShowGUI(AppPlayer player) {
setVisible(true);
/*
Thread thread = new Thread(this);
thread.start();
String path = "Drive:\\path\\to\\image.png";
try {
img = ImageIO.read(new java.io.FileInputStream(path));
} catch (IOException e) {
e.printStackTrace();
}
*/
Thread panelThread = new Thread(panel);
panelThread.start();
}
}
При этом отобразятся графические элементы JPanel и анимированы их по мере необходимости.
Если вы знаете способ созданияJPanel фон прозрачный (так что мы можемn видеть насквозь), все еще позволяя ему отображать графику. Это наверняка решит проблему.