如何在Java中刷新窗口类的图形
我试图画一个vlcj(VLC库的java绑定)面板,这样我就可以播放视频并在上面画。我遇到了一些问题。以下是完整的基本代码: 代码清单1:AppOverlay.java如何在Java中刷新窗口类的图形,java,awt,vlcj,Java,Awt,Vlcj,我试图画一个vlcj(VLC库的java绑定)面板,这样我就可以播放视频并在上面画。我遇到了一些问题。以下是完整的基本代码: 代码清单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
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);
}
}
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
@SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
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();
}
}
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();
}
});
}
}
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();
}
}
}
代码清单3:AppFrame.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);
}
}
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
@SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
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();
}
}
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();
}
});
}
}
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();
}
}
}
代码清单4:Main.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);
}
}
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
@SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
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();
}
}
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();
}
});
}
}
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();
}
}
}
有了它和vlcj-4库,你应该可以自己测试我的代码了。我的问题是覆盖(扩展窗口类的AppOverlay类)不会显示或刷新动画,除非我取消选择窗口(单击其他窗口或桌面或操作系统工具栏),使窗口(应用程序)处于非活动状态,然后再次选择窗口(应用程序)。它将只加载一个帧,仅此而已。我必须取消选择并再次选择窗口以加载另一帧(这仅适用于叠加,即如果我在AppPlayer类中播放视频,视频将正常播放)
我想要的是能够在覆盖上绘制一些动画图形。我知道JPanel类有paintComponent()方法,但Window类没有该方法(只有paint()和repaint()方法可用)
我该怎么做才能解决这个问题
编辑:
我尝试添加一个我在上面绘制的JPanel,而不是直接在AppOverlay上绘制
代码清单5:AppPanel.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);
}
}
package app;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
@SuppressWarnings("serial")
public class AppPlayer extends EmbeddedMediaPlayerComponent {
}
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();
}
}
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();
}
});
}
}
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();
}
}
}
这样做将显示JPanel的图形,并根据需要设置动画
如果您知道如何使JPanel背景透明(以便我们可以看穿它),同时仍让它显示其图形。这肯定会解决问题。您已经完成了大部分工作。只需调用
app.repaint()在每次绘制帧时重新绘制帧即可;
您可以使用JComponent中的以下方法:()
我仔细研究了一下你的例子,想出了一些有效的方法,但我不认为这是一个好的解决方案 主要的问题似乎是没有办法告诉覆盖层刷新(或者我只是没有找到它)。只是
重新绘制
覆盖层不会在屏幕上更新它,所以我使用的解决方法是隐藏并再次显示它
对于更新间隔的计时,我使用了javax.swing.Timer
。
(在真实版本中,您可能希望通过MediaPlayerEventListener
启动和停止计时器)
作为副作用,调用repaint
方法,并调整x
坐标以在屏幕上移动图像
在下面的简化示例中(使用main
运行它),我移动了一个带有x坐标的红色矩形,而不是一些未知图像
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.HeadlessException;
导入java.awt.Window;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JFrame;
导入javax.swing.Timer;
导入com.sun.jna.platform.WindowUtils;
导入uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.OverlayApi;
公共类AppFrame扩展了JFrame{
私有静态最终长serialVersionUID=-1569823648323129877L;
公共类覆盖扩展窗口{
私有静态最终长serialVersionUID=8337750467830040964L;
私有整数x,y;
私有布尔ltr=true;
公共覆盖(窗口所有者)抛出HeadlessException{
super(所有者,WindowUtils.getAlphaCompatibleGraphicConfiguration());
挫折背景(新颜色(0,0,0,0));
}
@凌驾
公共空间涂料(图g){
超级油漆(g);
如果(ltr){
if(x<1180)
x+=1;
其他的
ltr=假;
}否则{
if(x<0)
ltr=真;
其他的
x-=1;
}
g、 setColor(Color.RED);
g、 fillRect(x,y,100100);
字符串s=整数。toString(x);
g、 setColor(Color.WHITE);
g、 拉丝字符(s.toCharArray(),0,s.length(),x+10,y+50);
}
}
私有嵌入式媒体播放器组件appPlayer;
public void createAndShowGUI(){
appPlayer=新的EmbeddedMediaPlayerComponent();
setPreferredSize(新维度(1280800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(关闭时退出);
setTitle(“App”);
setVisible(真);
包装();
覆盖层=新覆盖层(本);
OverlayApi api=appPlayer.mediaPlayer().overlay();
api.set(覆盖);
api.enable(true);
//appPlayer.mediaPlayer().media().play(“…”);
计时器计时器=新计时器(0,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
api.enable(假);
api.enable(true);
}
});
timer.setRepeats(真);
定时器设置延迟(200);
timer.start();
}
}
如果这是您的一个选择,那么使用
动画gif
可能会容易得多。至少它本身可以工作(不需要计时器)
更新: 正如您所发现的,使用
JPanel
似乎效果更好。
只需使用setOpaque(false)
使其透明即可
这里是一个调整后的例子
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.OverlayApi;
public class AppFrame2 extends JFrame {
private static final long serialVersionUID = -1569823648323129877L;
public class OverlayPanel extends JPanel {
private static final long serialVersionUID = 8070414617530302145L;
private int x, y;
private boolean ltr = true;
public OverlayPanel() {
this.setOpaque(false);
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (ltr) {
if (x < 1180)
x += 1;
else
ltr = false;
} else {
if (x < 0)
ltr = true;
else
x -= 1;
}
g.setColor(Color.RED);
g.fillRect(x, y, 100, 100);
String s = Integer.toString(x);
g.setColor(Color.WHITE);
g.drawChars(s.toCharArray(), 0, s.length(), x+10, y+50);
}
}
public class Overlay extends Window {
private static final long serialVersionUID = 8337750467830040964L;
OverlayPanel panel;
public Overlay(Window owner) throws HeadlessException {
super(owner);
setBackground(new Color(0,0,0,0));
panel = new OverlayPanel();
this.add(panel);
}
}
private EmbeddedMediaPlayerComponent appPlayer;
public void createAndShowGUI() {
appPlayer = new EmbeddedMediaPlayerComponent();
appPlayer.setPreferredSize(new Dimension(1280, 800));
getContentPane().add(appPlayer);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("App");
setVisible(true);
pack();
Overlay overlay = new Overlay(this);
OverlayApi api = appPlayer.mediaPlayer().overlay();
api.set(overlay);
api.enable(true);
//appPlayer.mediaPlayer().media().play(" ... ");
Timer timer = new Timer(0, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
overlay.panel.repaint();
}
});
timer.setRepeats(true);
timer.setDelay(17);
timer.start();
}
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.HeadlessException;
导入java.awt.Window;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
import uk.co.caprica.vlcj.player.component.Em