在 JPanel 中显示图像时遇到问题
Trouble with displaying images in JPanel
我正在尝试编写一个应用程序来获取视频帧,对其进行处理,然后将它们作为图像显示在 JPanel
中。我使用OpenCV库获取视频帧(一帧一帧),然后处理后显示在屏幕上(达到播放视频的效果)。
我使用 Java Swing 创建了 GUI。创建了一个 window 应用程序,其中包含必要的按钮和一个显示视频的面板。单击“开始”后,将调用一个方法 playVideo
,该方法从所选视频中获取视频帧,对其进行修改并将其显示在面板中。我的代码如下所示:
public class HelloApp {
private JFrame frame;
private JPanel panel;
final JLabel vidpanel1;
ImageIcon image;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
HelloApp window = new HelloApp();
window.frame.setVisible(true);
}
});
}
public void playVideo() throws InterruptedException{
Mat inFrame = new Mat();
VideoCapture camera = new VideoCapture();
camera.open(Config.filename);
while (true) {
if (!camera.read(inFrame))
break;
Imgproc.resize(inFrame, inFrame, new Size(Config.FRAME_WIDTH, Config.FRAME_HEIGHT), 0., 0., Imgproc.INTER_LINEAR);
... processing frame
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame)); // option 0
vidpanel1.setIcon(image);
vidpanel1.repaint();
}
}
public HelloApp() {
frame = new JFrame("MULTIPLE-TARGET TRACKING");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);//new FlowLayout()
frame.setResizable(false);
frame.setBounds(50, 50, 800, 500);
frame.setLocation(
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().width,
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().height
);
frame.setVisible(true);
vidpanel1 = new JLabel();
panel = new JPanel();
panel.setBounds(11, 39, 593, 371);
panel.add(vidpanel1);
frame.getContentPane().add(panel);
JButton btnStart = new JButton("START / REPLAY");
btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
playVideo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
}
}
每次单击“开始”按钮时,我都尝试删除旧面板并创建一个新面板,但没有成功。我也在 运行 方法 playVideo
之前尝试使用以下方法清洁所有面板:
panel.removeAll();
panel.repaint();
playVideo();
老实说,我不知道出了什么问题。创建了 GUI,拍摄并处理了帧,但面板仅显示最后一帧。如果有任何建议,我将不胜感激:)
首先,证明它实际上可以以某种方式与您的代码一起工作。
在这里,我阅读了位于 resources
文件夹中的 JPG 图片,但实际上并不重要。
你的代码也有点乱。您将 btnStart
JButton
附加到外面板的什么位置?你也需要了解how to layout components。
您有一个主 JFrame
和一个需要布局的根 JPanel
。在这种情况下,我们可以选择 BorderLayout.
panel = new JPanel(new BorderLayout());
然后我们添加组件。
panel.add(btnStart, BorderLayout.PAGE_START);
panel.add(vidpanel1, BorderLayout.CENTER);
现在谈到你的问题,你说
The gui is created, frames are taken and processed, but panel display only the last frame
我不知道“最后一帧”部分的真实性,主要是因为您 运行 是 Event Dispatch Thread 内的无限阻塞循环,这将导致 GUI冻结并变得反应迟钝。
在 actionPerformed
中你实际上应该生成一个新的 Thread
,在 playVideo
中你应该包裹
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
vidpanel1.repaint(); // Remove this
在EventQueue.invokeAndWait
,如
// Process frame
...
// Update GUI
EventQueue.invokeAndWait(() -> {
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
});
我正在尝试编写一个应用程序来获取视频帧,对其进行处理,然后将它们作为图像显示在 JPanel
中。我使用OpenCV库获取视频帧(一帧一帧),然后处理后显示在屏幕上(达到播放视频的效果)。
我使用 Java Swing 创建了 GUI。创建了一个 window 应用程序,其中包含必要的按钮和一个显示视频的面板。单击“开始”后,将调用一个方法 playVideo
,该方法从所选视频中获取视频帧,对其进行修改并将其显示在面板中。我的代码如下所示:
public class HelloApp {
private JFrame frame;
private JPanel panel;
final JLabel vidpanel1;
ImageIcon image;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
HelloApp window = new HelloApp();
window.frame.setVisible(true);
}
});
}
public void playVideo() throws InterruptedException{
Mat inFrame = new Mat();
VideoCapture camera = new VideoCapture();
camera.open(Config.filename);
while (true) {
if (!camera.read(inFrame))
break;
Imgproc.resize(inFrame, inFrame, new Size(Config.FRAME_WIDTH, Config.FRAME_HEIGHT), 0., 0., Imgproc.INTER_LINEAR);
... processing frame
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame)); // option 0
vidpanel1.setIcon(image);
vidpanel1.repaint();
}
}
public HelloApp() {
frame = new JFrame("MULTIPLE-TARGET TRACKING");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);//new FlowLayout()
frame.setResizable(false);
frame.setBounds(50, 50, 800, 500);
frame.setLocation(
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().width,
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().height
);
frame.setVisible(true);
vidpanel1 = new JLabel();
panel = new JPanel();
panel.setBounds(11, 39, 593, 371);
panel.add(vidpanel1);
frame.getContentPane().add(panel);
JButton btnStart = new JButton("START / REPLAY");
btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
playVideo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
}
}
每次单击“开始”按钮时,我都尝试删除旧面板并创建一个新面板,但没有成功。我也在 运行 方法 playVideo
之前尝试使用以下方法清洁所有面板:
panel.removeAll();
panel.repaint();
playVideo();
老实说,我不知道出了什么问题。创建了 GUI,拍摄并处理了帧,但面板仅显示最后一帧。如果有任何建议,我将不胜感激:)
首先,证明它实际上可以以某种方式与您的代码一起工作。
在这里,我阅读了位于 resources
文件夹中的 JPG 图片,但实际上并不重要。
你的代码也有点乱。您将 btnStart
JButton
附加到外面板的什么位置?你也需要了解how to layout components。
您有一个主 JFrame
和一个需要布局的根 JPanel
。在这种情况下,我们可以选择 BorderLayout.
panel = new JPanel(new BorderLayout());
然后我们添加组件。
panel.add(btnStart, BorderLayout.PAGE_START);
panel.add(vidpanel1, BorderLayout.CENTER);
现在谈到你的问题,你说
The gui is created, frames are taken and processed, but panel display only the last frame
我不知道“最后一帧”部分的真实性,主要是因为您 运行 是 Event Dispatch Thread 内的无限阻塞循环,这将导致 GUI冻结并变得反应迟钝。
在 actionPerformed
中你实际上应该生成一个新的 Thread
,在 playVideo
中你应该包裹
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
vidpanel1.repaint(); // Remove this
在EventQueue.invokeAndWait
,如
// Process frame
...
// Update GUI
EventQueue.invokeAndWait(() -> {
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
});