[wxPython] clinical computing

Hello. I'm an academic physician and an amateur programmer
new to Python. From what I have seen so far, Python appears
to be IDEAL for evolving many of the tools sorely needed in
the clinical setting. At the moment, however, I am
struggling with how best to create a user interface. (Not
that Swing was any easier, but at least with Swing there
are a plethora of tutorials and examples available.) This
mailing list looks like a good place to ask a few questions
to help get me started.

I have lots of questions, but I'll just start out with a
simple widget. Clinical calculations frequently require the
user to enter a small decimal number into a text field.
Below is my first attempt to create a modified wxTextCtrl
that allows only numeric input, called wxDecimalField. The
following questions refer to the code below.

1. Is there a wxDecimalField equivalent already available
somewhere?

2. When subclassing a wxControl, is the convention to
prefix the class name with 'wx' (wxDecimalField) or not
(DecimalField)?

3. It appears that my OnChar() method overrides the OnChar
method of the parent wxTextCtrl, but this cannot be the
case because:
  a. it does not work without the EVT_CHAR macro in
__init__
  b. EVT_CHAR(self, self.Spam) and def Spam(self, event)
works just as well
  c. wxTextCtrl.OnChar(self, self, event) is not found
Am I right about my OnChar method not REALLY overriding the
method in the wxTextCtrl? If I am wrong, how does this
work?

4. What is event.Skip() actually doing in this code? It
seems to work fine, but I am not sure I understand why. For
example, in my OnChar() method, I first tried to call
wxText.Ctrl.OnChar(self, self, event) to process the
accepted keystroke (which did not work).

5. Instead of capturing keystrokes, should I be using
wxValidator, wxTextValidator or wxPyValidator? If so, how
would that work?

6. I have no C++ experience. Will I be able to use wxPython
effectively without learning C++ to understanding
wxWindows?

···

=======
from wxPython.wx import *

class TestApp(wxApp):
    def OnInit(self):
        frame = MyFrame(NULL, -1, "Decimal Field Test")
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

class MyFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition,
                         wxSize(300, 150))
        panel = wxPanel(self, -1)
        df1 = DecimalField(panel, 10, "",
                           wxPoint(20, 10),
                           wxSize(50, 20))

    def OnCloseMe(self, event):
        self.Close(true)

    def OnCloseWindow(self, event):
        self.Destroy()

class wxDecimalField(wxTextCtrl):
    def __init__(self, parent, ID, title,
                 position, size):
        wxTextCtrl.__init__(self, parent, ID, title,
                            position, size)
        EVT_CHAR(self, self.OnChar)
        EVT_KILL_FOCUS(self, self.Finish)

    def OnChar(self, event):
        key = event.GetKeyCode()
        if key > 47 and key < 58:
            event.Skip()
        elif key == 46:
            if '.' not in self.GetValue():
                if self.GetInsertionPoint() == 0:
                    self.WriteText("0")
                event.Skip()
        elif key == 8 or key == 127:
            event.Skip()
        elif key == 316 or key == 318:
            event.Skip()

    def Finish(self, event):
        # replace with code to handle/use this value
        print self.GetValue()
        event.Skip()

app = TestApp(0)
app.MainLoop()

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices
http://auctions.yahoo.com/

Donnal Walter wrote:

I can't provide much help with your other questions, but I thougth I
might as well cover this one.

6. I have no C++ experience. Will I be able to use wxPython
effectively without learning C++ to understanding
wxWindows?

Yes. I also have no C++ experience. It took a little effort for me to
figure out how to read the docs and translate them from C++ to Python,
but after I got rolling, it's been pretty easy. There are frequently pst
sot this list from someone saying that they are having hard time getting
started, and that they intend to write a new doc or tutorial so that
others won't have the same problems. It hasn't happened yet, and I
suspect part of that is because it turns out that once you get rolling,
it really isn't very hard.

Good luck,

-Chris

