Two quick questions

I'm writing an app that will have several distinct states, and I have a couple of minor questions about the best way to do things.

1) I have a single frame containing a panel. The panel is changed when the app changes state. I also want to change the menu to contain only items appropriate to the current state. Am I better off getting the frame's menubar, deleting unneeded items, and adding new ones, or can I simply create a new menubar and call wxFrame.SetMenuBar(new_menubar)?

2) The state-change transitions often include sending a command to a remote server and waiting for a response. During that time, there's no practical use for user interaction. I want to disable input and "gray out" the panel while waiting, so that the user knows to just be patient. I'm currently using wxPanel.Enable(False) and wxBeginBusyCursor(), but I can't find a simple/obvious way to gray out the entire panel (Enable() doesn't change the appearance, it seems). I seem to remember seeing this discussed on the list, but I don't recall the proper method...

Thanks in advance for any pointers anyone might have.

Jeff Shannon
Technician/Programmer
Credit International

I'm writing an app that will have several distinct states, and I have a
couple of minor questions about the best way to do things.

1) I have a single frame containing a panel. The panel is changed when
the app changes state. I also want to change the menu to contain only
items appropriate to the current state. Am I better off getting the
frame's menubar, deleting unneeded items, and adding new ones, or can I
simply create a new menubar and call wxFrame.SetMenuBar(new_menubar)?

I think that would depend upon how much the change of state affects the
menus. If they stay mostly the same, then it would make sense to delete
or grey out individual items. If the menus change drastically, then
keeping two or more menubars seems most elegant. BTW, does that work?
I've never tried it.

2) The state-change transitions often include sending a command to a
remote server and waiting for a response. During that time, there's no
practical use for user interaction.

What about a "Cancel" button? That would seem a practical use.

I want to disable input and "gray
out" the panel while waiting, so that the user knows to just be patient.
I'm currently using wxPanel.Enable(False) and wxBeginBusyCursor(), but
I can't find a simple/obvious way to gray out the entire panel (Enable()
doesn't change the appearance, it seems). I seem to remember seeing
this discussed on the list, but I don't recall the proper method...

You could traverse the panel's children using window.GetChildren(),
changing their state. Alternatively, you could simply pop a modal
dialog on top of your frame, preventing user interaction. This would
also be a good place to put the Cancel button :wink:

Regards,
Cliff

···

On Tue, 2003-08-05 at 19:20, Jeff Shannon wrote:

--
Take a hollow point revolver, right down the rapids of your heart
                                                           -Coil

Cliff Wells wrote:

I'm writing an app that will have several distinct states, and I have a couple of minor questions about the best way to do things.

1) I have a single frame containing a panel. The panel is changed when the app changes state. I also want to change the menu to contain only items appropriate to the current state. Am I better off getting the frame's menubar, deleting unneeded items, and adding new ones, or can I simply create a new menubar and call wxFrame.SetMenuBar(new_menubar)?
   
I think that would depend upon how much the change of state affects the
menus. If they stay mostly the same, then it would make sense to delete
or grey out individual items. If the menus change drastically, then
keeping two or more menubars seems most elegant. BTW, does that work? I've never tried it.

The menus will have only a few points of similarity, therefore it seems to me that it'd be easier to construct an entirely new menubar for each panel. However, I don't know if that'll work -- that's what I'm asking. :wink:

2) The state-change transitions often include sending a command to a remote server and waiting for a response. During that time, there's no practical use for user interaction.
   
What about a "Cancel" button? That would seem a practical use.

My (client) program is submitting XMLRPC requests to a server; there's no provisions (AFAIK) in the XMLRPC library to cancel an already-submitted request. I could, at least in theory, simply ignore the result of the request, but when the event in question is an attempt to post information to the server database, and there's no guarantee that (even if I could cancel it) any cancellation would come before the database change was made, I'd be just as happy to not delude users into thinking that "Cancel" will do what they expect. It'll be easy enough to edit/delete any mistakes anyhow...

