Toolbar in Windows 7 staying in the background

I’m building an application with an embedded sqlite3 database for use with ruggedized tablets by field geologists. It uses a single frame, with different panels being loaded for different modules/database tables. Although each frame contains a unique set of fields and buttons, the menus and the toolbar are common to all of them. They are attached to the frame, using a login window on a panel that creates them programatically on a successful user login.

I’ve done most of the development work on my personal laptop running Ubuntu, and everything I’ve got so far is looking pretty good – management is pleased. Unfortunately, the application will not be used on Linux. The tablets run Windows 7, and it’s not going quite so well there.

Most things I’ve been able to work through, but the issue that has me stymied is the menu bar. I’ll show code if asked, but I’m not sure if it’s really a coding issue or a design issue. The toolbar will usually appear properly on the first screen that loads after the user login. However, if you navigate to any subsequent window, the toolbar is overwritten by the panel’s background color. The individual button icons are still visible, but the “bar” portion is hidden, while the enabled buttons will turn to the toolbar color if hovered over, disabled buttons will not, leaving a splotchy appearance.

Functionally, the toolbar does work, but I simply can’t get it to “look” like a toolbar. Doing a SetBackgroundColour on it has no effect. Also, I said it usually looks normal on the first panel that loads. If you return to that panel after navigating to another one, the toolbar has the same problem it does on all the other panels. The background color covers it up.

It seems like all I need is some way to bring the toolbar to the “top” of the display. Is there a Windows technique?

Thanks!

Dave

Hi Dave,

···

On Thursday, September 6, 2012 12:06:02 AM UTC-5, llanitedave wrote:

I’m building an application with an embedded sqlite3 database for use with ruggedized tablets by field geologists. It uses a single frame, with different panels being loaded for different modules/database tables. Although each frame contains a unique set of fields and buttons, the menus and the toolbar are common to all of them. They are attached to the frame, using a login window on a panel that creates them programatically on a successful user login.

I’ve done most of the development work on my personal laptop running Ubuntu, and everything I’ve got so far is looking pretty good – management is pleased. Unfortunately, the application will not be used on Linux. The tablets run Windows 7, and it’s not going quite so well there.

Most things I’ve been able to work through, but the issue that has me stymied is the menu bar. I’ll show code if asked, but I’m not sure if it’s really a coding issue or a design issue. The toolbar will usually appear properly on the first screen that loads after the user login. However, if you navigate to any subsequent window, the toolbar is overwritten by the panel’s background color. The individual button icons are still visible, but the “bar” portion is hidden, while the enabled buttons will turn to the toolbar color if hovered over, disabled buttons will not, leaving a splotchy appearance.

Functionally, the toolbar does work, but I simply can’t get it to “look” like a toolbar. Doing a SetBackgroundColour on it has no effect. Also, I said it usually looks normal on the first panel that loads. If you return to that panel after navigating to another one, the toolbar has the same problem it does on all the other panels. The background color covers it up.

It seems like all I need is some way to bring the toolbar to the “top” of the display. Is there a Windows technique?

Thanks!

Dave

I’ve not seen that on Windows. Are you just switching between panels in your frame by showing/hiding them? Are you calling a Layout() at the end of a panel change? Is the menu attached to the frame? Are we talking about an app that is full-screen?

  • Mike

Are you sure you attached it to the frame and not to the panel? If yes, try to do a small sample app with just the menu, toolbar and use a button on the initial frame to "fake" your login process.

http://wiki.wxpython.org/MakingSampleApps

Werner

···

On 06/09/2012 07:06, llanitedave wrote:

I'm building an application with an embedded sqlite3 database for use with ruggedized tablets by field geologists. It uses a single frame, with different panels being loaded for different modules/database tables. Although each frame contains a unique set of fields and buttons, the menus and the toolbar are common to all of them. They are attached to the frame, using a login window on a panel that creates them programatically on a successful user login.

I've done most of the development work on my personal laptop running Ubuntu, and everything I've got so far is looking pretty good -- management is pleased. Unfortunately, the application will not be used on Linux. The tablets run Windows 7, and it's not going quite so well there.

