views:

107

answers:

2

okay code:

#!/usr/bin/python

import wx
import sys

class XPinst(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)
    def OnInit(self):
        frame = wx.Frame(None, -1, title='Redirect Test', size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)
        panel = wx.Panel(frame, -1)
        log = wx.TextCtrl(panel, -1, size=(500,400), style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
        redir=RedirectText(log)
        sys.stdout=redir
        print 'test'
        frame.Show()
        return True

class RedirectText:
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl
    def write(self,string):
        self.out.WriteText(string)

app = XPinst()
app.MainLoop()

added:

class MyFrame(wx.Frame)
    def __init__(self, parent, id, title, size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE):
        wx.Frame.__init__(self, parent, id, title, size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)

replaced:

frame = wx.Frame(None, -1, title='Redirect Test', size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)

with:

frame = MyFrame(None, -1, title='Redirect Test', size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)

Now, it doesn't run...

I want to be able to call the MyFrame constructor more than once in my code passing different arguments

I tried many things...

instanciating MyFrame with all arguments instanciating myFrame and with all, but default arguments
constructor method signature with all arguments
constructor method signature with all, but default arguments
calling parent constructor method with all arguments
calling parent constructor method with all, but default arguments

plus the tutorial http://zetcode.com/wxpython/ mentions a method where the number of default and optional arguments are different! (what's the difference?)

UDPATE:

"it has seven parameters. The first parameter does not have a default value. The other six parameters do have. Those four parameters are optional. The first three are mandatory." - http://zetcode.com/wxpython/firststeps/

UPDATE 2:

With semi-colon correction, i have just tried:

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title, size, style):
        wx.Frame.__init__(self, parent, id, title, size, style)
  • I tell what arguments are going in (second line)
  • I call with the arguments that went in (third line)

UPDATE 3:

the full error message is:

Traceback (most recent call last):
  File "test.py", line 29, in <module>
    app = XPinst()
  File "test.py", line 8, in __init__
    wx.App.__init__(self, redirect, filename)
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 7978, in __init__
    self._BootstrapApp()
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 7552, in _BootstrapApp
    return _core_.PyApp__BootstrapApp(*args, **kwargs)
  File "test.py", line 10, in OnInit
    frame = MyFrame(None, -1, title='Redirect Test', size=(620,450), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)
  File "test.py", line 21, in __init__
    wx.Frame.__init__(self, parent, id, title, size, style)
  File "/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode/wx/_windows.py", line 497, in __init__
    _windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))
TypeError: Expected a 2-tuple of integers or a wxSize object.

Why didn't it work?

+1  A: 

Runs fine for me with one tweak; you're missing a colon after your subclassed wx.Frame statement.

One comment; if you're just "passing through" arguments to the parent initalizer, use *args and/or **kwargs to save some typing.

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

If you want to modify or add particular arguments, you could just modify the dictionary kwargs, e.g.

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        kwargs['size']=(1000,200)
        wx.Frame.__init__(self, *args, **kwargs)

On running files for development:

Run scripts you're working on in the console, with python, not pythonw. The latter will just quit when it sees errors and send them off to lala-land.

N:\Code>pythonw wxso.pyw

N:\Code>rem nothing happened.

N:\Code>python wxso.pyw
  File "wxso.pyw", line 24
    class MyFrame(wx.Frame)
                          ^
SyntaxError: invalid syntax

N:\Code>

On keyword arguments:

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title, size, style):
        #wx.Frame.__init__(self, parent, id, title, size, style) # broken
        # equivalent to:
        #wx.Frame.__init__(self, parent, id=id, title=title, pos=size, size=style)

        # the below works.
        wx.Frame.__init__(self, parent, id, title=title, size=size, style=style)

When you pass arguments as keywords e.g. title, size, style, their position to the function that actually takes them could be totally different. The first line there assigns "size" to whatever is the fifth argument in the wx.Frame.__init__ function, which is probably not size. It could be the 100th argument, but you use the keyword to tell it where to go.

"Optional" is somewhat vague; keyword arguments supply defaults, but the default may be inappropriate.

Nick T
thank you very much!
Delirium tremens
+1  A: 

You're missing the pos from your Frame.__init__ call. Here's the prototype from the docs:

Frame.__init__(self, parent, id, title, pos, size, style, name)

So basically the error is saying that it expects size to be a 2-tuple or wxSize object, and what you were passing doesn't match that. I'm guessing that this crept in when you removed size= from the constructor here:

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title, size, style):
        wx.Frame.__init__(self, parent, id, title, size, style)

Edit: Either of the following would be fine

        wx.Frame.__init__(self, parent, id, title, size=size, style=style)
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size, style)

but by omitting the keywords from the arguments, your call was being handled in the order passed, as

        wx.Frame.__init__(self, parent, id, title, pos=size, size=style)
Peter Gibson
Didn't I cover this? :P He didn't remove size, it's more that he removed the keyword arguments and replaced them with positional arguments, which effectively did `wx.Frame.__init__(self, parent, id=id, title=title, pos=size, size=style)`
Nick T
Ah, right - should have read your whole answer - I got the impression that the problem wasn't yet solved.
Peter Gibson
Nick T