我开始学习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);
}
}
答案 0 :(得分:3)
while(true){
以上是在Event Dispatch Thread(aka EDT
)上运行的无限循环。 Swing
是单线程的 - 所有事件,绘画等等都发生在一个线程(EDT)上 - 如果该线程由于任何原因被捆绑起来工作,则不会发生其他任何职责(换句话说) ,看起来你的用户界面锁定了)。 main
方法在一个单独的Thread上运行,所以你看不到相同的行为(虽然所有对Swing组件的调用都应放在EDT上,所以我不一定称之为正确的方法来绕过这个行为) 。三个选项:
1的例子:
//long running task inside a new Thread
new Thread(new Runnable(){
@Override
public void run(){
while(true){
}
}
});