Create checked checkbox in wx.html.HtmlWindow

As I understand, wx.html.HtmlWindow does not support the standard <input type="checkbox"> tag, and the way to add checkboxes is something like this:

import wx
import wx.html as html
import wx.lib.wxpTag

class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(500, 500))
        
        self.control = html.HtmlWindow(self, size=(500, 500))
        self.windowSizer = wx.BoxSizer()
        self.windowSizer.Add(self.control, 1, wx.ALL|wx.EXPAND)

        content = r'''<html><head></head><body>
        Some text first<br>
        <wxp module="wx" class="CheckBox">
            <param name="id" value="1">
            <param name="name" value="MyName">
            <param name="label" value="MyLabel">
        </wxp><br>
        <wxp module="wx" class="CheckBox"><param name="id" value="2"></wxp><br>
        <wxp module="wx" class="CheckBox"><param name="id" value="3"></wxp><br>
        </body></html>
        '''
        self.control.SetPage(content)
        
        self.SetSizerAndFit(self.windowSizer)
        self.control.Bind(wx.EVT_CHECKBOX, self.OnCheck)

    def OnCheck(self, evt):
        print(f"{evt.Id} checked: {evt.IsChecked()}")

if __name__ == '__main__':
    app = wx.App()
    frame = MainWindow(None, -1, "Window")
    frame.Show(1)
    app.MainLoop()

How do I create a box that is already checked (or check it programmatically immediately after it is created)? The parameters used in <param name...> seem to be from the CheckBox’s __init__ function, and there’s no parameter to create it already checked. I’ve tried getting the control through wx.window.FindWindowByName/Label/Id to call SetValue on it, but to no avail.

The html2.WebView control does support the standard <input type="checkbox"> tag.

I copied a simple HTML example from w3schools and pasted it into a file. I then modified the first checkbox so that it was checked:

<!DOCTYPE html>
<html>
<body>

<h1>Show Checkboxes</h1>

<form action="/action_page.php">
  <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike" checked="checked">
  <label for="vehicle1"> I have a bike</label><br>
  <input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
  <label for="vehicle2"> I have a car</label><br>
  <input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
  <label for="vehicle3"> I have a boat</label><br><br>
  <input type="submit" value="Submit">
</form>

</body>
</html>

I then ran the following script that was created by Cody Precord:

# Module: html2_browser.py
# Author: Cody Precord

import wx
import wx.html2 as html2

class NaviBar(wx.Panel):
    def __init__(self, parent, browser):
        super(NaviBar, self).__init__(parent)

        self._url = wx.TextCtrl(self,
                                style=wx.TE_PROCESS_ENTER)
        self._url.SetHint("Enter URL here and press enter...")

        back = wx.Button(self, style=wx.BU_EXACTFIT)
        back.Bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_BACK,
                                               wx.ART_TOOLBAR)
        fw = wx.Button(self, style=wx.BU_EXACTFIT)
        fw.Bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD,
                                             wx.ART_TOOLBAR)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(back, 0, wx.ALL, 5)
        sizer.Add(fw, 0, wx.ALL, 5)
        sizer.Add(self._url, 1, wx.EXPAND)
        self.SetSizer(sizer)

        b = browser
        self.Bind(wx.EVT_TEXT_ENTER,
                  lambda event: b.LoadURL(self._url.Value))
        self.Bind(wx.EVT_BUTTON, lambda event: b.GoBack(), back)
        self.Bind(wx.EVT_BUTTON, lambda event: b.GoForward(), fw)
        self.Bind(wx.EVT_UPDATE_UI,
                  lambda event: event.Enable(b.CanGoBack()),
                  back)
        self.Bind(wx.EVT_UPDATE_UI,
                  lambda event: event.Enable(b.CanGoForward()),
                  fw)

class WebFrame(wx.Frame):
    def __init__(self, parent, title):
        super(WebFrame, self).__init__(parent, title=title)
        self.SetSize((800, 400))
        self._browser = html2.WebView.New(self)
        self._bar = NaviBar(self, self._browser)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self._bar, 0, wx.EXPAND)
        sizer.Add(self._browser, 1, wx.EXPAND)
        self.SetSizer(sizer)

        self.Bind(html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnTitle)


    def OnTitle(self, event):
        self.Title = event.GetString()


class MyApp(wx.App):
    def OnInit(self):
        self.frame = WebFrame(None, "HTML2 Browser")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

When I opened the sample file, this is what the script displayed:

Tested using wxPython 4.2.3 gtk3 (phoenix) wxWidgets 3.2.7 + Python 3.12.3 + Linux Mint 22.1

My question is specific to wx.html.HtmlWindow.

I don’t want to use html2.WebView, because although it supports the entire HTML, along with CSS and Javascript, the OS-specific browser engines it uses for that tend to also have “security features”, such as refusing to display local images if the content was set programmatically (e. g. through SetPage, not LoadURL). At the moment, images in such case are displayed on my Linux, not displayed on Windows, showing some “security restricted forbidden blah-blah” instead.

OK. That’s fair enough.

import wx
import wx.html as html
import wx.lib.wxpTag


class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(500, 500))

        self.control = html.HtmlWindow(self, size=(500, 500))
        self.windowSizer = wx.BoxSizer()
        self.windowSizer.Add(self.control, 1, wx.ALL | wx.EXPAND)

        content = r'''<html><head></head><body>
        Some text first<br>
        <wxp module="wx" class="CheckBox">
            <param name="id" value="1">
            <param name="name" value="MyName">
            <param name="label" value="MyLabel">
        </wxp><br>
        <wxp module="wx" class="CheckBox"><param name="id" value="2"></wxp><br>
        <wxp module="wx" class="CheckBox"><param name="id" value="3"></wxp><br>
        </body></html>
        '''
        self.control.SetPage(content)

        self.SetSizerAndFit(self.windowSizer)
        self.control.Bind(wx.EVT_CHECKBOX, self.OnCheck)

        children = self.control.GetChildren()
        for child in children:
            if child.GetId() == 1:
                child.SetValue(True)
                break


    def OnCheck(self, evt):
        print(f"{evt.Id} checked: {evt.IsChecked()}")


if __name__ == '__main__':
    app = wx.App()
    frame = MainWindow(None, -1, "Window")
    frame.Show(1)
    app.MainLoop()

Works. Thank you.