与主要听众和建筑阵列一起播放视频的程序 (VLCJ)
Program to Play Videos (VLCJ) with Key Listeners and Building Arrays
我自愿帮助一个朋友完成一个项目,但我担心我可能会不知所措。基本思想是采用 3 个输入的组合,并根据 6 个可用组合播放特定视频。我正在使用 vlcj 加载和播放视频,最重要的是关键听众。如果每个视频只有 listen/use 一个输入,我终于能够让它们工作并且可以加载 6 个视频中的每一个。我挂断了等待 3 个输入的部分,并根据该组合播放单个视频。以下是我到目前为止所拥有的。我正在考虑构建一个包含 3 个输入的数组,然后检查该数组的内容与 6 种可能的组合进行比较。唯一的问题是我很确定我',不是在代码中正确比较 3 inputs/not 之后 properly/cutting 关闭它。当程序处于 运行 时我在键盘上键入 1、2、3 时,什么也没有发生。
代码可能看起来有点草率,因为很多代码是放在一起查看这里的各种帖子和 vlcj 提供的教程。任何帮助将不胜感激。
package javaapplication9;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Canvas;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
public class JavaApplication9 {
private final JFrame frame;
int[] tools = new int[3];
int[] vid1 = {1, 2, 3};
int[] vid2 = {1, 3, 2};
int[] vid3 = {2, 1, 3};
int[] vid4 = {2, 3, 1};
int[] vid5 = {3, 1, 2};
int[] vid6 = {3, 2, 1};
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JavaApplication9(args);
}
});
}
public JavaApplication9(String[] args) {
frame = new JFrame("Tutorials");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
System.exit(0);
}
});
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.setContentPane(mediaPlayerComponent);
frame.setVisible(true);
Canvas videoSurface = mediaPlayerComponent.getVideoSurface();
mediaPlayerComponent.getVideoSurface().requestFocus();
mediaPlayerComponent.getMediaPlayer().playMedia("file location0");
videoSurface.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyChar();
for (int i = 0; i < tools.length; i++){
tools[i] = key;
}
/*
if (key == KeyEvent.VK_1){
mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
}
if (key == KeyEvent.VK_2){
mediaPlayerComponent.getMediaPlayer().playMedia("file location2");
}
if (key == KeyEvent.VK_3){
mediaPlayerComponent.getMediaPlayer().playMedia("file location3");
}
if (key == KeyEvent.VK_4){
mediaPlayerComponent.getMediaPlayer().playMedia("file location4");
}
if (key == KeyEvent.VK_5){
mediaPlayerComponent.getMediaPlayer().playMedia("file location5");
}
if (key == KeyEvent.VK_6){
mediaPlayerComponent.getMediaPlayer().playMedia("file location6");
}
if (key == KeyEvent.VK_ESCAPE){
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
*/
}
});
if (tools == vid1){
mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
}
}
}
评论部分的所有内容都是我如何使用每个视频的单个输入(使用 e.getKeyCode() 而不是 e.getKeyChar())
谢谢!
更新
@MadProgrammer - 你的更新包含的基本上是我使用 list1.equals(list2) 命令所做的,尽管我认为你的方法是一种更简单的方法来解决这个问题。
我仍然 运行 关注使用输入构建数组的问题(在最终产品中将仅使用 1,2,3)如果该键不更新数组中键的位置已经存在于数组中。例如,我按下键 1、2、3 并构建 array/list [key1, key2, key3]
,这将播放 vid1
。如果我想在之后立即播放 vid3
,并尝试输入 2、1、3,则不会构建新数组,因为所有这些输入已经是输出数组的一部分,尽管顺序不同。但是,转到 4、5、6 然后返回到 2、1、3 是可行的。
有没有办法在按下第 4 个键时完全清除数组,并让第 4 个键位于正在构建的第 2 个数组的位置 0,从而产生一个新的输出数组 - 第一个的重新排列版本?
KeyListener
是善变的,要产生按键事件,不仅要可聚焦,还要有键盘焦点。
首先,您需要使 mediaPlayerComponent
或 videoSurface
可聚焦 (setFocsuable
) 并使用 requestFocusInWindow
为组件提供焦点。
这可能行不通,因为其他事情可能会将焦点从您的组件上移开,因此 MouseListener
可能会有用,因此您可以在单击视频表面时调用 requestFocusInWindow
。
更好的解决方案是使用旨在帮助解决此问题的键绑定 API。问题是,它只设计用于轻量级 (Swing) 组件,而不是 AWT 组件。
但是,您可以使用 JPanel
作为框架的 contentPane
并将您 mediaPlayerComponent
添加到其中。这样您就可以使用 JPanel
并将您的密钥绑定到它,例如...
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
/**
*
* @author swhitehead
*/
public class Player {
private final JFrame frame;
int[] tools = new int[3];
int[] vid1 = {1, 2, 3};
int[] vid2 = {1, 3, 2};
int[] vid3 = {2, 1, 3};
int[] vid4 = {2, 3, 1};
int[] vid5 = {3, 1, 2};
int[] vid6 = {3, 2, 1};
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Player(args);
}
});
}
private List<String> inputs = new ArrayList<>(3);
public Player(String[] args) {
frame = new JFrame("Tutorials");
frame.setSize(200, 200);
// frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
System.exit(0);
}
});
JPanel content = new JPanel(new BorderLayout());
bindKey(content, KeyEvent.VK_1, "key1");
bindKey(content, KeyEvent.VK_2, "key2");
bindKey(content, KeyEvent.VK_3, "key3");
bindKey(content, KeyEvent.VK_4, "key4");
bindKey(content, KeyEvent.VK_5, "key5");
bindKey(content, KeyEvent.VK_6, "key6");
frame.setContentPane(content);
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.add(mediaPlayerComponent);
frame.setVisible(true);
Canvas videoSurface = mediaPlayerComponent.getVideoSurface();
mediaPlayerComponent.getVideoSurface().requestFocus();
// mediaPlayerComponent.getMediaPlayer().playMedia("file location0");
//
// if (tools == vid1) {
// mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
// }
}
protected void bindKey(JComponent component, int keyCode, String name) {
InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = component.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), name + ".pressed");
actionMap.put(name + ".pressed", new PressAction(name));
}
protected void inputDidChange() {
System.out.println(inputs);
}
public class PressAction extends InputAction {
public PressAction(String name) {
super(name, true);
}
}
public class ReleaseAction extends InputAction {
public ReleaseAction(String name) {
super(name, false);
}
}
public class InputAction extends AbstractAction {
private String name;
private boolean pressed;
public InputAction(String name, boolean pressed) {
this.name = name;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
boolean didChange = false;
if (pressed) {
if (!inputs.contains(name)) {
while (inputs.size() > 2) {
inputs.remove(0);
}
inputs.add(name);
didChange = true;
}
} else {
didChange = inputs.remove(name);
}
if (didChange) {
inputDidChange();
}
}
}
}
有关详细信息,请参阅 How to Use Key Bindings
已更新
If I declare vid1 as 1,2,3 and vid2 as 4,5,6 it works flawlessly to play 2 seperate videos. If I use a different order like stated above (1,3,2) right after the 1,2,3 input array, it doesn't like it and will just keep playing the first video over again with each key press. Is there a way to clear the array and start over again once a 4th input is pressed, rather than overwriting the array using the most recent key presses? This method only seems to work if the 2nd set of inputs are entirely different from the 1st.
这是因为 List#contains
不关心元素的顺序...
所以,鉴于...
private List<String> vid1 = new ArrayList<>(Arrays.asList(new String[]{"key1", "key2", "key3"}));
private List<String> vid2 = new ArrayList<>(Arrays.asList(new String[]{"key4", "key5", "key6"}));
private List<String> vid3 = new ArrayList<>(Arrays.asList(new String[]{"key1", "key3", "key2"}));
我用过...
protected void inputDidChange() {
System.out.println(inputs);
if (contains(vid1, inputs)) {
System.out.println("vid1");
} else if (contains(vid2, inputs)) {
System.out.println("vid2");
} else if (contains(vid3, inputs)) {
System.out.println("vid3");
}
}
protected boolean contains(List<String> source, List<String> compare) {
boolean contains = source.size() == compare.size();
if (contains) {
for (int index = 0; index < source.size(); index++) {
if (!source.get(index).equals(compare.get(index))) {
contains = false;
break;
}
}
}
return contains;
}
检查每个索引处的每个元素以查看它们是否相等
Is there a way to completely clear the array when a 4th key is pressed, and have that 4th key be in position 0 of the 2nd array being built, leading to a new output array - a rearranged version of the first?
您可以将 InputAction
的 actionPerformed
方法更改为更像...
@Override
public void actionPerformed(ActionEvent e) {
boolean didChange = false;
if (pressed) {
if (!inputs.contains(name)) {
if (inputs.size() >= 3) {
inputs.clear();
}
inputs.add(name);
didChange = true;
}
} else {
didChange = inputs.remove(name);
}
if (didChange) {
inputDidChange();
}
}
基本上,如果 inputs
的大小是 >= 3
当按下一个键时, List
被清除并添加新键
记住,仅仅因为我使用 String
s 作为 "commands",并不意味着你必须这样做,你可以使用 int
或你想要的任何其他对象
我自愿帮助一个朋友完成一个项目,但我担心我可能会不知所措。基本思想是采用 3 个输入的组合,并根据 6 个可用组合播放特定视频。我正在使用 vlcj 加载和播放视频,最重要的是关键听众。如果每个视频只有 listen/use 一个输入,我终于能够让它们工作并且可以加载 6 个视频中的每一个。我挂断了等待 3 个输入的部分,并根据该组合播放单个视频。以下是我到目前为止所拥有的。我正在考虑构建一个包含 3 个输入的数组,然后检查该数组的内容与 6 种可能的组合进行比较。唯一的问题是我很确定我',不是在代码中正确比较 3 inputs/not 之后 properly/cutting 关闭它。当程序处于 运行 时我在键盘上键入 1、2、3 时,什么也没有发生。
代码可能看起来有点草率,因为很多代码是放在一起查看这里的各种帖子和 vlcj 提供的教程。任何帮助将不胜感激。
package javaapplication9;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Canvas;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
public class JavaApplication9 {
private final JFrame frame;
int[] tools = new int[3];
int[] vid1 = {1, 2, 3};
int[] vid2 = {1, 3, 2};
int[] vid3 = {2, 1, 3};
int[] vid4 = {2, 3, 1};
int[] vid5 = {3, 1, 2};
int[] vid6 = {3, 2, 1};
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JavaApplication9(args);
}
});
}
public JavaApplication9(String[] args) {
frame = new JFrame("Tutorials");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
System.exit(0);
}
});
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.setContentPane(mediaPlayerComponent);
frame.setVisible(true);
Canvas videoSurface = mediaPlayerComponent.getVideoSurface();
mediaPlayerComponent.getVideoSurface().requestFocus();
mediaPlayerComponent.getMediaPlayer().playMedia("file location0");
videoSurface.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyChar();
for (int i = 0; i < tools.length; i++){
tools[i] = key;
}
/*
if (key == KeyEvent.VK_1){
mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
}
if (key == KeyEvent.VK_2){
mediaPlayerComponent.getMediaPlayer().playMedia("file location2");
}
if (key == KeyEvent.VK_3){
mediaPlayerComponent.getMediaPlayer().playMedia("file location3");
}
if (key == KeyEvent.VK_4){
mediaPlayerComponent.getMediaPlayer().playMedia("file location4");
}
if (key == KeyEvent.VK_5){
mediaPlayerComponent.getMediaPlayer().playMedia("file location5");
}
if (key == KeyEvent.VK_6){
mediaPlayerComponent.getMediaPlayer().playMedia("file location6");
}
if (key == KeyEvent.VK_ESCAPE){
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
*/
}
});
if (tools == vid1){
mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
}
}
}
评论部分的所有内容都是我如何使用每个视频的单个输入(使用 e.getKeyCode() 而不是 e.getKeyChar())
谢谢!
更新
@MadProgrammer - 你的更新包含的基本上是我使用 list1.equals(list2) 命令所做的,尽管我认为你的方法是一种更简单的方法来解决这个问题。
我仍然 运行 关注使用输入构建数组的问题(在最终产品中将仅使用 1,2,3)如果该键不更新数组中键的位置已经存在于数组中。例如,我按下键 1、2、3 并构建 array/list [key1, key2, key3]
,这将播放 vid1
。如果我想在之后立即播放 vid3
,并尝试输入 2、1、3,则不会构建新数组,因为所有这些输入已经是输出数组的一部分,尽管顺序不同。但是,转到 4、5、6 然后返回到 2、1、3 是可行的。
有没有办法在按下第 4 个键时完全清除数组,并让第 4 个键位于正在构建的第 2 个数组的位置 0,从而产生一个新的输出数组 - 第一个的重新排列版本?
KeyListener
是善变的,要产生按键事件,不仅要可聚焦,还要有键盘焦点。
首先,您需要使 mediaPlayerComponent
或 videoSurface
可聚焦 (setFocsuable
) 并使用 requestFocusInWindow
为组件提供焦点。
这可能行不通,因为其他事情可能会将焦点从您的组件上移开,因此 MouseListener
可能会有用,因此您可以在单击视频表面时调用 requestFocusInWindow
。
更好的解决方案是使用旨在帮助解决此问题的键绑定 API。问题是,它只设计用于轻量级 (Swing) 组件,而不是 AWT 组件。
但是,您可以使用 JPanel
作为框架的 contentPane
并将您 mediaPlayerComponent
添加到其中。这样您就可以使用 JPanel
并将您的密钥绑定到它,例如...
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
/**
*
* @author swhitehead
*/
public class Player {
private final JFrame frame;
int[] tools = new int[3];
int[] vid1 = {1, 2, 3};
int[] vid2 = {1, 3, 2};
int[] vid3 = {2, 1, 3};
int[] vid4 = {2, 3, 1};
int[] vid5 = {3, 1, 2};
int[] vid6 = {3, 2, 1};
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Player(args);
}
});
}
private List<String> inputs = new ArrayList<>(3);
public Player(String[] args) {
frame = new JFrame("Tutorials");
frame.setSize(200, 200);
// frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
System.exit(0);
}
});
JPanel content = new JPanel(new BorderLayout());
bindKey(content, KeyEvent.VK_1, "key1");
bindKey(content, KeyEvent.VK_2, "key2");
bindKey(content, KeyEvent.VK_3, "key3");
bindKey(content, KeyEvent.VK_4, "key4");
bindKey(content, KeyEvent.VK_5, "key5");
bindKey(content, KeyEvent.VK_6, "key6");
frame.setContentPane(content);
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
frame.add(mediaPlayerComponent);
frame.setVisible(true);
Canvas videoSurface = mediaPlayerComponent.getVideoSurface();
mediaPlayerComponent.getVideoSurface().requestFocus();
// mediaPlayerComponent.getMediaPlayer().playMedia("file location0");
//
// if (tools == vid1) {
// mediaPlayerComponent.getMediaPlayer().playMedia("file location1");
// }
}
protected void bindKey(JComponent component, int keyCode, String name) {
InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = component.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), name + ".pressed");
actionMap.put(name + ".pressed", new PressAction(name));
}
protected void inputDidChange() {
System.out.println(inputs);
}
public class PressAction extends InputAction {
public PressAction(String name) {
super(name, true);
}
}
public class ReleaseAction extends InputAction {
public ReleaseAction(String name) {
super(name, false);
}
}
public class InputAction extends AbstractAction {
private String name;
private boolean pressed;
public InputAction(String name, boolean pressed) {
this.name = name;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
boolean didChange = false;
if (pressed) {
if (!inputs.contains(name)) {
while (inputs.size() > 2) {
inputs.remove(0);
}
inputs.add(name);
didChange = true;
}
} else {
didChange = inputs.remove(name);
}
if (didChange) {
inputDidChange();
}
}
}
}
有关详细信息,请参阅 How to Use Key Bindings
已更新
If I declare vid1 as 1,2,3 and vid2 as 4,5,6 it works flawlessly to play 2 seperate videos. If I use a different order like stated above (1,3,2) right after the 1,2,3 input array, it doesn't like it and will just keep playing the first video over again with each key press. Is there a way to clear the array and start over again once a 4th input is pressed, rather than overwriting the array using the most recent key presses? This method only seems to work if the 2nd set of inputs are entirely different from the 1st.
这是因为 List#contains
不关心元素的顺序...
所以,鉴于...
private List<String> vid1 = new ArrayList<>(Arrays.asList(new String[]{"key1", "key2", "key3"}));
private List<String> vid2 = new ArrayList<>(Arrays.asList(new String[]{"key4", "key5", "key6"}));
private List<String> vid3 = new ArrayList<>(Arrays.asList(new String[]{"key1", "key3", "key2"}));
我用过...
protected void inputDidChange() {
System.out.println(inputs);
if (contains(vid1, inputs)) {
System.out.println("vid1");
} else if (contains(vid2, inputs)) {
System.out.println("vid2");
} else if (contains(vid3, inputs)) {
System.out.println("vid3");
}
}
protected boolean contains(List<String> source, List<String> compare) {
boolean contains = source.size() == compare.size();
if (contains) {
for (int index = 0; index < source.size(); index++) {
if (!source.get(index).equals(compare.get(index))) {
contains = false;
break;
}
}
}
return contains;
}
检查每个索引处的每个元素以查看它们是否相等
Is there a way to completely clear the array when a 4th key is pressed, and have that 4th key be in position 0 of the 2nd array being built, leading to a new output array - a rearranged version of the first?
您可以将 InputAction
的 actionPerformed
方法更改为更像...
@Override
public void actionPerformed(ActionEvent e) {
boolean didChange = false;
if (pressed) {
if (!inputs.contains(name)) {
if (inputs.size() >= 3) {
inputs.clear();
}
inputs.add(name);
didChange = true;
}
} else {
didChange = inputs.remove(name);
}
if (didChange) {
inputDidChange();
}
}
基本上,如果 inputs
的大小是 >= 3
当按下一个键时, List
被清除并添加新键
记住,仅仅因为我使用 String
s 作为 "commands",并不意味着你必须这样做,你可以使用 int
或你想要的任何其他对象