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