Каков рекомендуемый способ для представлений SWT (ViewPart), которые получают внешнее событие для обновления элемента GUI? - PullRequest
2 голосов
/ 12 февраля 2010

Мое представление является производным от ViewPart, но у меня есть прослушиватель, который получает события из потоков, не относящихся к GUI.

Если что-то должно происходить в потоке GUI, оно должно пройти через asyncExec().

Пока все хорошо.

Дело в том, что GUIэлементы создаются в createPartControl(), поэтому они не могут быть окончательными.На данный момент я просто поместил их в AtomicReference, что может быть просто отлично.

Какой у вас подход?

Обновить

допроясните проблему, используя пример из одного из ответов ниже:

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
            }
        });
    }
}

Ответы [ 2 ]

2 голосов
/ 16 февраля 2010

Вы просто получаете доступ к 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 прозрачно передает ссылку на внешний класс (ы) во внутренний класс. Это позволяет вам получить доступ к любому из полей во внешнем классе изнутри внутреннего класса. Поскольку внутренний класс содержит ссылку на внешний класс, внешний класс не сможет собрать мусор или выйти из области видимости раньше, чем внутренний класс. Вот почему вам не нужно делать текст1 окончательным. Он всегда будет доступен для использования внутренними классами.

Когда вы объявляете переменную внутри метода, это другая история. Анонимный внутренний класс, объявленный в createPartControl (), вероятно, превзойдет область действия метода. Возможно, нет, но Java не рискует. Когда метод выходит из области видимости, ссылка на text2 будет потеряна, и внутреннему классу не повезет. Чтобы исправить эту Java, необходимо использовать модификатор final в text2. Что в итоге делает то, что гарантирует, что переменная всегда будет указывать на один и тот же объект в памяти. Поскольку в Java теперь есть гарантия того, что этот объект будет в памяти, он может перейти в это место во внутренний класс. Для практических целей создается впечатление, что создается внутренняя класс новой переменной с именем text1 типа Text, что позволяет вам обращаться к ней еще долго после того, как метод выходит из области видимости.

В вашем случае вы бы просто сделали все компоненты пользовательского интерфейса, к которым необходимо получить доступ изнутри Переменные экземпляра someNetworkMessageReceived () так же, как text1.

Надеюсь, это прояснит вашу путаницу с последним модификатором.

0 голосов
/ 13 февраля 2010

Обычно я использую задания Eclipse, когда хочу выполнить что-то в потоке, не являющемся графическим интерфейсом, и тогда все, что мне нужно сделать, это поместить отображение в конструктор, а затем обратиться к конечной переменной-члену из метода run.

...