Надеюсь, я могу помочь объяснить, что здесь происходит.
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 для вашей оболочки, но я подозреваю, что это как-то связано с флагами стиля, которые вы передаете в конструктор оболочки.У оболочек в моем примере нет флагов стилей, и все они имеют значок на панели задач.