У меня есть приложение SWT, и я использую canvas для отображения изображений, видео и файлов PDF. Пользователь может перетаскивать любой тип носителя на холст. Я использую объект браузера для показа только PDF. Когда я закончил показывать PDF, я просто распоряжаюсь браузером. Иногда это работает, но иногда браузер не уходит, я получаю окно браузера зомби, прикрепленное к моему холсту.
Почему я получаю зомби-браузеры?
Мой класс холста имеет метод рисования, что-то вроде этого
public void draw(GC gc) {
if (mediaType == PDF) {
if (browser == null)
browser = new Browser(this, SWT.NONE);
}
else if (browser != null) {
browser.dispose();
browser = null;
}
// etc, etc
}
поэтому я только создаю браузер, когда мне это нужно.
Проблема в том, что новый браузер (этот, SWT.NONE) иногда вызывает метод рисования холста. Поэтому, если вы создаете новый браузер в режиме рисования, метод draw может вызываться несколько раз, что в этой ситуации даст вам несколько браузеров.
Я добавил Thread.dumpStack() в начало розыгрыша и получаю это.
java.lang.Throwable
at java.lang.Thread.dumpStack(Thread.java:417)
at com.acme.client.widget.canvas.AcmeImageCanvas.draw(AcmeImageCanvas.java:1923)
at com.acme.client.widget.canvas.AcmeImageCanvas.paintControl(AcmeImageCanvas.java:1888)
at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Composite.WM_PAINT(Unknown Source)
at org.eclipse.swt.widgets.Control.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Canvas.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
at org.eclipse.swt.internal.ole.win32.COM.VtblCall(Native Method)
at org.eclipse.swt.internal.ole.win32.IDispatch.Invoke(Unknown Source)
at org.eclipse.swt.ole.win32.OleAutomation.invoke(Unknown Source)
at org.eclipse.swt.ole.win32.OleAutomation.setProperty(Unknown Source)
at org.eclipse.swt.browser.IE.create(Unknown Source)
at org.eclipse.swt.browser.Browser.<init>(Unknown Source)
at com.acme.client.widget.canvas.AcmeImageCanvas.draw(AcmeImageCanvas.java:1923)
at com.acme.client.widget.canvas.AcmeImageCanvas.retrieveImage(AcmeImageCanvas.java:4679)
at com.acme.client.widget.canvas.AcmeThumbnailCanvas.mouseUp(AcmeThumbnailCanvas.java:1761)
at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Unknown Source)
at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
at com.acme.client.uiframework.AcmeApp.main(AcmeApp.java:1674)
и вы можете видеть, что браузер. <init> вызывает метод рисования холста.
Решение состоит в том, чтобы переместить конструкцию браузера в другое место и скрыть ее с помощью setVisible (false) вместо dispose.