Most things I've been able to work through, but the issue that has me stymied is the menu bar. I'll show code if asked, but I'm not sure if it's really a coding issue or a design issue. The toolbar will *usually* appear properly on the first screen that loads after the user login. However, if you navigate to any subsequent window, the toolbar is overwritten by the panel's background color. The individual button icons are still visible, but the "bar" portion is hidden, while the enabled buttons will turn to the toolbar color if hovered over, disabled buttons will not, leaving a splotchy appearance.

Functionally, the toolbar does work, but I simply can't get it to "look" like a toolbar. Doing a SetBackgroundColour on it has no effect. Also, I said it usually looks normal on the first panel that loads. If you return to that panel after navigating to another one, the toolbar has the same problem it does on all the other panels. The background color covers it up.

It seems like all I need is some way to bring the toolbar to the "top" of the display. Is there a Windows technique?

Yes, I am doing panel switching using show and hide. Is that the problem? A typical switch goes like this:

self.current_panel.Hide()

self.current_panel = tablefile.MyDataEntryPanel(self)

self.current_panel.Show()

I haven’t been using the Layout() command either – I don’t think I was aware of it. It didn’t seem to be causing any problems on Linux. Something new to experiment with.

···

On Thursday, September 6, 2012 7:08:16 AM UTC-7, Mike Driscoll wrote:

Hi Dave,

On Thursday, September 6, 2012 12:06:02 AM UTC-5, llanitedave wrote:

I’m building an application with an embedded sqlite3 database for use with ruggedized tablets by field geologists. It uses a single frame, with different panels being loaded for different modules/database tables. Although each frame contains a unique set of fields and buttons, the menus and the toolbar are common to all of them. They are attached to the frame, using a login window on a panel that creates them programatically on a successful user login.

I’ve done most of the development work on my personal laptop running Ubuntu, and everything I’ve got so far is looking pretty good – management is pleased. Unfortunately, the application will not be used on Linux. The tablets run Windows 7, and it’s not going quite so well there.

Most things I’ve been able to work through, but the issue that has me stymied is the menu bar. I’ll show code if asked, but I’m not sure if it’s really a coding issue or a design issue. The toolbar will usually appear properly on the first screen that loads after the user login. However, if you navigate to any subsequent window, the toolbar is overwritten by the panel’s background color. The individual button icons are still visible, but the “bar” portion is hidden, while the enabled buttons will turn to the toolbar color if hovered over, disabled buttons will not, leaving a splotchy appearance.

Functionally, the toolbar does work, but I simply can’t get it to “look” like a toolbar. Doing a SetBackgroundColour on it has no effect. Also, I said it usually looks normal on the first panel that loads. If you return to that panel after navigating to another one, the toolbar has the same problem it does on all the other panels. The background color covers it up.

It seems like all I need is some way to bring the toolbar to the “top” of the display. Is there a Windows technique?

Thanks!

Dave

I’ve not seen that on Windows. Are you just switching between panels in your frame by showing/hiding them? Are you calling a Layout() at the end of a panel change? Is the menu attached to the frame? Are we talking about an app that is full-screen?

  • Mike

To add, I just added self.current_panel.Layout() to one of my panel calling methods. It didn’t make any difference.

Werner, I’ll probably be able to do the sample code tonight. I hope I think of something between now and then. The createtoolbar method is attached to the frame, although it’s called by the login method which is attached to a panel.

···

On Thursday, September 6, 2012 8:49:25 AM UTC-7, llanitedave wrote:

Yes, I am doing panel switching using show and hide. Is that the problem? A typical switch goes like this:

self.current_panel.Hide()

self.current_panel = tablefile.MyDataEntryPanel(self)

self.current_panel.Show()

I haven’t been using the Layout() command either – I don’t think I was aware of it. It didn’t seem to be causing any problems on Linux. Something new to experiment with.

On Thursday, September 6, 2012 7:08:16 AM UTC-7, Mike Driscoll wrote:

Hi Dave,

On Thursday, September 6, 2012 12:06:02 AM UTC-5, llanitedave wrote:

I’m building an application with an embedded sqlite3 database for use with ruggedized tablets by field geologists. It uses a single frame, with different panels being loaded for different modules/database tables. Although each frame contains a unique set of fields and buttons, the menus and the toolbar are common to all of them. They are attached to the frame, using a login window on a panel that creates them programatically on a successful user login.

I’ve done most of the development work on my personal laptop running Ubuntu, and everything I’ve got so far is looking pretty good – management is pleased. Unfortunately, the application will not be used on Linux. The tablets run Windows 7, and it’s not going quite so well there.