Note: you may want to take a look at wxDesigner
(http://www.roebling.de/). As it happens it is written by a physician as
well.

···

--
Christopher Barker,
Ph.D.
ChrisHBarker@home.net --- --- ---
http://members.home.net/barkerlohmann ---@@ -----@@ -----@@
                                   ------@@@ ------@@@ ------@@@
Oil Spill Modeling ------ @ ------ @ ------ @
Water Resources Engineering ------- --------- --------
Coastal and Fluvial Hydrodynamics --------------------------------------
------------------------------------------------------------------------

Hello Donnal,

Tuesday, May 22, 2001, 8:24:41 PM, you wrote:

[...]

1. Is there a wxDecimalField equivalent already available
somewhere?

AFAIK no

2. When subclassing a wxControl, is the convention to
prefix the class name with 'wx' (wxDecimalField) or not
(DecimalField)?

IMHO wx is kind of C namespace. Python has real modules.

3. It appears that my OnChar() method overrides the OnChar
method of the parent wxTextCtrl, but this cannot be the
case because:
  a. it does not work without the EVT_CHAR macro in
__init__
  b. EVT_CHAR(self, self.Spam) and def Spam(self, event)
works just as well
  c. wxTextCtrl.OnChar(self, self, event) is not found
Am I right about my OnChar method not REALLY overriding the
method in the wxTextCtrl? If I am wrong, how does this
work?

OnChar is not magic name. It depends on EVT_CHAR to bind it.

4. What is event.Skip() actually doing in this code? It
seems to work fine, but I am not sure I understand why. For
example, in my OnChar() method, I first tried to call
wxText.Ctrl.OnChar(self, self, event) to process the
accepted keystroke (which did not work).

event.Skip() means to proceed with next handler for this event.

5. Instead of capturing keystrokes, should I be using
wxValidator, wxTextValidator or wxPyValidator? If so, how
would that work?

Look in demo for validators demo.

···

--
regards,
Niki Spahiev

Hi Donnal,

Hello. I'm an academic physician and an amateur programmer
new to Python. From what I have seen so far, Python appears
to be IDEAL for evolving many of the tools sorely needed in
the clinical setting. At the moment, however, I am
struggling with how best to create a user interface. (Not
that Swing was any easier, but at least with Swing there
are a plethora of tutorials and examples available.)

I'd agree that wxPython is an *ideal* tool for developing UI-intensive systems. It takes a bit of learning to get familiar with it, but a bunch of us are working on writing more documentation to help make this process easier...

This mailing list looks like a good place to ask a few questions
to help get me started.

Sure -- ask away. I'll answer the questions I can...

1. Is there a wxDecimalField equivalent already available
somewhere?

Not that I know of, I'm afraid. That's a good idea, though -- we should probably see if we can't set up a "contributed code" section on the web site (if there isn't one already -- I can't see one at first glance, but I might have missed it). I've got my own "snippets" database where I paste in commonly used bits of code, and I'd be keen to see this extended to something more public and with wider contributions. Kind of like a "vaults of parnassis" or "CPAN", but smaller and specifically for wxPython...

2. When subclassing a wxControl, is the convention to
prefix the class name with 'wx' (wxDecimalField) or not
(DecimalField)?

Based on the code I've seen in various places, but I think the convention is to *not* put 'wx' in front of your own class names. That way, you can easily distinguish between built-in wxPython classes and your own ones...others might beg to differ, though...

3. It appears that my OnChar() method overrides the OnChar
method of the parent wxTextCtrl, but this cannot be the
case because:
  a. it does not work without the EVT_CHAR macro in
__init__
  b. EVT_CHAR(self, self.Spam) and def Spam(self, event)
works just as well
  c. wxTextCtrl.OnChar(self, self, event) is not found
Am I right about my OnChar method not REALLY overriding the
method in the wxTextCtrl? If I am wrong, how does this
work?

All wxPython objects are merely "wrappers" around C++ objects implemented by wxWindows itself. The default wxTextCtrl.OnChar method is implemented in C++ -- you can't override C++ objects as such, but what you can do is write your own "on char" handler and tell wxPython to use that rather than the default. That's done using your 'b' option above: you define your own handler, and tell wxPython to use it by calling EVT_CHAR.

Mind you, I suspect you might be better off using a wxValidator to validate the user's keystrokes. Take a look at the wxPython demo (under Miscellaneous -> wxValidator) for an example of how this is done...

4. What is event.Skip() actually doing in this code? It
seems to work fine, but I am not sure I understand why. For
example, in my OnChar() method, I first tried to call
wxText.Ctrl.OnChar(self, self, event) to process the
accepted keystroke (which did not work).

event.Skip() is, in my opinion, misleadingly named. You would think that event.Skip() would tell wxPython not to process the event -- but in fact the opposite happens. event.Skip() tells wxPython to pass the event on to the next event handler in the chain -- which has the effect of processing the event as if you'd never intercepted it in the first place...

6. I have no C++ experience. Will I be able to use wxPython
effectively without learning C++ to understanding
wxWindows?

Absolutely! If you take a look at the wxPython web site (http://www.wxpython.org), you'll see under "Community" a section called "wxPyWiki". That link will take you to the "wiki" (collaborative web site) which we're using for storing the latest FAQ and the user documentation we're working on. The docs are nowhere near ready, but if you go to the "Frequently Asked Questions" section, you'll find under "Getting Started" a question about reading the C++ based reference docs. Hopefully the little mini-HOWTO I wrote there will make it easier to figure out the C++ docs...

Oh, and please let me know if you find any of what I wrote confusing or still have problems afterwards. We are kind of stuck with the C++-oriented reference docs, because wxPython is built on top of wxWindows and wxWindows itself is all written in C++...

Good luck!

  - Erik.

For starting up in wxPython:

Run the demo. Read the demo code. AND READ main.py FROM THE DEMO.

If you use grids, read grid.i, and be aware that the grid documentation
in wxWindows help is way, way out of date.

I use the OO-Browser on top of emacs to browse the classes of both
wxPython and wxWindows. Very, very useful to have some kind of class
browser. Even if you don't know C++, if you want to know how a call
should be made, it helps to look at the C++ interface. There are also
useful comments in there.

The oo-browser sez:

       Bob Weiner designed and implemented the OO-Browser.
    BeOpen.com develops and maintains it for commercial use.
         www.beopen.com <info@beopen.com>

Have fun!
Patricia

···

--
Patricia J. Hawkins
Hawkins Internet Applications, LLC

Chris, Niki, Erick, and Patricia:

Thank you, everyone, for the warm welcome and the extremely
helpful responses. I had previously looked at the demo that
comes with the wxPython distribution, but somehow I missed
the wxPyValidator demo. I'll be experimenting with it more
today. The wxPyWiki has a lot of material that will be
useful as well. I will definitely take a look at
wxDesigner. Probably I'll wade in a little deeper on my own
first, just because I like to understand the nuts and bolts
(as far as possible), but in the long run wxDesigner might
speed things up a lot. I couldn't get www.beopen.com to
respond last night or this morning (I get BChosting
instead), but I'll keep trying.

Thanks again,
Donnal

···

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices
http://auctions.yahoo.com/

This question almost certainly involves Python syntax
rather than wx, but since it follows on my questions from
yesterday, I'll ask it here again. Thanks in advance. In
the following code:

class DecimalField(wxTextCtrl):
    def __init__(self, parent, ID, title,
                 position, size):
        wxTextCtrl.__init__(self, parent, ID, title,
                            position, size)
        EVT_CHAR(self, self.OnChar)

    def OnChar(self, event):
        key = event.GetKeyCode()
        # test for numeric character keys
        if key > 47 and key < 58:
            event.Skip()
        # test for period (decimal point)
        elif key == 46:
            if '.' not in self.GetValue():
                if self.GetInsertionPoint() == 0:
                    # add 0 before leading decimal point
                    self.WriteText("0")
                event.Skip()
        # test for <Backspace> and <Delete>
        elif key == 8 or key == 127:
            event.Skip()
        # test for <left arrow> and <right arrow>
        elif key == 316 or key == 318:
            event.Skip()
        else:
            print "not accepted"

I had not previously had an 'else' statement at the end of
the OnChar def, but when I added it for debugging purposes,
I noticed the follow behavior. The numeric, backspace,
delete, and arrow keys work as expected, being processed by
the wxTextCtrl and NOT printing the "not accepted" message
to the console. But the decimal (period) key is processed
as expected *except* that it *does* print the "not
accepted" message as well. All other key strokes do nothing
except print "not accepted" to the console. Is there
something about my nested 'if' statements for the decimal
key that I am not understanding?

···

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices
http://auctions.yahoo.com/

But the decimal (period) key is processed
as expected *except* that it *does* print the "not
accepted" message as well. All other key strokes do nothing
except print "not accepted" to the console. Is there
something about my nested 'if' statements for the decimal
key that I am not understanding?

No, they look fine. My guess would be that there is another event being
generated with a different key code. Try doing this instead to see what
keycode is being rejected.

        else:
            print key, "not accepted"

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Thank you, Robin. When I first started working on this class I simply put
'print key' at the beginning of the OnChar def to see what events were being
captured and '.' gave me only 46. Now I get a single event for every
keystroke, except '.' gives (340, 46), '-' gives (337, 61) and '+' gives me
(339, 45). It looks like somehow I have inadvertently changed my keyboard
mapping (win2k). I'll have to figure out how to restore it. Thanks for the suggestion.

···

--- Robin Dunn <robin@alldunn.com> wrote:

> But the decimal (period) key is processed
> as expected *except* that it *does* print the "not
> accepted" message as well. All other key strokes do nothing
> except print "not accepted" to the console. Is there
> something about my nested 'if' statements for the decimal
> key that I am not understanding?

No, they look fine. My guess would be that there is another event being
generated with a different key code. Try doing this instead to see what
keycode is being rejected.

        else:
            print key, "not accepted"

=====
Donnal Walter
Arkansas Children's Hospital

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices

Thank you, Robin. When I first started working on this class I simply put
'print key' at the beginning of the OnChar def to see what events were

being

captured and '.' gave me only 46. Now I get a single event for every
keystroke, except '.' gives (340, 46), '-' gives (337, 61) and '+' gives

me

(339, 45). It looks like somehow I have inadvertently changed my keyboard
mapping (win2k). I'll have to figure out how to restore it. Thanks for the

suggestion.

On the Numeric Keypad, right? I think those extra values are WXK_DECIMAL,
WXK_SUBTRACT and WXK_ADD.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!