Как избавиться от снарядов SWT (и диалогов)? - PullRequest
3 голосов
/ 22 декабря 2011

Как правильно утилизировать снаряды SWT?Я создал несколько диалогов с успехом, следуя шаблону, приведенному в документации по Dialog API. SWT API для диалога говорит :

Базовый шаблон для пользовательского диалога обычно выглядит примерно так:

 public class MyDialog extends Dialog {
        Object result;

        public MyDialog (Shell parent, int style) {
                super (parent, style);
        }
        public MyDialog (Shell parent) {
                this (parent, 0); // your default style bits go here (not the Shell's style bits)
        }
        public Object open () {
                Shell parent = getParent();
                Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
                shell.setText(getText());
                // Your code goes here (widget creation, set result, etc).
                shell.open();
                Display display = parent.getDisplay();
                while (!shell.isDisposed()) {
                        if (!display.readAndDispatch()) display.sleep();
                }
                return result;
        }
 }

Диалоги, которые я создал , не не имеют своего собственного значка панели задач в Windows, как я ожидал бы для Диалога.Теперь я хочу создать несколько оболочек, которые, если я правильно понимаю, получат ли собственную запись панели задач в Windows?

В отличие от указаний, приведенных в приведенных выше документах API, я также видел статья , которая, кажется, предполагает, что использование цикла while, как показано в документации API, является неправильным способом сделать это.Вместо этого в статье предлагается утилизировать оболочку с помощью прослушивателя событий закрытия.

Как правильно утилизировать оболочки SWT (и, хотя это тоже было в теме «Диалоги»)?

1 Ответ

10 голосов
/ 22 декабря 2011

Надеюсь, я могу помочь объяснить, что здесь происходит.

Dialog - это просто удобный класс для подкласса, потому что сам Shell не должен быть подклассом.Вы можете создавать оболочки без использования Dialog, если хотите.В этом случае ваш MyDialog класс - это класс, который другие могут использовать для многократного открытия одного и того же типа диалога.

Этот фрагмент кода управляет циклом событий SWT, пока открыта оболочка (щелкнув покнопка закрытия на оболочке удаляет оболочку по умолчанию):

            while (!shell.isDisposed()) {
                    if (!display.readAndDispatch()) display.sleep();
            }

Вам необходимо периодически вызывать Display.readAndDispatch, чтобы приложение SWT не блокировалось.В основном это приводит к тому, что все входящие события из операционной системы (события клавиатуры и мыши, события перерисовки и т. Д.) Корректно обрабатываются вашим приложением.readAndDispatch в основном берет событие из очереди событий приложения и вызывает правильных слушателей.В приложении Eclipse RCP рабочая среда обычно отвечает за «прокачку» цикла событий, и вам не нужно с ним связываться. Вот немного больше информации о цикле событий.

Цель "ручной" накачки цикла событий в этом контексте состоит в том, чтобы предотвратить возврат MyDialog.open, пока оболочка не расположена,но все равно держите приложение от "зависания".Если ваш метод MyDialog.open попытался дождаться утилизации оболочки, но он не прокачал цикл событий, ваше приложение «заблокировалось бы», потому что без запуска цикла событий нет возможности для уведомления оболочки когда-либочто он должен быть утилизирован!

Вы можете создавать оболочки без использования этого шаблона.Вот пример очень простого SWT-приложения, которое одновременно открывает тонну оболочек и продолжает работать до тех пор, пока хотя бы одна из них все еще открыта (я пропустил объявление пакета и импортировал):

public class Shells {
    private static int numDisposals = 0;

    public static void main(String[] args) {
        Display d = Display.getDefault();

        for (int i = 0; i < 5; i++) {
            Shell s = new Shell(d);
            s.open();
            s.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(DisposeEvent arg0) {
                    numDisposals++;
                }
            });
        }

        while (numDisposals < 5) {
            while (!d.readAndDispatch()) {
                d.sleep();
            }
        }
    }
}

Обратите внимание, что я добавляю DisposeListener к каждой оболочке, чтобы я мог предпринять некоторые действия, когда оболочка закрыта.Вы также можете использовать IShellListener для более непосредственного прослушивания события close и даже для его фактического предотвращения (что может потребоваться, например, если оболочка содержит несохраненную работу).Вот раздражающая модификация первой программы, которая запускает 5 оболочек и случайным образом не позволяет вам закрыть их:

public class Shells {
    private static Random r = new Random();
    private static int numDisposals = 0;

    public static void main(String[] args) {
        Display d = Display.getDefault();

        for (int i = 0; i < 5; i++) {
            Shell s = new Shell(d);
            s.open();
            s.addShellListener(new ShellAdapter() {
                @Override
                public void shellClosed(ShellEvent e) {
                    boolean close = r.nextBoolean();
                    if (close) {
                        System.out.println("Alright, shell closing.");
                    } else {
                        System.out.println("Try again.");
                    }
                    e.doit = close;
                }
            });
            s.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(DisposeEvent arg0) {
                    numDisposals++;
                }
            });
        }

        while (numDisposals < 5) {
            while (!d.readAndDispatch()) {
                d.sleep();
            }
        }
    }
}

Надеюсь, это помогло прояснить ситуацию!


Отредактировано, чтобы добавить: я не совсем уверен, почему вы не получаете элемент панели задач Windows для вашей оболочки, но я подозреваю, что это как-то связано с флагами стиля, которые вы передаете в конструктор оболочки.У оболочек в моем примере нет флагов стилей, и все они имеют значок на панели задач.

...