Frage

I have an SWT application and I use canvas to show images, video, and PDF files. The user can drag any media type onto a canvas. I use a browser object for showing the PDF only. When I'm done showing the PDF, I just dispose the browser. Sometimes this works, but sometimes the browser doesn't go away, I get a zombie browser window stuck to my canvas.

Why do I get zombie browsers??

My canvas class has a draw method, something like this

        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
        }

so I only create the browser when I need it.

War es hilfreich?

Lösung

The problem is that new Browser(this, SWT.NONE) sometimes calls the canvas draw method. So if you create a new browser in draw, the draw method may get called multiple times, which in this situation will give you multiple browsers.

I added a Thread.dumpStack() to the start of draw and get this.

    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)

and you can see that the Browser.<init> invokes the canvas draw method.

The solution is to move the Browser construction elsewhere, and hide it using setVisible(false) instead of dispose.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top