java - 对于接收外部事件以更新 GUI 元素的 SWT View (ViewPart),推荐的方法是什么?

标签 java eclipse multithreading user-interface swt

我的 View 派生自 ViewPart,但我有一个监听器,它从非 GUI 线程接收事件。

如果应该在 GUI 线程中发生某些事情,它必须通过 asyncExec()

到目前为止一切顺利。

事实是,GUI 元素是在 createPartControl() 中创建的,因此它们不可能是最终的。目前我只是将它们放在 AtomicReference 中,它可以是 final 就好了。

你的方法是什么?

更新

使用以下答案之一的示例来阐明问题:

public class MyView extends ViewPart implements SomeNetWorkActionListener {

    private Text text1;

    private final AtomicReference<Text> text3 = new AtomicReference<Text>();

    public void createPartControl(Composite parent) {
        text1 = new Text(parent, SWT.None);
        final Text text2 = new Text(parent, SWT.None);
        text3.set(new Text(parent, SWT.None));

        parent.getDisplay().asyncExec(new Runnable() {
            public void run() {
                text1.setText("Hello");
                text2.setText("World");
            }
        });
    }

    public void setFocus() {
        text1.forceFocus();
    }

    @Override
    public void someNetworkMessageReceived(MyMessage message) {
        getSite ().getShell ().getDisplay().asyncExec(new Runnable() {
            public void run() {
                //... how to reference text 1 or text 2?
                text3.get().setText(message.toString()); // this is what I do at the moment
            }
        });
    }
}

最佳答案

您只需访问 text1。它不需要包装,也不需要是最终的。

有两个放置变量的基本位置:在类级别(这里它们不能是最终的,因为它们不在构造函数中),或者在一个方法中,无论方法是什么,它们都可以声明为最终的叫做。这是使用变量的两种方式的示例:

public class MyView extends ViewPart {
    private Text text1;

    public void createPartControl(Composite parent) {
        text1 = new Text(parent, SWT.None);
        final Text text2 = new Text(parent, SWT.None);

        parent.getDisplay().asyncExec(new Runnable() {
            public void run() {
                text1.setText("Hello");
                text2.setText("World");
            }
        });
    }

    public void setFocus() {
        text1.forceFocus();
    }

    public void someNetworkMessageReceived(MyMessage message) {
        getSite().getShell().getDisplay().asyncExec(new Runnable() {
            public void run() {
                text1.setText(message.toString());
            }
        });
    }
}

匿名内部类的行为与所有其他内部类一样。当您实例化一个内部类时,java 透明地将对外部类的引用传递给内部类。这允许您从内部类中访问外部类中的任何字段。由于内部类持有对外部类的引用,因此外部类无法在内部类之前进行垃圾收集或超出范围。这就是为什么您不需要将 text1 设置为 final 的原因。它将始终可供内部类使用。

当您在方法中声明变量时,情况就不同了。在 createPartControl() 中声明的匿名内部类可能会比方法的范围更持久。可能不会,但 Java 不会冒任何风险。当方法超出范围时,对 text2 的引用将丢失,内部类将不走运。要解决此问题,Java 需要您对 text2 使用 final 修饰符。 final 所做的是它保证变量将始终指向内存中的同一个对象。由于 Java 现在可以保证该对象在内存中的位置,因此它可以将该位置传递给内部类。出于所有实际目的,它就像在内部类中创建一个名为 text1 的 Text 类型的新变量,从而让您可以在方法超出范围后很长时间内访问它。

在您的情况下,您只需制作需要从内部访问的所有 UI 组件 someNetworkMessageReceived() 实例变量就像 text1 一样。

希望这能消除您对最终修饰符的困惑。

关于java - 对于接收外部事件以更新 GUI 元素的 SWT View (ViewPart),推荐的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2254333/

相关文章:

c - 第一个线程信号未被捕获,所有其他线程信号被捕获

java - 组织.postgresql.util.PSQLException : No value specified for parameter 1

java.io.FileNotFoundException : localhost/broadcast_1

java - 单参数方法命名: repeat paramter in method name

eclipse - 通过Eclipse插件以编程方式更改菜单项

java - 是否可以在线程可运行的声明中将文件写入交互式 shell?

java - Google App Engine for Java session 究竟是如何工作的?

android - 对于 Eclipse 和 Android,IDE 从不显示异常值

C++ STM32用户定义类构造函数问题

objective-c - 如何跨线程跟踪NSError对象?