0

I am learning to use wxPython to build a dialogue based program.

I tried following code (simply copied from wxPython Demo):

import  wx

#---------------------------------------------------------------------------

class TestPanel(wx.Panel):
    def __init__(self, parent, log):
        self.log = log
        wx.Panel.__init__(self, parent, -1)

        b = wx.Button(self, -1, "Create and Show a DirDialog", (50,50))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)


    def OnButton(self, evt):
        # In this case we include a "New directory" button. 
        dlg = wx.DirDialog(self, "Choose a directory:",
                          style=wx.DD_DEFAULT_STYLE
                           #| wx.DD_DIR_MUST_EXIST
                           #| wx.DD_CHANGE_DIR
                           )

        # If the user selects OK, then we process the dialog's data.
        # This is done by getting the path data from the dialog - BEFORE
        # we destroy it. 
        if dlg.ShowModal() == wx.ID_OK:
            self.log.WriteText('You selected: %s\n' % dlg.GetPath())

        # Only destroy a dialog after you're done with it.
        dlg.Destroy()


#---------------------------------------------------------------------------


def runTest(frame, nb, log):
    win = TestPanel(nb, log)
    return win


#---------------------------------------------------------------------------




overview = """\
This class represents the directory chooser dialog.  It is used when all you
need from the user is the name of a directory. Data is retrieved via utility
methods; see the <code>DirDialog</code> documentation for specifics.
"""


if __name__ == '__main__':
    import sys,os
    import run
    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])

I ran above code both in Python IDLE and Apatana Studio 3. Here is what I got.

In Python IDLE, I've got:

IDLE Subprocess: no IP port passed in sys.argv.

And in Apatana Studio 3, I've got:

Traceback (most recent call last):
File "C:\Users\User\My Documents\Aptana Studio 3 Workspace\Test Dialogue\main.py", line 61, in import run ImportError: No module named run

May I know what am I wrong? Thanks a lot. :)

ChangeMyName
  • 7,018
  • 14
  • 56
  • 93

1 Answers1

1

The ImportError is the Python interpreter (the program that runs your Python code) letting you know it cannot find the module (.py file) you are trying to import. Specifically, the error is saying it cannot find the module "run" which you have asked it to import on line 61.

When you do an import in Python, the interpreter searches a bunch of places for the module. One of those is the current directory, and the rest are standard places like where Python libraries are installed. This page has some info about it: http://docs.python.org/2/tutorial/modules.html#the-module-search-path. You'll actually get the same ImportError if you run the program from the command line. It's a Python error, not an Apatana Studio 3 error.

So if you copy "run.py" into the directory with your Python file, the Python interpreter will be able to easily find it when you asks it to import. Another way is to leave the run.py module where it is and change the sys.path at runtime, or add the module location to the PYTHONPATH variable (see link above for more info).

The run.py module isn't needed for what you are trying to achieve though. Here's an example of your code without the run.py module being imported. I'll warn that I'm new to wxPython myself so there may be better ways to do it ;-)

import  wx

# This Log class is copied from the run module
class Log(object):
    def WriteText(self, text):
        if text[-1:] == '\n':
            text = text[:-1]
        wx.LogMessage(text)
    write = WriteText


class TestPanel(wx.Panel):
    def __init__(self, parent, log):
        self.log = Log()
        wx.Panel.__init__(self, parent, -1)

        b = wx.Button(self, -1, "Create and Show a DirDialog", (50,50))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)


    def OnButton(self, evt):
        # In this case we include a "New directory" button. 
        dlg = wx.DirDialog(self, "Choose a directory:",
                          style=wx.DD_DEFAULT_STYLE
                           #| wx.DD_DIR_MUST_EXIST
                           #| wx.DD_CHANGE_DIR
                           )

        # If the user selects OK, then we process the dialog's data.
        # This is done by getting the path data from the dialog - BEFORE
        # we destroy it. 
        if dlg.ShowModal() == wx.ID_OK:
            self.log.WriteText('You selected: %s\n' % dlg.GetPath())

        # Only destroy a dialog after you're done with it.
        dlg.Destroy()


class Frame ( wx.Frame ):
    def __init__( self, parent ):
        wx.Frame.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size(300, 150))

        panel = TestPanel(self, -1)



class App(wx.App):

    def OnInit(self):
        self.frame = Frame(parent=None)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

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

I'm not sure what's happening with the error in IDLE though. That's weird!

Ben
  • 2,143
  • 2
  • 19
  • 27
  • Hi, Ben. Thanks a lot for the very detailed answer. It is really helpful. If I may ask a further question: what is the `log` in the constructor of class `TestPanel`? When I run the code, after I select a directory, following error pops up: `Traceback (most recent call last): File "P:/Project Backups/Python Practice/Examples/Demo_Panel2.py", line 25, in OnButton self.log.WriteText('You selected:' % dlg.GetPath()) AttributeError: 'int' object has no attribute 'WriteText' `. I think this error is pointing to `log`. Thank you very much. – ChangeMyName Dec 18 '13 at 16:07
  • This code is copied from the wxpython demo code for DirDialog the log is used to display output in the demo. You can comment out any references to log. – Yoriz Dec 18 '13 at 19:15
  • Excellent sleuthing! The run.py module also contained a Log class for showing you the selection you made. As Yoriz said you can just remove the references to log. I chose to add the log class to the example code above so you can see how that might fit in too. It's copied from run.py but I changed the class to be a "new style" class rather than an old one (see http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python) and changed a line in TestPanel from self.log = log to self.log = Log() – Ben Dec 18 '13 at 23:20