I want to disable input and "gray out" the panel while waiting, so that the user knows to just be patient. I'm currently using wxPanel.Enable(False) and wxBeginBusyCursor(), but I can't find a simple/obvious way to gray out the entire panel (Enable() doesn't change the appearance, it seems). I seem to remember seeing this discussed on the list, but I don't recall the proper method...
   
You could traverse the panel's children using window.GetChildren(),
changing their state. Alternatively, you could simply pop a modal
dialog on top of your frame, preventing user interaction. This would
also be a good place to put the Cancel button :wink:

Ah, I should've realized that Enable() wouldn't automatically affect child windows; that makes sense. I've considered the modal dialog; however, realizing that any OK or Cancel button would be more misleading than useful makes this seem questionable. I *could* pop up a small dialog with just static text... probably end up trying both and see which I prefer from a UI perspective.

Jeff Shannon
Technician/Programmer
Credit International

···

On Tue, 2003-08-05 at 19:20, Jeff Shannon wrote:

Cliff Wells wrote:

The menus will have only a few points of similarity, therefore it seems
to me that it'd be easier to construct an entirely new menubar for each
panel. However, I don't know if that'll work -- that's what I'm asking. :wink:

Well, why are you asking me? I don't know either <wink>

>You could traverse the panel's children using window.GetChildren(),
>changing their state. Alternatively, you could simply pop a modal
>dialog on top of your frame, preventing user interaction. This would
>also be a good place to put the Cancel button :wink:

Ah, I should've realized that Enable() wouldn't automatically affect
child windows; that makes sense.

Well, actually I think it does work for most children. ISTR there are a
couple widgets that somehow escape being (en/dis)abled, but you might
not be using them.

"""
virtual bool Enable(bool enable = true)

Enable or disable the window for user input. Note that when a parent
window is disabled, all of its children are disabled as well and they
are reenabled again when the parent is.
"""

I thought you were saying you had tried it and it didn't work. Have you
tried it?

Regards,

···

On Wed, 2003-08-06 at 11:07, Jeff Shannon wrote:

--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 (800) 735-0555

Okay, now I do.

"""
void SetMenuBar(wxMenuBar* menuBar)
...

Note that it is not possible to call this function twice for the same
frame object.
"""

Regards,

···

On Wed, 2003-08-06 at 11:54, Cliff Wells wrote:

On Wed, 2003-08-06 at 11:07, Jeff Shannon wrote:
> Cliff Wells wrote:

> The menus will have only a few points of similarity, therefore it seems
> to me that it'd be easier to construct an entirely new menubar for each
> panel. However, I don't know if that'll work -- that's what I'm asking. :wink:

Well, why are you asking me? I don't know either <wink>

--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 (800) 735-0555

Strangely enough, despite what the docs seem to imply, this works for me
(Linux/GTK):

import wx

class Frame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "")
        self.menuBar= {}
        self.menuBar[0] = wx.MenuBar()
        self.menuBar[1] = wx.MenuBar()

        menu = wx.Menu()
        id = wx.NewId()
        menu.Append(id, "&Item 1")
        id = wx.NewId()
        menu.Append(id, "&Item 2")
        id = wx.NewId()
        menu.Append(id, "&Use menu 2")
        wx.EVT_MENU(self, id, lambda evt, m = 1: self.switchMenu(m))
        self.menuBar[0].Append(menu, "&Menu 1")

        menu = wx.Menu()
        id = wx.NewId()
        menu.Append(id, "&Item 4")
        id = wx.NewId()
        menu.Append(id, "&Item 5")
        id = wx.NewId()
        menu.Append(id, "&Use menu 1")
        wx.EVT_MENU(self, id, lambda evt, m = 0: self.switchMenu(m))
        self.menuBar[1].Append(menu, "&Menu 2")

        self.SetMenuBar(self.menuBar[0])

    def switchMenu(self, menu):
        self.SetMenuBar(self.menuBar[menu])

class App(wx.App):
    def OnInit(self):
        f = Frame(None, -1)
        f.Show(True)
        return True

app = App()
app.MainLoop()

HTH,

Cliff

···

On Wed, 2003-08-06 at 11:54, Cliff Wells wrote:

On Wed, 2003-08-06 at 11:07, Jeff Shannon wrote:
> Cliff Wells wrote:

> The menus will have only a few points of similarity, therefore it seems
> to me that it'd be easier to construct an entirely new menubar for each
> panel. However, I don't know if that'll work -- that's what I'm asking. :wink:

Well, why are you asking me? I don't know either <wink>

--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 (800) 735-0555