这是不良的编程实践吗?

3
请看下面的代码:

请考虑以下代码:

public class MyClass extends javax.swing.JFrame {

    private JTree jTree;
    //Code ommited for clarity

    public void methodCalledByAnotherThread(){

       final DefaultTreeModel t = new DefaultTreeModel();
       //Do some thing with t

       SwingUtilities.invokeLater(new Runnable(){
            public void Run(){
               jTree.setModel(t);
            }
       });
   }
}

MyClass 在Swing线程上创建并执行。在其执行过程中,会启动第二个线程,该线程最终将调用 methodCalledByAnotherThread() 方法。请注意,该方法永远不会在Swing线程上被调用。

methodCalledByAnotherThread() 创建一个(本地)DefaultTreeModel 对象,并对其进行一些操作,但由于此操作不在Swing线程上,因此无法将模型设置到 jTree 中,因此需要调用 SwingUtilities.invokeLater()。在可运行对象中,在Swing线程上执行的情况下,将局部 DefaultTreeModel t 设置到 JTree 中。

我的问题是(实际上我还没有编译和运行这段代码,所以可能不起作用):上述是否是不良编程实践?如果是,那么如何将在非Swing线程上创建的 TreeModel 设置到Swing对象中?

2个回答

3

看起来不错(事实上这是最佳方案)。只要//Do some thing with t 不包含任何已经在UI中显示的元素。


谢谢您的快速回复。您有没有任何参考资料可以证明这是正确的处理方式? - D-Dᴙum
我发现在这个发布的问题中:http://stackoverflow.com/questions/5895481/update-jlabel-from-another-thread - John Vint

3

1)不要在组合与继承中再扩展javax.swing.JFrame

2)更好的方法是从当前JTree实例中获取getModel,而不是在运行时重新创建DefaultTreeModel,也许还有未知的生命周期。

3)正确的方式是通过将model包装到invokeLater中添加,建议最简单的方式是使用Runnable#Thread,最好使用SwingWorker


关于您的#2 TreeModel,据我所知,它不是线程安全的。因此,应该考虑将其从另一个线程修改为不良编程实践。 - Oleg Mikheev
@ʘleg你的“考虑糟糕的编程实践”可能是从后台任务添加/更新DefaultXxxModel到Swing GUI的默认方式。 - mKorbel
修改非线程安全对象的方式不是我的问题 :) - Oleg Mikheev
我认为当前JTree的_.getModel_方法不会返回一个AbstractXxxModel... - Oleg Mikheev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接