Most things I’ve been able to work through, but the issue that has me stymied is the menu bar. I’ll show code if asked, but I’m not sure if it’s really a coding issue or a design issue. The toolbar will usually appear properly on the first screen that loads after the user login. However, if you navigate to any subsequent window, the toolbar is overwritten by the panel’s background color. The individual button icons are still visible, but the “bar” portion is hidden, while the enabled buttons will turn to the toolbar color if hovered over, disabled buttons will not, leaving a splotchy appearance.

Functionally, the toolbar does work, but I simply can’t get it to “look” like a toolbar. Doing a SetBackgroundColour on it has no effect. Also, I said it usually looks normal on the first panel that loads. If you return to that panel after navigating to another one, the toolbar has the same problem it does on all the other panels. The background color covers it up.

It seems like all I need is some way to bring the toolbar to the “top” of the display. Is there a Windows technique?

Thanks!

Dave

I’ve not seen that on Windows. Are you just switching between panels in your frame by showing/hiding them? Are you calling a Layout() at the end of a panel change? Is the menu attached to the frame? Are we talking about an app that is full-screen?

  • Mike

I’m attaching a sample file that displays 3 panels that are children of a single frame. Two of those panels have a toolbar assigned to them. Buttons toggle back and forth between the two panels.

I’m also attaching a couple of screenshots: one from the Linux version and one from the Windows version. The Linux version looks just like I thought it should. The toolbar sits above the panel’s background, and has a light green shade of its own.

On Windows, the panel overlaps the toolbar, and the toolbar background color doesn’t work (which in itself is not a problem for me).

I hope this is enough for you to go on. How do I get the toolbar to sit above panel background in Windows the same way it already does in Linux? What is my code missing?

Thanks!

Dave

toolbarshort.py (5.78 KB)

user.png

linuxwxtoolbar.png

windowswxpanel.PNG

Every time you show a different panel you are doing something like this:

         self.current_panel.Hide()
         self.current_panel = PortalPanel(self)
         self.current_panel.Show()

and that is losing the reference to the old current_panel and creating a new instance to replace it. That old panel still exists and although it's hidden, it will still consume resources. And when you "GoBack" you are creating a new instance instead of reusing the old one. The typical way to do things like this is to create all your panels to begin with keeping a reference to each of them and hide all but one of them, and then do a Hide/Show of the appropriate panels when you want to switch views.

As for the layout issue, I expect that the problem has to do with the fact that you have multiple child panels (after the 2nd one is created anyway) and the frame's automatic fill-the-client-area functionality is only triggered when the frame has only one non-bar child. So you'll want to give the frame a sizer, add all the panels to it, and call self.Layout() each time you show a new one.

···

On 9/6/12 8:31 PM, llanitedave wrote:

I'm attaching a sample file that displays 3 panels that are children of
a single frame. Two of those panels have a toolbar assigned to them.
  Buttons toggle back and forth between the two panels.

I'm also attaching a couple of screenshots: one from the Linux version
and one from the Windows version. The Linux version looks just like I
thought it should. The toolbar sits above the panel's background, and
has a light green shade of its own.

On Windows, the panel overlaps the toolbar, and the toolbar background
color doesn't work (which in itself is not a problem for me).

I hope this is enough for you to go on. How do I get the toolbar to sit
above panel background in Windows the same way it already does in Linux?
  What is my code missing?

--
Robin Dunn
Software Craftsman

To me the toolbar shows fine on Win 7 with Python 2.7 and wxPython 2.9.4.0.b20120623.

But I notice that you are creating new panels all the time, you are just assigning them to self.current_panel and they are not controlled by a sizer.

In other words after I clicked a few times "alright" and "go to previous" I ended up with multiple instances of PortalPanel and TogglePanel.

I added a sizer and used the "WIT" to discover/confirm the above.

WIT = http://wiki.wxpython.org/Widget%20Inspection%20Tool

I think you should change your code that you only have one instance of PortalPanel and TogglePanel and then show and hide them and call Layout on the top/frame sizer.

Werner

toolbarshort.py (6.08 KB)

···

On 07/09/2012 05:31, llanitedave wrote:

I'm attaching a sample file that displays 3 panels that are children of a single frame. Two of those panels have a toolbar assigned to them. Buttons toggle back and forth between the two panels.

