Wx.html2, Unable to lower screen priority

My app requires me to place widgets on top of awx.html2 panel.

I’ve tried different panels and positioning options, to no avail. The wx.html2 panel is always the top most panel and any defined widgets are below it, regardless of setting Lower() or Raise().

I have verified that I can replace the wx.html2 widget with a wx.StaticText widget and as I expect can position widgets on top, so this appears to be an issue only with the html2 widget.

Is this a design feature or a defect?

Thanks for any suggestions/help.

As far as I remember, wxWidgets - and by extension wxPython - makes no guarantees nor promises when it comes to the z-order of overlapping widgets. I believe the behaviour is undefined.

It might be possible to make it work - I have no idea how as I haven’t ever done it myself. It may also turn out to be impossible to make it cross-platform.

Do you really need other widgets on top of a wx.html2 window? What type of widgets? Do you have a sketch of how your app should look like?

Here is what I want it to look like (this was implemented using PyQt6):

You’ll note that the app overlays the page’s header, while still allowing the user to select the html widgets on the displayed page. The app sets the hidden area by resizing a StaticText box’s height to remove just the unwanted section at the top of the web page.

Having tried to reproduce it in my prototype, however, I found that wx.html2 is unable to display the loop at all, which is very disappointing as I was hoping to take advantage of the smaller library with less restrictive licensing terms (even though I plan on offering the App for free.

The page that I was trying to display in my prototype (that fails to render at all) is: https://aviationweather.gov.gfa/#cigvis. In trying to debug why the page won’t display, it appears that there is a problem with the javascript that displays the loops.

Any thoughts would be appreciated.

Tom

I (somehow, not sure what I did to get the page to render) got the page to show correctly in my prototype, so here it is:

As you will note the AWC header is showing on the prototype, but not on the PyQt6 version.

well, Ithink there is always the possibility of having a frame stay on top of html2, but the positioning must be handmade (in contrast to those lovely sizers) :face_with_peeking_eye:

import wx
import wx.html2

class WebBrowser(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        wx.html2.WebView.New(self).LoadURL('https://docs.wxpython.org/')
        def evt_destroy(_):
            if parent.__nonzero__():
                parent.Destroy()
        self.Bind(wx.EVT_WINDOW_DESTROY, evt_destroy)
        self.Show()

class Gui(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent, title='Browser with overlay',
                    style=wx.DEFAULT_FRAME_STYLE|wx.STAY_ON_TOP)
        WebBrowser(self)
        self.Show()

app = wx.App()
Gui(None)
app.MainLoop()

Unfortunately, this opens a new window with the browser in it, not underlying the GUI frame, as I wanted. I had tried this option earlier and got the windows to always be synchronized (one directly on top of the other) moving both when the top window moved. But I ran into problems resizing the top window when the bottom window was resized using the lower right corner.

well, once you know what you want (I don’t really) it should be achievable (at least in wxPython) :joy:

import wx
import wx.html2

class WebBrowser(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.wv = wx.html2.WebView.New(self)
        self.wv.LoadURL('https://docs.wxpython.org/')
        self.height = None
        self.position = self.GetPosition()
        self.size = self.GetSize()
        self.max = False
        def evt_size(evt):
            s = evt.GetSize()
            h = self.height if self.height else s[1]
            parent.SetPosition(self.GetPosition())
            parent.SetSize(s[0], h)
            evt.Skip()
        self.Bind(wx.EVT_SIZE, evt_size)
        self.Show()

    def set_width(self, width):
        self.SetSize(width, self.GetSize()[1])

    def set_max(self, gui):
        if self.max:
            self.SetPosition(self.position)
            if self.size[1] < 40:
                self.size[1] = int(gui.GetSize()[1] + 40)
            elif not gui.GetSize()[1] < self.size[1] - 20:
                gui.SetSize((self.size[0], int(self.size[1] / 2)))
            self.SetSize(self.size)
            self.SetFocus()
            self.max = False
        else:
            self.position = self.GetPosition()
            self.size = self.GetSize()
            self.SetPosition((0, 0))
            self.SetSize(wx.DisplaySize())
            self.max = True

class Gui(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent, title='Html2 with overlay',
                    style=wx.DEFAULT_FRAME_STYLE
                    & ~(wx.MAXIMIZE_BOX) | wx.STAY_ON_TOP)
        wb = WebBrowser(self)
        pnl = wx.Panel(self)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        pnl.SetSizer(hbox)
        btn = wx.Button(pnl, label='Maxi / Restore')
        hbox.Add(btn, 0, wx.ALL, 10)
        btn.Bind(wx.EVT_BUTTON, lambda _: wb.set_max(self))
        btn = wx.Button(pnl, label='load http://www.google.com')
        hbox.Add(btn, 0, wx.ALL, 10)
        btn.Bind(wx.EVT_BUTTON, lambda _:
                        wb.wv.LoadURL('http://www.google.com'))
        btn = wx.Button(pnl, label='load https://aviationweather.gov/gfa/#obs')
        hbox.Add(btn, 0, wx.ALL, 10)
        btn.Bind(wx.EVT_BUTTON, lambda _:
                        wb.wv.LoadURL('https://aviationweather.gov/gfa/#obs'))
        pnl.Bind(wx.EVT_ENTER_WINDOW, lambda _: wb.SetFocus())
        def evt_size(evt):
            s = evt.GetSize()
            wb.height = s[1]
            wb.set_width(s[0])
            evt.Skip()
        self.Bind(wx.EVT_SIZE, evt_size)
        def evt_move(evt):
            wb.SetPosition(self.GetPosition())
            evt.Skip()
        self.Bind(wx.EVT_MOVE, evt_move)
        s = self.GetSize()
        s.SetHeight(int(s[1] / 2))
        self.SetSize(s)
        self.SetBackgroundColour('cyan')
        self.SetTransparent(200)
        self.Show()

app = wx.App()
Gui(None)
app.MainLoop()