如何使用 SwingWorker 从 no-gui 类更新 Java Jframe 控件



我已经问过这个问题,但需要更多详细信息。

如何实时从 no-gui 类更新 Java Jframe 控件

提出的答案无法测试,因为当 Windows 应用程序启动时,它看起来像大小 0,0,而当我最大化时,没有绘制任何控件。

无论如何,这是我最初的问题:

我想做的(并寻找方法(是将元素添加到我的 实时从无 GUI 类ListBox,换句话说 "异步",而不会冻结我的应用程序。这清楚吗?我试过了SwingWorker和线程,但没有结果。我所能做的就是更新 所有进程完成后的列表框(显然我的应用程序冻结了 因为我的过程很长(。

这是我的架构:

  • 项目
  • __控制器
  • __商
  • __Util
  • __视图

这是我的代码(尝试重现提出的解决方案(

视图(使用 NetBeans 生成(

package view;
import MyController;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
public class MyView extends javax.swing.JFrame {
static MyController controller;
public MyView(DefaultListModel<String> model) {
initComponents();
pack();
setVisible(true);
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {
btnRun = new javax.swing.JButton();
jscrlLog = new javax.swing.JScrollPane();
jlstLog = new javax.swing.JList();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
btnRun.setText("Run");
btnRun.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRunActionPerformed(evt);
}
});
jscrlLog.setViewportView(jlstLog);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(159, 159, 159)
.addComponent(btnRun)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jscrlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(btnRun)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jscrlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 242, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>                        
private void btnRunActionPerformed(java.awt.event.ActionEvent evt) {                                       
controller.runProcess();
}                                      
public void addButtonListener(ActionListener listener) {
btnRun.addActionListener(listener);
}
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
controller = new MyController();
}
});

}
// Variables declaration - do not modify                     
private javax.swing.JButton btnRun;
private javax.swing.JList jlstLog;
private javax.swing.JScrollPane jscrlLog;
// End of variables declaration                   
}

package business;
import MyLog;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.SwingWorker;
public class MyBusiness {
private int counter = 0;
private DefaultListModel<String> model;
private MyLog log;
public MyBusiness(DefaultListModel<String> model) {
this.model = model;a
}
public void runProcess() {
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < 10; i++) {
publish("log message number " + counter++);
Thread.sleep(2000);
}
return null;
}
@Override
protected void process(List<String> chunks) {
// this is called on the Swing event thread
for (String text : chunks) {
model.addElement("");
}
}
};
worker.execute();
}
}

日志(模型(

package util;
import javax.swing.DefaultListModel;
public class MyLog {
private DefaultListModel<String> model;
public MyLog() {
model = new DefaultListModel<String>();
}
public DefaultListModel<String> getLog(){
return model;
}
}

当Windows应用程序启动时,它看起来像大小为0,0,当我最大化时,没有绘制任何控件。

public MyView(DefaultListModel<String> model) {
setVisible(true);
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

我所看到的只是你使框架可见。我看不出你在哪里向框架添加组件。这就是你曾经调用过 initComponents(( 的地方?

在使框架可见之前,需要将组件添加到框架中。并且您需要在帧可见之前对其进行 pack((。

有两个主要问题阻止日志出现在JList中:

A. 从不使用模型。也使用它添加一个model字段:

private DefaultListModel<String> model;
public MyView(DefaultListModel<String> model) {
this.model = model;
initComponents();
}

并将模型分配给JList

//change  jlstLog = new JList<>();  to  
jlstLog = new JList<>(model); 

B. 此方法

public void runProcess() {
view.addButtonListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
business.runProcess();
}}
);
}

永远不会调用,因此按钮没有操作侦听器。
可以在此处查看清除此问题的完整代码。

关于询问
的一些补充评论最初的问题得到了回答。 我认为,在回答问题后更改问题不是好做法。
它使问题的答案变得无关紧要,并且投入其中的工作对未来的读者没有帮助。 请坚持"每个帖子一个问题"的政策。
在对和上一个问题的评论中也多次强调了 mcve 的重要性。MCVE 应该演示问题而不是您的应用程序。

最新更新