I'm also attaching a couple of screenshots: one from the Linux version and one from the Windows version. The Linux version looks just like I thought it should. The toolbar sits above the panel's background, and has a light green shade of its own.

On Windows, the panel overlaps the toolbar, and the toolbar background color doesn't work (which in itself is not a problem for me).

I hope this is enough for you to go on. How do I get the toolbar to sit above panel background in Windows the same way it already does in Linux? What is my code missing?

The mystery deepens, for me at least. I implemented Robin's and
werner's suggestions:

Not really. You're still waiting to create the new panels until when they need to be shown. But at least you are destroying the old login panel before you lose a reference to it. (Be aware however that there could be pending events for those windows and destroying them could lead to trouble. Only top-level windows will automatically do a delayed destroy, but you can also do it for any window by using wx.CallAfter(window.Destroy) )

I made a single instance of each panel that could
be toggled in and out, I created a Box sizer for the frame and added the
panels to it,

But you never use SetSizer to assign that sizer to the frame.

and Iused the self.Layout() command with the show command.

No, you're using self.current_panel.Layout() which will redo the layout of the contents of the panel but not the panel itself. You should be calling the Frame's Layout so it will resize and reposition the currently visible panel to fill the frame's client area. Also, the new panel needs to be shown before the layout, otherwise the sizer will ignore it.

Now, when I toggle back and forth between the panels, "Panel 1" shows
the toolbar properly, but "Panel 2" still displays the same glitch that
it did before. I can't find any code differences that would account for
the behavioral differences. And what's even stranger now, the menubar
doesn't show at all!

I suspect that since you are not adding the toolbar and menubar until after the frame is already shown that it will need a real size event to execute the code that will correctly reposition its client area origin. Try calling SendSizeEvent right after the toolbar and menubar have been created.

···

On 9/8/12 8:41 AM, llanitedave wrote:

--
Robin Dunn
Software Craftsman

Thanks so much for your patience, Robin. It’s embarrassing to need this much hand-holding for something that should be so simple.

We’re making progress, though!

I changed the code in the button methods to

self.Layout()

self.current_panel.Show()

And I added

self.SetSizer(self.framesizer)

to the frame’s init method.

That made the difference for the toolbar. Now it works as it should for both panels. Big step!

But I had no luck on the menu bar. I put

self.makeMenuBar()

self.makeToolBar()

self.SendSizeEvent()

in the login() method, and I stuck it after Layout() calls as well (Not at the same time). Nothing happens in any case. I wonder if it could be somehow hidden behind the toolbar?

···

On Saturday, September 8, 2012 5:23:58 PM UTC-7, Robin Dunn wrote:

On 9/8/12 8:41 AM, llanitedave wrote:

The mystery deepens, for me at least. I implemented Robin’s and

werner’s suggestions:

Not really. You’re still waiting to create the new panels until when
they need to be shown. But at least you are destroying the old login
panel before you lose a reference to it. (Be aware however that there
could be pending events for those windows and destroying them could lead
to trouble. Only top-level windows will automatically do a delayed
destroy, but you can also do it for any window by using
wx.CallAfter(window.Destroy) )

I made a single instance of each panel that could

be toggled in and out, I created a Box sizer for the frame and added the

panels to it,

But you never use SetSizer to assign that sizer to the frame.

and Iused the self.Layout() command with the show command.

No, you’re using self.current_panel.Layout() which will redo the layout
of the contents of the panel but not the panel itself. You should be
calling the Frame’s Layout so it will resize and reposition the
currently visible panel to fill the frame’s client area. Also, the new
panel needs to be shown before the layout, otherwise the sizer will
ignore it.

Now, when I toggle back and forth between the panels, “Panel 1” shows

the toolbar properly, but “Panel 2” still displays the same glitch that

it did before. I can’t find any code differences that would account for

the behavioral differences. And what’s even stranger now, the menubar

doesn’t show at all!

I suspect that since you are not adding the toolbar and menubar until
after the frame is already shown that it will need a real size event to
execute the code that will correctly reposition its client area origin.
Try calling SendSizeEvent right after the toolbar and menubar have
been created.


Robin Dunn

Software Craftsman

http://wxPython.org

Good morning Dave,

