0

I have a wxpython gui, which I defined in an xrc file, the root item (idk if that is the right term) of this gui is a wxFrame, which I load into a wxDialog window. I want to then populate stuff, inside of this gui, from python, but I can't seem to be able to do this.

As an example, lets say I have the following 2 files:

test.py:

import wx
import wx.xrc

class GUI(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size(400,800), style = wx.TAB_TRAVERSAL)

        # Create an instance of the XmlResource class and load the resource file
        xml_resource = wx.xrc.XmlResource()
        xml_resource.Load('test.xrc')

        # Create a box sizer for the dialog
        outer_sizer = wx.BoxSizer(wx.VERTICAL)
        
        # Load the panel object from the resource file and add it to the outer sizer
        panel = xml_resource.LoadObject(self, 'panel', 'wxPanel')
        outer_sizer.Add(panel, 1, wx.EXPAND)

        panel2 = xml_resource.LoadObject(self, 'panel2', 'wxPanel')

        # Set the dialog's sizer
        self.SetSizer(outer_sizer)

# Create a wx.App instance and run the main dialog
app = wx.App()
dialog = GUI(None)
dialog.Show()
app.MainLoop()

test.xrc:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.5.3.0">
    <object class="wxPanel" name="panel">
        <style>wxTAB_TRAVERSAL</style>
        <object class="wxBoxSizer">
            <orient>wxVERTICAL</orient>
            <object class="sizeritem">
                <option>1</option>
                <flag>wxEXPAND | wxALL</flag>
                <border>5</border>
                <object class="wxPanel" name="panel2">
                    <style>wxTAB_TRAVERSAL</style>
                    <bg>#4b6983</bg>
                </object>
            </object>
        </object>
    </object>
</resource>

Then panel will load correctly, but it will throw an error: (XRC error: XRC resource "panel2" (class "wxPanel") not found. So my question would be: how would one properly load a panel (or a scrollbox, or a sizer, etc) that has been defined in an xrc file into python, so that it can be populated? And is that even possible?

TT-392
  • 43
  • 5
  • From the docs for LoadObject: "In either case, only the resources defined at the top level of XRC files can be loaded by this function, use LoadObjectRecursively() if you need to load an object defined deeper in the hierarchy. " However, when you loaded panel, that will have created panel2, so panel2 already exists. – Randolph Dec 12 '22 at 18:40
  • I know that panel2 already exists in the gui, but I want to reach it from python so that I can put stuff in the panel. I think LoadObjectsRecursively does indeed create another panel2 ui element which I don't want. I guess my approach of using LoadObject is wrong, but I can't tell how you are supposed to do it? – TT-392 Dec 12 '22 at 22:32

1 Answers1

1

Let's run with a second attempt, now you have defined a little more, of what you're trying to achieve.

the wx.xrc module allows you to request the name and/or id of an object within the xrc resource. So in your case, this could result in:

import wx
import wx.xrc

class GUI(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size(400,800), style = wx.TAB_TRAVERSAL)

        # Create an instance of the XmlResource class and load the resource file
        xml_resource = wx.xrc.XmlResource()
        xml_resource.Load('test.xrc')

        # Create a box sizer for the dialog
        outer_sizer = wx.BoxSizer(wx.VERTICAL)

        # Load the panel object from the resource file and add it to the outer sizer
        panel = xml_resource.LoadObject(self, 'panel', 'wxPanel')
        outer_sizer.Add(panel, 1, wx.EXPAND)

        self.panel2 = wx.xrc.XRCCTRL(self, "panel2")

        self.cb = wx.ComboBox(self.panel2, wx.ID_ANY, choices=[("Choice 1"), ("Choice 2")], style=wx.CB_READONLY)

        # Set the dialog's sizer
        self.SetSizer(outer_sizer)

# Create a wx.App instance and run the main dialog
app = wx.App()
dialog = GUI(None)
dialog.Show()
app.MainLoop()

Here the resource object defined in the xrc file as panel2 is defined within the code and then is available to be accessed as such.

For the record, for the id use wx.xrc.XRCID("panel2")

In your example, this results as follows, if I add in a wx.ComboBox

enter image description here

Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60
  • As far as I can tell, this example code populates a frame created in python with stuff defined in an xrc file. That is the opposite of my problem. I need to populate something inside of one of the elements defined in the xrc file with stuff created in python. – TT-392 Dec 12 '22 at 22:35
  • @TT-392, can you explain in plain English (and maybe with the sketch) what you are looking for? – Igor Dec 12 '22 at 23:15
  • Basically, I designed a complicated gui using an xrc file. Somewhere inside of this gui, there is a scroll box, which I want to dynamically populate with some buttons and text inputs. This has to be done on the python side, because the way these buttons and text inputs are positioned inside that scroll box depends on stuff elsewhere in the program. Therefore, I need to be able to access that scroll box, which is nested somewhere in the gui, from python. (I used a frame in my example in an attempt to simplify things) – TT-392 Dec 12 '22 at 23:22
  • 1
    @TT-392 See my adjusted answer – Rolf of Saxony Dec 13 '22 at 10:25