Java 在main()外部实例化类时GUI无响应
我开始学习Java,我想使用OpenCV创建一个简单的摄像头提要查看器。 当从自己的main()方法实例化时,或者从调用方类的main()方法中进行调用时,MyCV类工作正常。 然后,我构建了一个“MyClient”类,其中包含一个main()方法和一个简单的GUI(实际上只有一个JFrame和一个JButton),因为我希望在MyClient GUI中按下按钮时显示MyCV GUI 问题是,当“调用者”类有自己的JFrame和关联的GUI元素时,我单击按钮,整个GUI冻结,MyCV类的框架显示为空,两个窗口都没有响应 我还尝试了使用Java 在main()外部实例化类时GUI无响应,java,swing,opencv,Java,Swing,Opencv,我开始学习Java,我想使用OpenCV创建一个简单的摄像头提要查看器。 当从自己的main()方法实例化时,或者从调用方类的main()方法中进行调用时,MyCV类工作正常。 然后,我构建了一个“MyClient”类,其中包含一个main()方法和一个简单的GUI(实际上只有一个JFrame和一个JButton),因为我希望在MyClient GUI中按下按钮时显示MyCV GUI 问题是,当“调用者”类有自己的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);
}
}
}
}
上面是一个无限循环,在事件分派线程(akaEDT
)上运行Swing
是单线程的-所有事件、绘画等…都发生在一个线程(EDT)上-如果该线程由于任何原因被束缚在工作中,那么它的任何其他责任都不会发生(换句话说,看起来您的用户界面被锁定)。main
方法在一个单独的线程上运行,因此您不会看到相同的行为(尽管对Swing组件的所有调用都应该放在EDT上,所以我不一定会用正确的方式调用它来绕过该行为)。三种选择:
//long running task inside a new Thread
new Thread(new Runnable(){
@Override
public void run(){
while(true){
}
}
});
上面是一个无限循环,在事件分派线程(akaEDT
)上运行Swing
是单线程的-所有事件、绘画等…都发生在一个线程(EDT)上-如果该线程由于任何原因被束缚在工作中,那么它的任何其他责任都不会发生(换句话说,看起来您的用户界面被锁定)。main
方法在一个单独的线程上运行,因此您不会看到相同的行为(尽管对Swing组件的所有调用都应该放在EDT上,所以我不一定会用正确的方式调用它来绕过该行为)。三种选择:
//long running task inside a new Thread
new Thread(new Runnable(){
@Override
public void run(){
while(true){
}
}
});
while(true){
这在EDT上运行一个无限循环。@copeg:我认为循环内容器面板的repaint()应该解决这个问题。此外,为什么只有在main()外调用MyCV时while循环才成问题?main
是一个与EDT不同的线程-因此它在EDT外运行该循环(因此你看不到这个问题)。但是ActionListener
代码是在EDT上运行的,就像SwingUtilities.invokeLater
-所以这两个都进入了这个循环,阻塞了EDT,而(true){
这在EDT上运行了一个无限循环。@copeg:我认为重新绘制()循环内容器面板的线程应该注意这一点。此外,为什么只有在main()外部调用MyCV时while循环才会出现问题?main
与EDT是不同的线程-因此它在EDT外部运行该循环(因此您没有看到此问题)但是,ActionListener
代码和SwingUtilities.invokeLater
-都是在EDT上运行的,所以这两个都落入了这个循环,阻塞了EDT。感谢您的清晰解释。它确实解决了我的问题。正如我所写的,我刚刚开始学习Java,还没有深入研究多线程。还有很多东西需要学习。谢谢您的帮助清楚的解释。它确实解决了我的问题。正如我所写的,我刚刚开始学习Java,还没有深入研究多线程。对我来说还有很多东西要学习。
//long running task inside a new Thread
new Thread(new Runnable(){
@Override
public void run(){
while(true){
}
}
});