The mystery deepens, for me at least. I implemented Robin's and werner's suggestions: I made a single instance of each panel that could be toggled in and out, I created a Box sizer for the frame and added the panels to it, and Iused the self.Layout() command with the show command.

Now, when I toggle back and forth between the panels, "Panel 1" shows the toolbar properly, but "Panel 2" still displays the same glitch that it did before.

What glitch do you see on the toolbar?

I can't find any code differences that would account for the behavioral differences. And what's even stranger now, the menubar doesn't show at all! I suppose there's something obvious in the code that holds it back, but I don't see it. The menubar in the original app that the example was distilled from still works.

As always, everything seems to work perfectly in Ubuntu, it's just Windows 7 where I'm having the difficulty.

I really appreciate the help you've already given. If you can check my code just one more time, I'm sure that something will jump out at you. It's still hiding from me.

Use the WIT, you will love it. I added it back in to the attached, run it and login and then press ctrl-alt-i.

The problems I noticed where:
- the file menu was not appended to the menubar
- proportion for the panels should be "1", expand in the "main direction" and not "-1" (not sure what it means to a sizer to give it -1 for proportion) - see UsingSizers - wxPyWiki
- the framesizer was not assigned to the frame with "SetSizer"
- You don't need to call "Layout" on the panel as the children where just added, but the frame does not know that something changed, so you need to call its "Layout" method. Or in other words calling layout will propagate down the hierarchy but not up.

I think that is all, but you might do a compare of your and my version to make sure.

Have a nice Sunday
Werner

toolbarshort2.py (6.93 KB)

···

On 08/09/2012 17:41, llanitedave wrote:

Wow, werner – you fixed it! I’m facepalming myself right now for leaving out the menuBar.Append() call. I must have read over that stretch of code a dozen times and still missed it.

And I still have a lot of work to do in order to understand sizers. But your example took me another step along that road.

Thanks very much!

Dave

···

On Sunday, September 9, 2012 12:57:46 AM UTC-7, werner wrote:

Good morning Dave,

On 08/09/2012 17:41, llanitedave wrote:

The mystery deepens, for me at least. I implemented Robin’s and
werner’s suggestions: I made a single instance of each panel that
could be toggled in and out, I created a Box sizer for the frame and
added the panels to it, and Iused the self.Layout() command with the
show command.

Now, when I toggle back and forth between the panels, “Panel 1” shows
the toolbar properly, but “Panel 2” still displays the same glitch
that it did before.

What glitch do you see on the toolbar?

I can’t find any code differences that would account for the
behavioral differences. And what’s even stranger now, the menubar
doesn’t show at all! I suppose there’s something obvious in the code
that holds it back, but I don’t see it. The menubar in the original
app that the example was distilled from still works.

As always, everything seems to work perfectly in Ubuntu, it’s just
Windows 7 where I’m having the difficulty.

I really appreciate the help you’ve already given. If you can check
my code just one more time, I’m sure that something will jump out at
you. It’s still hiding from me.

Use the WIT, you will love it. I added it back in to the attached, run
it and login and then press ctrl-alt-i.

The problems I noticed where:

  • the file menu was not appended to the menubar

  • proportion for the panels should be “1”, expand in the “main
    direction” and not “-1” (not sure what it means to a sizer to give it -1
    for proportion) - see http://wiki.wxpython.org/UsingSizers

  • the framesizer was not assigned to the frame with “SetSizer”

  • You don’t need to call “Layout” on the panel as the children where
    just added, but the frame does not know that something changed, so you
    need to call its “Layout” method. Or in other words calling layout will
    propagate down the hierarchy but not up.

I think that is all, but you might do a compare of your and my version
to make sure.

Have a nice Sunday

Werner

Good morning Dave,

Wow, werner -- you fixed it! I'm facepalming myself right now for leaving out the menuBar.Append() call. I must have read over that stretch of code a dozen times and still missed it.

And I still have a lot of work to do in order to understand sizers.

They are not easy to understand, it took me a long long time and I still have times where I mess it up. But at the end they are well worth the pain;-) .

But your example took me another step along that road.

Great that it helped. Can't push it enough but the WIT is an incredible help for debugging sizer issues and debugging in general.

BTW, you might want to look at the SizedControls in the wxPython demo, for some time I now I use them for my layouts instead of using a UI generator.

Thanks very much!

You are welcome
Werner

···

On 10/09/2012 05:53, llanitedave wrote: