Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
227 views
in Technique[技术] by (71.8m points)

java - Trouble with displaying images in JPanel

I am trying to write an application that get video frames, process them and then display them in JPanel as images. I use the OpenCV library to get video frames (one by one), then they are processed and after that displayed on the screen (to get the effect of playing video).

I created the GUI using Java Swing. A window application is created with the necessary buttons and a panel to display the video. After clicking "START", a method playVideo is called, which takes video frames from the selected video, modifies them and displays them in the panel. My code looks like this:

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();
                        }
                    }
                });
            }
        });
    }
}

I tried to delete the old panel and create a new one every time when button "START" is clicked, but it didn't work. Also I tried before running method playVideo to clean all the panel with methods:

panel.removeAll();
panel.repaint();
playVideo();

And to be honest I don't know what's wrong. The GUI is created, frames are taken and processed, but the panel displays only the last frame. I would be grateful for any advice :)

question from:https://stackoverflow.com/questions/66062066/trouble-with-displaying-images-in-jpanel

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

First of all, a proof it can actually work, somehow, with your code.
Here I read JPG images located in the resources folder, but it actually doesn't really matter.

enter image description here

Your code is a bit messy too. Where are you attaching the btnStart JButton to the outer panel? You need to understand how to layout components too.

You have a main JFrame, and a root JPanel which needs a layout. In this case we can opt for a BorderLayout.

panel = new JPanel(new BorderLayout());

Then we add our components.

panel.add(btnStart, BorderLayout.PAGE_START);
panel.add(vidpanel1, BorderLayout.CENTER);

enter image description here

Now coming to your issue, you say

The gui is created, frames are taken and processed, but panel display only the last frame

I don't know how much the "last frame" part is true, mostly because you're running an infinite - blocking - loop inside the Event Dispatch Thread, which will cause the GUI to freeze and become unresponsive.

In actionPerformed you should actually spawn a new Thread, and inside playVideo you should wrap

ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
vidpanel1.repaint(); // Remove this

in EventQueue.invokeAndWait, such as

// Process frame
...

// Update GUI
EventQueue.invokeAndWait(() -> {
  ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
  vidpanel1.setIcon(image);
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...