Ok, I think I asked this question more generally a few days ago, but now that I have some XRC experience, I will be more specific and hopefully it will make more sense.
But before I ask, I have one other question. In an example on the wxPyWiki I saw this kind of code:
Are lines 2-5 necessary for creating the widgets, or are they there just so the program will have access to them later? I ran something similar myself and it seems like the LoadFrame call automatically creates and shows the children of the frame, so I wasn't sure if 2-5 were actually doing anything at this point, or if they were just to assign references.
Ok, now my main question: I want to create a program that will allow the user to open new tabs using the Notebook widget. I understand how to use XRC to design a static layout, but I don't understand where the GUI code is supposed to go for the notebook pages that will be created during the run of the program. It's not something that I want to appear when the program starts, so it seems like it's wrong to put them as children of the frame. I thought maybe, since notebook pages are custom Panels, that I could put a top-level Panel widget in the XRC file, but I tried this and it didn't seem to work. I wasn't sure how to access it, and when the program finally ran without errors, it just showed a frame with a panel.
So I hope someone can explain how to use XRC when you expect to create new widgets during runtime.
Ok, I think I asked this question more generally a few days ago, but now that I have some XRC experience, I will be more specific and hopefully it will make more sense.
But before I ask, I have one other question. In an example on the wxPyWiki I saw this kind of code:
Are lines 2-5 necessary for creating the widgets, or are they there just so the program will have access to them later? I ran something similar myself and it seems like the LoadFrame call automatically creates and shows the children of the frame, so I wasn't sure if 2-5 were actually doing anything at this point, or if they were just to assign references.
They are just for assigning references. The XRCCTRL function basically looks up the ID for the name, and then does a FindWindowById.
Ok, now my main question: I want to create a program that will allow the user to open new tabs using the Notebook widget. I understand how to use XRC to design a static layout, but I don't understand where the GUI code is supposed to go for the notebook pages that will be created during the run of the program. It's not something that I want to appear when the program starts, so it seems like it's wrong to put them as children of the frame. I thought maybe, since notebook pages are custom Panels, that I could put a top-level Panel widget in the XRC file, but I tried this and it didn't seem to work. I wasn't sure how to access it, and when the program finally ran without errors, it just showed a frame with a panel.
So I hope someone can explain how to use XRC when you expect to create new widgets during runtime.
If you define the pages in the XRC as children of the notebook then when you load the notebook it will load all the pages. If you want to load the pages separately, then define them in the XRC as separate top-level panels. Then in your code when you decide to add a page you can load it from the XRC at that time and add it to the notebook programatically.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
If you define the pages in the XRC as children of the notebook then when you load the notebook it will load all the pages. If you want to load the pages separately, then define them in the XRC as separate top-level panels. Then in your code when you decide to add a page you can load it from the XRC at that time and add it to the notebook programatically.
I tried this but I think I must be doing it wrong. I defined a separate Panel object at the top-level, and I tried adding it to the notebook. Here is my code:
Ah, I forgot to add the Notebook to a BoxSizer! Now it works!
Ok, more confusion. Here is my code and XRC. Why do I get this error message when I don't comment out the two lines in the InitMenu() method, but when they are commented it works fine (and still shows the menu bar)?
Python Error
XRC resource 'menuBar' (class 'wxMenuBar') not found!
Ah, I forgot to add the Notebook to a BoxSizer! Now it works!
Ok, more confusion. Here is my code and XRC. Why do I get this error message when I don't comment out the two lines in the InitMenu() method, but when they are commented it works fine (and still shows the menu bar)?
Python Error
XRC resource 'menuBar' (class 'wxMenuBar') not found!
Because the menu bar is not a top-level item in your XRC file. It is a child of the mainFrame so it is created and associated with the frame when the frame is loaded. The Load* methods can only "see" items that are at the top-level in the resource, in other words their parent node is <resource>
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
Ah, I forgot to add the Notebook to a BoxSizer! Now it works!
Ok, more confusion. Here is my code and XRC. Why do I get this error message when I don't comment out the two lines in the InitMenu() method, but when they are commented it works fine (and still shows the menu bar)?
Python Error
XRC resource 'menuBar' (class 'wxMenuBar') not found!
Because the menu bar is not a top-level item in your XRC file. It is a child of the mainFrame so it is created and associated with the frame when the frame is loaded. The Load* methods can only "see" items that are at the top-level in the resource, in other words their parent node is <resource>
Ah ha! Thanks! So which is the preferred method? I think I put the MenuBar beneath the Frame because that's how it's normally done when hand-written, right? The menu is a child of the frame? Seems simpler to do that in XRC too, so the frame automatically initializes it, but I see an example that doesn't do this (which is where I got the InitMenu code from).
So I hope someone can explain how to use XRC when you expect to create new widgets during runtime.
::sigh:: This is still behaving strangely. I attach my two files (one for the program, one for XRC). For some reason when you go to File --> New Record, it properly creates a new tab, but the background changes to a darker color. But if you drag the window to a larger sizer, the rest of the revealed space is white, while the darker color remains in its original size.
Furthermore, once you create a second tab, then this dark color goes away altogether.
So what is it? Do I need to do something extra with a sizer, perhaps? Or sizer settings on the notebook or panel controls?
Because the menu bar is not a top-level item in your XRC file. It is a child of the mainFrame so it is created and associated with the frame when the frame is loaded. The Load* methods can only "see" items that are at the top-level in the resource, in other words their parent node is <resource>
Ah ha! Thanks! So which is the preferred method?
If you need to have direct access to the menubar before you give it to the frame, or if you need to change menubars over the life of the app, the define them separately. Otherwise define it inside the frame object.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
One more quickie question: why does this line have to be written this way, with the id keyword argument, instead of like:
xrc.XCRCTRL(self.XXX, 'new RecordMenuItem')
Doesn't the Bind() method take a reference to the object as its third parameter?
Yes, but xrc.XCRCTRL doesn't know how to return a wx.MenuItem, only things that derive from wx.Window. Technically the 3rd parameter can be anything that has a GetId() method, and GetId is what is called if it is passed, otherwise the value of the id parameter is used to make the connection between the source and target of the event.
And why is the 'id' necessary? It didn't work when I left it out.
Because in this case you want to pass a value for the 4th parameter (named 'id') and not the 3rd (named 'source').
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
So I hope someone can explain how to use XRC when you expect to create new widgets during runtime.
::sigh:: This is still behaving strangely. I attach my two files (one for the program, one for XRC). For some reason when you go to File --> New Record, it properly creates a new tab, but the background changes to a darker color. But if you drag the window to a larger sizer, the rest of the revealed space is white, while the darker color remains in its original size.
This is a known problem with, I think, how wx deals with the notebook theme settings for XP. Nobody's found a solution yet. It only happens when the notebook has no pages to begin with, so the easiest way to work around it is to either always give the notebook at least on page, or don't create the notebook until you need to show the first page.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
One more quickie question: why does this line have to be written this way, with the id keyword argument, instead of like:
xrc.XCRCTRL(self.XXX, 'new RecordMenuItem')
Doesn't the Bind() method take a reference to the object as its third parameter?
Yes, but xrc.XCRCTRL doesn't know how to return a wx.MenuItem, only things that derive from wx.Window. Technically the 3rd parameter can be anything that has a GetId() method, and GetId is what is called if it is passed, otherwise the value of the id parameter is used to make the connection between the source and target of the event.
And why is the 'id' necessary? It didn't work when I left it out.
Because in this case you want to pass a value for the 4th parameter (named 'id') and not the 3rd (named 'source').
Thanks! Makes perfect sense. I was even beginning to suspect something like this.
This is a known problem with, I think, how wx deals with the notebook theme settings for XP.
Whew!
when the notebook has no pages to begin with, so the easiest way to work around it is to either always give the notebook at least on page, or don't create the notebook until you need to show the first page.
So how would this look in the XRC? Define the Notebook as top-level? If so, does this mean you need to define a Panel first, then a BoxSizer, *then* the Notebook?
This is a known problem with, I think, how wx deals with the notebook theme settings for XP. Nobody's found a solution yet. It only happens when the notebook has no pages to begin with, so the easiest way to work around it is to either always give the notebook at least on page, or don't create the notebook until you need to show the first page.
I tried both of these options (as best as I know how) and the problem still persists in one form or another. If an initial tab appears by default, it still has that grayish background, and expanding the window makes it white.
I'm not really sure how to create the Notebook at a later time, because it only needs to be done once, so I've only managed to put it into code that keeps creating it each time a new tab is created.
This is a known problem with, I think, how wx deals with the notebook theme settings for XP. Nobody's found a solution yet. It only happens when the notebook has no pages to begin with, so the easiest way to work around it is to either always give the notebook at least on page, or don't create the notebook until you need to show the first page.
I tried both of these options (as best as I know how) and the problem still persists in one form or another. If an initial tab appears by default, it still has that grayish background, and expanding the window makes it white.
Yes, I've just discovered that too. I'll ask about it on wx-dev.
I'm not really sure how to create the Notebook at a later time, because it only needs to be done once,
>> I'm not really sure how to create the Notebook at a later time,
>> because it only needs to be done once,
>
> See the attached for one way to do it.
>> I'm not really sure how to create the Notebook at a later time,
>> because it only needs to be done once,
>
> See the attached for one way to do it.
Thanks! It's making more sense now!
Hmm, I just noticed that this still does the same thing. I think what I'm going to do is make my frame non-resizable anyway, so this will prevent the resizing to cause a discoloration.
But wait, this won't completely fix the issue, because the first tab will still be a gray color, and then when the next tab is opened the background will change to white.
>> I'm not really sure how to create the Notebook at a later time,
>> because it only needs to be done once,
>
> See the attached for one way to do it.
Thanks! It's making more sense now!
Hmm, I just noticed that this still does the same thing.
Yeah, I know the color problem wasn't solved, I was just showing you a way to create the notebook later when you create the first page.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!