Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从另一个方法中更新JFrame_Java_Swing - Fatal编程技术网

Java 从另一个方法中更新JFrame

Java 从另一个方法中更新JFrame,java,swing,Java,Swing,我有一个.csv文件,它是来自60000个手绘数字(手写数字的mnist数据集)的完整像素数据。按下按钮时调用名为train()的函数。在train()函数中,我希望60000位数字中的每一位都显示在屏幕上。代码运行得非常好,我只是无法从train()方法中更新JFrame 我测试了代码,它100%按预期工作。在train()函数中,我无法更新JFrame public void trainMenu(){ JButton trainBtn=新JButton(“列车”); JLabel otp=新

我有一个.csv文件,它是来自60000个手绘数字(手写数字的mnist数据集)的完整像素数据。按下按钮时调用名为train()的函数。在train()函数中,我希望60000位数字中的每一位都显示在屏幕上。代码运行得非常好,我只是无法从train()方法中更新JFrame

我测试了代码,它100%按预期工作。在train()函数中,我无法更新JFrame

public void trainMenu(){
JButton trainBtn=新JButton(“列车”);
JLabel otp=新的JLabel();
JPanel bottomBar=新的JPanel();
列车图像=新图像图标();
JLabel imageLabel=新的JLabel(此.trainImage);
底部栏。设置布局(新网格布局(1,2,5,5));
底部栏。添加(列车编号);
添加(otp);
this.frame.getContentPane().add(BorderLayout.CENTER,imageLabel);
this.frame.getContentPane().add(BorderLayout.SOUTH,bottomBar);
SwingUtilities.updateComponentTreeUI(this.frame);
ActionListener trainListener=新建ActionListener(){
已执行的公共无效操作(操作事件e){
如果(如getSource()==trainBtn){
火车();
}
}
};
trainBtn.addActionListener(trainListener);
}
无效列车(){
缓冲图像双图像;
//所有60000个数字都是从.csv文件中提取的
//我省略了这个函数的所有内容,因为它对这个问题不重要
...
//这行代码运行了60000次。它显示了转换后的像素数据(非常快)。代码肯定能正常工作,根本不会更新。
此.trainImage.setImage(双页面);
SwingUtilities.updateComponentTreeUI(框架);
}
}
}
公共静态void main(字符串[]args){
新NetGUI();
}
}

当我按下“train”(列车)按钮时,GUI将冻结且无响应,直到train()方法完成。

而不是更新
trainImage
,将新的
ImageIcon
设置为
JLabel

imageLabel.setIcon(new ImageIcon(bImage));
您可能还需要调用标签上的
revalidate
和/或
repaint
,以触发新的布局/绘制过程

就个人而言,我会从
train
方法返回
BufferedImage
,因为
train
方法实际上不应该更新UI,这不是它的工作

当我按下“train”按钮时,GUI将冻结,并且在train()方法完成之前没有响应

是的,这是因为Swing和大多数UI工具包一样,是单线程的。这意味着,如果在事件调度线程的上下文中执行任何阻塞或长时间运行的操作,将阻止它更新UI或响应任何用户输入

有关更多详细信息,请参阅

“一个”可能的解决方案是使用
SwingWorker
。这允许您在不同的线程上执行阻塞/长时间运行操作,但提供了多种方法将更新安全地同步回UI(Swing也不是线程安全的;)


有关更多详细信息,请参阅,您的GUI处于挂起状态,因为您正在Swing事件线程上执行大量图像操作。你有可能使用像SwingWorker这样的东西吗?通过这种方式,您可以在单独的线程上构建映像,并且仅在必要时更新GUI

private void train() {
    SwingWorker<BufferedImage, Object> worker = new SwingWorker<BufferedImage, Void>() {
        @Override
        protected BufferedImage doInBackground() throws Exception {
            // load the CSV file
            BufferedImage bImage = new BufferedImage();
            // ... fill up the bImage
            return bImage;
        }

        @Override
        protected void done() {
            try {
                BufferedImage img = get();
                // ... set the trainImage
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    };

    worker.execute();
}
private void train(){
SwingWorker worker=新SwingWorker(){
@凌驾
受保护的BuffereImage doInBackground()引发异常{
//加载CSV文件
BuffereImage双图像=新的BuffereImage();
//…填满这张照片
返回双图像;
}
@凌驾
受保护的void done(){
试一试{
BuffereImage img=get();
//…设置列车图像
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
}
};
worker.execute();
}

你的意思是说
这个.trainImage.setImage(bImage)
下面的行运行了60000次吗?您能否从文件中构建映像,然后
setImage
一次?