Who's to blame?

N

Nicola Musatti

Hallo,
First of all I apologize for the longish example at the bottom, but
the biggest source file is automatically generated and I didn't want
to modify more than strictly necessary. Also, it would be shorter if
XML wasn't so verbose ;-)

The following is a wxPython/XRC toy program with a form with a button
which, when pressed, causes a simple dialog to be displayed. The
problem lies in the fact that apparently ShowModal() does not return
when either the Yes or the No buttons are pressed. Curiously, if you
change the Yes and No buttons with the OK and Cancel ones that are
currently commented everything works as expected.

As the sbs_test_xrc.py file below is automatically generated by
wxPython 2.8.6.1's XRCed tool from a XRC file which in turn is
generated by wxFormBuilder (http://wxformbuilder.org/), I really cant
figure out to whom I should report this problem, assuming I'm not
missing some obvious mistake of mine, that is.

Thanks for your help.

Cheers,
Nicola Musatti

# sbs_test.py
import wx
import sbs_test_xrc

class MainFrame(sbs_test_xrc.xrcMainFrame):
def __init__(self, parent):
sbs_test_xrc.xrcMainFrame.__init__(self, parent)
self.button.Bind(wx.EVT_BUTTON, self.OnButton)

def OnButton(self, event=None):
d = sbs_test_xrc.xrcDialog(self)
## if d.ShowModal() == wx.ID_OK:
if d.ShowModal() == wx.ID_YES:
self.Close()

class Application(wx.App):
def OnInit(self):
self.frame = MainFrame(None)
self.frame.Show()
self.SetTopWindow(self.frame)
return True

if __name__ == '__main__':
app = Application()
app.MainLoop()

# sbs_test_xrc.py
# This file was automatically generated by pywxrc, do not edit by
hand.
# -*- coding: UTF-8 -*-

import wx
import wx.xrc as xrc

__res = None

def get_resources():
""" This function provides access to the XML resources in this
module."""
global __res
if __res == None:
__init_resources()
return __res

class xrcDialog(wx.Dialog):
def PreCreate(self, pre):
""" This function is called during the class's initialization.

Override it for custom setup before the window is created
usually to
set additional window styles using SetWindowStyle() and
SetExtraStyle()."""
pass

def __init__(self, parent):
# Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
pre = wx.PreDialog()
self.PreCreate(pre)
get_resources().LoadOnDialog(pre, parent, "Dialog")
self.PostCreate(pre)

# create attributes for the named items in this container
self.wxID_YES = xrc.XRCCTRL(self, "wxID_YES")
self.wxID_NO = xrc.XRCCTRL(self, "wxID_NO")

class xrcMainFrame(wx.Frame):
def PreCreate(self, pre):
""" This function is called during the class's initialization.

Override it for custom setup before the window is created
usually to
set additional window styles using SetWindowStyle() and
SetExtraStyle()."""
pass

def __init__(self, parent):
# Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
pre = wx.PreFrame()
self.PreCreate(pre)
get_resources().LoadOnFrame(pre, parent, "MainFrame")
self.PostCreate(pre)

# create attributes for the named items in this container
self.button = xrc.XRCCTRL(self, "button")

# ------------------------ Resource data ----------------------

def __init_resources():
global __res
__res = xrc.EmptyXmlResource()

wx.FileSystem.AddHandler(wx.MemoryFSHandler())

sbs_test_xrc = '''\
<?xml version="1.0" ?><resource version="2.3.0.1" xmlns="http://
www.wxwindows.org/wxxrc">
<object class="wxDialog" name="Dialog">
<style>wxDEFAULT_DIALOG_STYLE</style>
<title/>
<object class="wxFlexGridSizer">
<rows>2</rows>
<cols>2</cols>
<vgap>0</vgap>
<hgap>0</hgap>
<growablecols/>
<growablerows/>
<object class="sizeritem">
<option>1</option>
<flag>wxEXPAND</flag>
<border>5</border>
<object class="wxStdDialogButtonSizer">
<object class="button">
<flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
<border>5</border>
<!--
<object class="wxButton" name="wxID_OK">
<label>&amp;OK</label>
</object>
-->
<object class="wxButton" name="wxID_YES">
<label>&amp;Yes</label>
</object>
</object>
<object class="button">
<flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
<border>5</border>
<!--
<object class="wxButton" name="wxID_CANCEL">
<label>&amp;Cancel</label>
</object>
-->
<object class="wxButton" name="wxID_NO">
<label>&amp;No</label>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="wxFrame" name="MainFrame">
<style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
<size>500,300</size>
<title/>
<object class="wxButton" name="button">
<label>MyButton</label>
<default>0</default>
</object>
</object>
</resource>'''

wx.MemoryFSHandler.AddFile('XRC/sbs_test/sbs_test_xrc',
sbs_test_xrc)
__res.Load('memory:XRC/sbs_test/sbs_test_xrc')
 
R

Rob Williscroft

Nicola Musatti wrote in @e4g2000hsg.googlegroups.com in comp.lang.python:

Note there is a wxpython mailinglist/newsgroup:


[snip]
problem lies in the fact that apparently ShowModal() does not return
when either the Yes or the No buttons are pressed. Curiously, if you
change the Yes and No buttons with the OK and Cancel ones that are
currently commented everything works as expected.

This is because the wx.Dialog class has handlers for the wxID_OK
and wxID_CANCEL button identifiers, IIRC in windows the MS supplied
dialog procedure behaves this way.
As the sbs_test_xrc.py file below is automatically generated by
wxPython 2.8.6.1's XRCed tool from a XRC file which in turn is
generated by wxFormBuilder (http://wxformbuilder.org/), I really cant
figure out to whom I should report this problem, assuming I'm not
missing some obvious mistake of mine, that is.
class MainFrame(sbs_test_xrc.xrcMainFrame):
def __init__(self, parent):
sbs_test_xrc.xrcMainFrame.__init__(self, parent)
self.button.Bind(wx.EVT_BUTTON, self.OnButton)

First you can make the dialog a member, you are showing and hiding it
so there is no need to create a new one every time OnButton is fired.

self.dialog = sbs_test_xrc.xrcDialog(self)

# now replace the defaults of ID_OK and ID_CANCEL
#
self.dialog.SetAffirmativeId( wxID_YES )
self.dialog.SetEscapeId( wxID_NO )

Alternativly you could derive from xrcDialog as you are with
xrcMainFrame and do the above in the derived classes __init__.
def OnButton(self, event=None):
d = sbs_test_xrc.xrcDialog(self)
## if d.ShowModal() == wx.ID_OK:
if d.ShowModal() == wx.ID_YES:
self.Close()

http://www.wxpython.org/docs/api/wx.Dialog-class.html

Rob.
 
K

kyosohma

Hallo,
First of all I apologize for the longish example at the bottom, but
the biggest source file is automatically generated and I didn't want
to modify more than strictly necessary. Also, it would be shorter if
XML wasn't so verbose ;-)

The following is a wxPython/XRC toy program with a form with a button
which, when pressed, causes a simple dialog to be displayed. The
problem lies in the fact that apparently ShowModal() does not return
when either the Yes or the No buttons are pressed. Curiously, if you
change the Yes and No buttons with the OK and Cancel ones that are
currently commented everything works as expected.

As the sbs_test_xrc.py file below is automatically generated by
wxPython 2.8.6.1's XRCed tool from a XRC file which in turn is
generated by wxFormBuilder (http://wxformbuilder.org/), I really cant
figure out to whom I should report this problem, assuming I'm not
missing some obvious mistake of mine, that is.

Thanks for your help.

Cheers,
Nicola Musatti

# sbs_test.py
import wx
import sbs_test_xrc

class MainFrame(sbs_test_xrc.xrcMainFrame):
def __init__(self, parent):
sbs_test_xrc.xrcMainFrame.__init__(self, parent)
self.button.Bind(wx.EVT_BUTTON, self.OnButton)

def OnButton(self, event=None):
d = sbs_test_xrc.xrcDialog(self)
## if d.ShowModal() == wx.ID_OK:
if d.ShowModal() == wx.ID_YES:
self.Close()

class Application(wx.App):
def OnInit(self):
self.frame = MainFrame(None)
self.frame.Show()
self.SetTopWindow(self.frame)
return True

if __name__ == '__main__':
app = Application()
app.MainLoop()

# sbs_test_xrc.py
# This file was automatically generated by pywxrc, do not edit by
hand.
# -*- coding: UTF-8 -*-

import wx
import wx.xrc as xrc

__res = None

def get_resources():
""" This function provides access to the XML resources in this
module."""
global __res
if __res == None:
__init_resources()
return __res

class xrcDialog(wx.Dialog):
def PreCreate(self, pre):
""" This function is called during the class's initialization.

Override it for custom setup before the window is created
usually to
set additional window styles using SetWindowStyle() and
SetExtraStyle()."""
pass

def __init__(self, parent):
# Two stage creation (seehttp://wiki.wxpython.org/index.cgi/TwoStageCreation)
pre = wx.PreDialog()
self.PreCreate(pre)
get_resources().LoadOnDialog(pre, parent, "Dialog")
self.PostCreate(pre)

# create attributes for the named items in this container
self.wxID_YES = xrc.XRCCTRL(self, "wxID_YES")
self.wxID_NO = xrc.XRCCTRL(self, "wxID_NO")

class xrcMainFrame(wx.Frame):
def PreCreate(self, pre):
""" This function is called during the class's initialization.

Override it for custom setup before the window is created
usually to
set additional window styles using SetWindowStyle() and
SetExtraStyle()."""
pass

def __init__(self, parent):
# Two stage creation (seehttp://wiki.wxpython.org/index.cgi/TwoStageCreation)
pre = wx.PreFrame()
self.PreCreate(pre)
get_resources().LoadOnFrame(pre, parent, "MainFrame")
self.PostCreate(pre)

# create attributes for the named items in this container
self.button = xrc.XRCCTRL(self, "button")

# ------------------------ Resource data ----------------------

def __init_resources():
global __res
__res = xrc.EmptyXmlResource()

wx.FileSystem.AddHandler(wx.MemoryFSHandler())

sbs_test_xrc = '''\
<?xml version="1.0" ?><resource version="2.3.0.1" xmlns="http://www.wxwindows.org/wxxrc">
<object class="wxDialog" name="Dialog">
<style>wxDEFAULT_DIALOG_STYLE</style>
<title/>
<object class="wxFlexGridSizer">
<rows>2</rows>
<cols>2</cols>
<vgap>0</vgap>
<hgap>0</hgap>
<growablecols/>
<growablerows/>
<object class="sizeritem">
<option>1</option>
<flag>wxEXPAND</flag>
<border>5</border>
<object class="wxStdDialogButtonSizer">
<object class="button">
<flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
<border>5</border>
<!--
<object class="wxButton" name="wxID_OK">
<label>&amp;OK</label>
</object>
-->
<object class="wxButton" name="wxID_YES">
<label>&amp;Yes</label>
</object>
</object>
<object class="button">
<flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
<border>5</border>
<!--
<object class="wxButton" name="wxID_CANCEL">
<label>&amp;Cancel</label>
</object>
-->
<object class="wxButton" name="wxID_NO">
<label>&amp;No</label>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="wxFrame" name="MainFrame">
<style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
<size>500,300</size>
<title/>
<object class="wxButton" name="button">
<label>MyButton</label>
<default>0</default>
</object>
</object>
</resource>'''

wx.MemoryFSHandler.AddFile('XRC/sbs_test/sbs_test_xrc',
sbs_test_xrc)
__res.Load('memory:XRC/sbs_test/sbs_test_xrc')

Nicola,

I've never created a modal dialog like this. Instead, I follow the
wxPython in Action book examples (most of the time), which would do a
yes/no dialog like this:

<code>

dlg = wx.MessageDialog(None, 'Some Message', 'A Message Box',
wx.YES_NO | wx.QUESTION)
retCode = dlg.ShowModal()
if retCode == wx.ID_YES:
# do something
print 'yes'
else:
# do something else
print 'no'
dlg.Destroy()

</code>

And I agree with Rob...there is a wxPython user's group, which is a
more appropriate place to post these types of questions. The Python
group will help all they can though.

Mike
 
N

Nicola Musatti

Hallo, Mike.
First of all, thanks to both you and Rob for your answers. I now see
that the wxPython group would have been a better place to post to, all
the more so given the tight connection between the wxPython and
wxWidgets projects, of which at first I wasn't aware.

On Jan 3, 8:19 pm, (e-mail address removed) wrote:
[...]
I've never created a modal dialog like this. Instead, I follow the
wxPython in Action book examples (most of the time), which would do a
yes/no dialog like this:

<code>

dlg = wx.MessageDialog(None, 'Some Message', 'A Message Box',
wx.YES_NO | wx.QUESTION)
retCode = dlg.ShowModal()
if retCode == wx.ID_YES:
# do something
print 'yes'
else:
# do something else
print 'no'
dlg.Destroy()

</code>

Actually my example started out as something like

if wx.MessageBox(message="Some message", caption="Some caption",
style=wx.YES|wx.NO) == wx.YES:
pass

I had to change it because the actual message can become very long, so
I assembled a dialog with a scrollable text field. Maybe I'm expecting
to much of wxStdDialogButtonSizer, but I still feel that given that
both your method and mine above work straight away, it should provide
the same behaviour with Yes/No buttons as with OK/Cancel ones.

Cheers,
Nicola Musatti
 
K

kyosohma

Hallo, Mike.
First of all, thanks to both you and Rob for your answers. I now see
that the wxPython group would have been a better place to post to, all
the more so given the tight connection between the wxPython and
wxWidgets projects, of which at first I wasn't aware.

On Jan 3, 8:19 pm, (e-mail address removed) wrote:
[...]


I've never created a modal dialog like this. Instead, I follow the
wxPython in Action book examples (most of the time), which would do a
yes/no dialog like this:

dlg = wx.MessageDialog(None, 'Some Message', 'A Message Box',
wx.YES_NO | wx.QUESTION)
retCode = dlg.ShowModal()
if retCode == wx.ID_YES:
# do something
print 'yes'
else:
# do something else
print 'no'
dlg.Destroy()

Actually my example started out as something like

if wx.MessageBox(message="Some message", caption="Some caption",
style=wx.YES|wx.NO) == wx.YES:
pass

I had to change it because the actual message can become very long, so
I assembled a dialog with a scrollable text field. Maybe I'm expecting
to much of wxStdDialogButtonSizer, but I still feel that given that
both your method and mine above work straight away, it should provide
the same behaviour with Yes/No buttons as with OK/Cancel ones.

Cheers,
Nicola Musatti

Nicola,

I have sub-classed wx.Dialog to do my own custom modal dialogs as
well. You can use sizers and put whatever widgets you want onto it
that way. Just make sure that when you create the Yes/No buttons, you
give them the wx.ID_YES or wx.ID_NO ids, rather than -1 or wx.ID_ANY.

yesBtn = wx.Button(parent, wx.ID_YES, 'Yes')
noBtn = wx.Button(parent, wx.ID_NO, 'No')

Mike
 
N

Nicola Musatti

On Jan 4, 3:12 pm, (e-mail address removed) wrote:
[...]
I have sub-classed wx.Dialog to do my own custom modal dialogs as
well. You can use sizers and put whatever widgets you want onto it
that way. Just make sure that when you create the Yes/No buttons, you
give them the wx.ID_YES or wx.ID_NO ids, rather than -1 or wx.ID_ANY.

yesBtn = wx.Button(parent, wx.ID_YES, 'Yes')
noBtn = wx.Button(parent, wx.ID_NO, 'No')

As far as I understand this should be taken care of by the XRC/
wxStdDialogButtonSizer combination.

Anyway, I solved my problem by binding the following event handler to
both buttons:

def OnButton(self, event):
if self.IsModal():
self.EndModal(event.GetId())

By the way, my assumption above appears to be supported by the fact
that a call to ShowModal() on my dialog does return wx.ID_YES when I
press the Yes button. I'm still a bit puzzled, but right now I can't
afford to let it bother me too much.

Thanks for your help!

Cheers,
Nicola
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,085
Latest member
cryptooseoagencies

Latest Threads

Top