类在main()外部实例化时没有响应的GUI

时间:2016-09-19 16:02:37

标签: java swing opencv

我开始学习Java,我想用OpenCV创建一个简单的摄像头视图。 从自己的main()方法实例化时,或者在调用者类的main()方法中调用时,MyCV类工作得很好。 然后我建立了一个" MyClient" class,有一个main()方法和一个简单的GUI(实际上只是一个JFrame和一个JButton),因为我想在MyClient GUI中按下按钮时显示MyCV GUI。

问题是,当"来电者" class有自己的JFrame和相关的GUI元素,我点击按钮,整个GUI冻结,MyCV类的框架显示为空,两个窗口都没有响应。

我也用SwingUtilities.invokeLater()尝试了这个课程,但没有用。

正如我所说,我是Java / Swing的新手,它看起来像paintComponent()问题,但对于我的生活,我无法修复它。

非常感谢任何帮助

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;


public class MyCV {
    public static void main(String args[]){
        MyCV cv=new MyCV();
    }

    public MyCV(){
        System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
        //-- Video capture structure
        VideoCapture feed=new VideoCapture(0);
        //-- Mat structures
        Mat imgFeed1=new Mat();
        Mat imgFeed2=new Mat();
        Mat imgFeed3=new Mat();
        Mat imgFeed4=new Mat();

        imgPanel feedPanel1=new imgPanel(); feedPanel1.setPreferredSize(new Dimension(400,400));
        imgPanel feedPanel2=new imgPanel(); feedPanel2.setPreferredSize(new Dimension(400,400));
        imgPanel feedPanel3=new imgPanel(); feedPanel3.setPreferredSize(new Dimension(400,400));
        imgPanel feedPanel4=new imgPanel(); feedPanel4.setPreferredSize(new Dimension(400,400));
        JPanel container=new JPanel(); container.setPreferredSize(new Dimension(800,800)); 
        container.add(feedPanel1);
        container.add(feedPanel2);
        container.add(feedPanel3);
        container.add(feedPanel4);

        JFrame f=new JFrame("MyChild");
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.add(container);
        f.setSize(1300, 800);
        f.setVisible(true);

        //-- clear resources on exit
        f.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                feed.release();
                f.dispose();
            }
        });

        //-- main loop
        while(true){
             if(!feed.isOpened()) break;
             feed.read(imgFeed1);           
             if(imgFeed1.size().width==0) break;

             //-- display images in panels (Colors +Feed +Norm)
             feedPanel1.setimagewithMat(imgFeed1);
             feedPanel2.setimagewithMat(imgFeed1);
             feedPanel3.setimagewithMat(imgFeed1);
             feedPanel4.setimagewithMat(imgFeed1);

             // repaint frame
             container.repaint();
        }

    }


    class imgPanel extends JPanel{
        private static final long serialVersionUID=1L;
        private BufferedImage image;
        //public imgPanel(){ super(); }
        private BufferedImage getimage(){ return image; }
        public void setimage(BufferedImage newimage){image=newimage; return; }
        //-- called method
        public void setimagewithMat(Mat newimage){
            image=matToBufferedImage(newimage); 
            return; 
        }       
        //--
        //--
        public BufferedImage matToBufferedImage(Mat matrix) {  
             int cols = matrix.cols();  
             int rows = matrix.rows();  
             int elemSize = (int)matrix.elemSize();  
             byte[] data = new byte[cols * rows * elemSize];  
             int type;  
             matrix.get(0, 0, data);  
             switch (matrix.channels()) {  
               case 1:  
                 type = BufferedImage.TYPE_BYTE_GRAY;  
                 break;  
               case 3:  
                 type = BufferedImage.TYPE_3BYTE_BGR;  
                 // bgr to rgb  
                 byte b;  
                 for(int i=0; i<data.length; i=i+3) {  
                   b = data[i];  
                   data[i] = data[i+2];  
                   data[i+2] = b;  
                 }  
                 break;  
               default:  
                 return null;  
             }  
             BufferedImage image2 = new BufferedImage(cols, rows, type);  
             image2.getRaster().setDataElements(0, 0, cols, rows, data);
             return image2;  
           }

        @Override
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            BufferedImage temp=getimage();
            if(temp!=null){
                g.drawImage(temp,  0,  0,  temp.getWidth(), temp.getHeight(), this);
            }
        }
    }
}

MyClient.java:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyClient {
    public static void main(String args[]){
        //MyCV cv=new MyCV();
        //MyClient cli=new MyClient();
        JFrame f=new JFrame("My Client");
        f.setSize(300, 300);
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);

        JButton button=new JButton("call Color Detector");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                MyCV cv=new MyCV();
            }
        });

        f.add(button);

    }

    public MyClient(){
        JFrame f=new JFrame("My Client");
        f.setSize(300, 300);
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setVisible(true);

        JButton button=new JButton("call Color Detector");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                MyCV cv=new MyCV();
            }
        });

        f.add(button);

    }
}

1 个答案:

答案 0 :(得分:3)

while(true){

以上是在Event Dispatch Thread(aka EDT)上运行的无限循环。 Swing是单线程的 - 所有事件,绘画等等都发生在一个线程(EDT)上 - 如果该线程由于任何原因被捆绑起来工作,则不会发生其他任何职责(换句话说) ,看起来你的用户界面锁定了)。 main方法在一个单独的Thread上运行,所以你看不到相同的行为(虽然所有对Swing组件的调用都应放在EDT上,所以我不一定称之为正确的方法来绕过这个行为) 。三个选项:

  1. 启动一个或多个新线程并在该线程中放置任何长时间运行的任务(请注意,任何对Swing组件的调用都应使用SwingUtilities放置在EDT上)
  2. 使用SwingWorker
  3. 如果您希望定期执行某些操作,例如动画,则可以使用java.swing.Timer
  4. 1的例子:

    //long running task inside a new Thread
    new Thread(new Runnable(){
    
        @Override
        public void run(){
            while(true){
    
            }
        }
    
    });