I'm trying to learn wxPython. Unfortunately when I came to China in Jan I had to leave the nice wxPython book in Canada because it was too heavy for my suitcase. So I humbly ask you to bear with my ignorance.

As practice (and because I have a practical use for it) I want to read in a textfile and display the text line by line. Much to my surprise & delight, the following program actually works!

''' TextFileDisp00.py
'''

import wx
import codecs

#-------------------
class TextFrame(wx.Frame):

    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, mysize)
        self.menubar = wx.MenuBar()
        self.file = wx.Menu()
        self.SetMenuBar(self.menubar)
        self.menubar.Append(self.file,'&File')
        self.openitem = self.file.Append(wx.ID_ANY,'&Open')
        self.Bind(wx.EVT_MENU,self.openevent,self.openitem)
        self.runitem = self.file.Append(wx.ID_ANY,'&Run')
        self.Bind(wx.EVT_MENU,self.runevent,self.runitem)
        self.exititem = self.file.Append(wx.ID_ANY,'E&xit')
        self.Bind(wx.EVT_MENU,self.exitevent,self.exititem)

        self.background = wx.Panel(self)
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.background, proportion=0, flag=wx.EXPAND)
        self.SetSizer(self.vbox)
        self.fileisopen = False
        self.Show()

    def openevent(self, event):
        filedialog = wx.FileDialog(self,
            message = 'Open text file',
            defaultDir = '.',
            defaultFile = 'TestTOC.txt',
            wildcard = 'Text file (*.txt;*.prn)| *.txt;*.prn',
            style = wx.OPEN)
        if filedialog.ShowModal() == wx.ID_OK:
            self.path = filedialog.GetPath()
            self.fileisopen = True

    def runevent(self, event):
        if not self.fileisopen:
            msgbox = wx.MessageDialog(self.background, message="No file is open!", style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
        else:
            myOK = True
            linenr = 0
            InFile = codecs.open(self.path, 'r')
            textline = InFile.readline()
            while textline <> '' and myOK:
                linenr += 1
                msg = "Line " + repr(linenr) + ": " + textline
                msgbox = wx.MessageDialog(self.background, message=msg, style=wx.OK+wx.CANCEL)
                if msgbox.ShowModal() == wx.ID_CANCEL:
                    myOK = False
                msgbox.Destroy()
                textline = InFile.readline()
            msg = "Finished, # lines = " + repr(linenr)
            msgbox = wx.MessageDialog(self.background, message=msg, style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
            InFile.close()
            self.Destroy()

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

#-------------------
''' Main application
'''

app = wx.App(redirect = False)
mywidth = 300
myheight = 150
mytitle = "Text file display"
frame = TextFrame(None, mytitle, (mywidth,myheight))
app.MainLoop()

I would appreciate the comments of experienced users about style and things I have not understood. I have a couple of specific questions as well:

1. I don't seem to understand sizers, and I can't make the background panel extend to the bottom of the app window.

2. I would like to display the text much bigger, i.e. in a (possibly multiline) textbox in which I could set font and font color & size. But I would still like to use a modal box, so I can press Enter to see the next line. How is this done?

Thanks for your help and understanding! Next time my questions might be smarter.

Recommended Answers

All 7 Replies

Corrected your code a little and it works just fine:

''' TextFileDisp00.py
'''

import wx
import codecs

#-------------------
class TextFrame(wx.Frame):

    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, mysize)
        self.menubar = wx.MenuBar()
        self.file = wx.Menu()
        self.SetMenuBar(self.menubar)
        self.menubar.Append(self.file,'&File')
        self.openitem = self.file.Append(wx.ID_ANY,'&Open')
        self.Bind(wx.EVT_MENU,self.openevent,self.openitem)
        self.runitem = self.file.Append(wx.ID_ANY,'&Run')
        self.Bind(wx.EVT_MENU,self.runevent,self.runitem)
        self.exititem = self.file.Append(wx.ID_ANY,'E&xit')
        self.Bind(wx.EVT_MENU,self.exitevent,self.exititem)

        self.background = wx.Panel(self)
        self.background.SetBackgroundColour("white")
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.background, proportion=1, flag=wx.EXPAND)  #!!!!
        self.SetSizer(self.vbox)
        self.fileisopen = False
        self.Show()

    def openevent(self, event):
        filedialog = wx.FileDialog(self,
            message = 'Open text file',
            defaultDir = '.',
            defaultFile = 'TestTOC.txt',
            wildcard = 'Textfile (.txt .prn)|*.txt;*.prn|All (.*)|*.*', #!!!!
            style = wx.OPEN)
        if filedialog.ShowModal() == wx.ID_OK:
            self.path = filedialog.GetPath()
            self.fileisopen = True

    def runevent(self, event):
        if not self.fileisopen:
            msgbox = wx.MessageDialog(self.background,
                message="No file is open!", style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
        else:
            myOK = True
            linenr = 0
            InFile = codecs.open(self.path, 'r')
            textline = InFile.readline()
            while textline <> '' and myOK:
                linenr += 1
                msg = "Line " + repr(linenr) + ": " + textline
                msgbox = wx.MessageDialog(self.background,
                    message=msg, style=wx.OK+wx.CANCEL)
                if msgbox.ShowModal() == wx.ID_CANCEL:
                    myOK = False
                msgbox.Destroy()
                textline = InFile.readline()
            msg = "Finished, # lines = " + repr(linenr)
            msgbox = wx.MessageDialog(self.background,
                message=msg, style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
            InFile.close()
            self.Destroy()

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

#-------------------
''' Main application
'''

app = wx.App(redirect = False)
mywidth = 300
myheight = 150
mytitle = "Text file display"
frame = TextFrame(None, mytitle, (mywidth,myheight))
app.MainLoop()

Line one of wx.AboutBox() has a larger font, maybe you can use that. See:
http://www.daniweb.com/forums/post901743-112.html

Sneekula, thanks for your reply! From your comments I conclude that a modal dialog is too limited for the kind of display I want. Here's a second try at displaying all lines of a file sequentially, using a text box instead. But it doesn't wait for me to press Enter, so all I see is the last line of the file. What to do?

import wx
import codecs

#-------------------
class TextFrame(wx.Frame):

    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, mysize)
        self.menubar = wx.MenuBar()
        self.file = wx.Menu()
        self.SetMenuBar(self.menubar)
        self.menubar.Append(self.file,'&File')
        self.openitem = self.file.Append(wx.ID_ANY,'&Open')
        self.Bind(wx.EVT_MENU,self.openevent,self.openitem)
        self.runitem = self.file.Append(wx.ID_ANY,'&Run')
        self.Bind(wx.EVT_MENU,self.runevent,self.runitem)
        self.exititem = self.file.Append(wx.ID_ANY,'E&xit')
        self.Bind(wx.EVT_MENU,self.exitevent,self.exititem)

        self.background = wx.Panel(self)
        self.background.SetBackgroundColour("white")

        self.textdisp = wx.TextCtrl(self.background, 100,
            style = wx.TE_READONLY | wx.TE_MULTILINE | wx.TE_PROCESS_ENTER)
        wx.EVT_TEXT_ENTER ( self.background, 100, self.handleEnter )

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.textdisp, proportion=1, border=0, flag=wx.EXPAND)
        self.background.SetSizer(self.vbox)
        self.fileisopen = False
        self.Show()

    def handleEnter(self, event):
        pass # ?? what to do?

    def openevent(self, event):
        filedialog = wx.FileDialog(self,
            message = 'Open text file',
            defaultDir = '.',
            defaultFile = 'TestTOC.txt',
            wildcard = 'Text file (*.txt;*.prn)| *.txt;*.prn',
            style = wx.OPEN)
        if filedialog.ShowModal() == wx.ID_OK:
            self.path = filedialog.GetPath()
            self.fileisopen = True

# Display the lines of the file sequentially. Wait for <Enter> between lines -- how??

    def runevent(self, event):
        if not self.fileisopen:
            msgbox = wx.MessageDialog(self.background, message="No file is open!", style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
        else:
            myOK = True
            linenr = 0
            InFile = codecs.open(self.path, 'r')
            textline = InFile.readline()
            while textline <> '' and myOK:
                linenr += 1
                textstr = "Line " + repr(linenr) + ": " + textline
                self.textdisp.SetValue(textstr) # ?? Now I want to wait for <Enter>

                textline = InFile.readline()
            msg = "Finished, # lines = " + repr(linenr)
            msgbox = wx.MessageDialog(self.background, message=msg, style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
            InFile.close()
            self.Destroy()

    def exitevent(self, event):
        self.Close(True)

#-------------------
''' Main application
'''
app = wx.App(redirect = False)
mywidth = 300
myheight = 150
mytitle = "Text file display"
frame = TextFrame(None, mytitle, (mywidth,myheight))
app.MainLoop()

If I can get this working, then I'll replace the TextCtrl by a RichTextCtrl (?) that will allow me to change font size etc., but first things first.

:'( It's VERY difficult to find the documentation I need on the Web. Is there a place where things like wx.TE_PROCESS_ENTER and wx.EVT_TEXT_ENTER are actually explained? I truly hate blundering around in the dark like this.

Thanks again for your help (and anyone else's who wants to)!

Excuse me! I'm really not clever yet with GUI programming, my apologies! I just realized that the behavior I want from the Enter key has nothing to do with the textbox display, which after all is just showing stuff out of the file. Here's a version that does what I want.

import wx
import codecs

#-------------------
class TextFrame(wx.Frame):

    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, mysize)
        self.menubar = wx.MenuBar()
        self.file = wx.Menu()
        self.SetMenuBar(self.menubar)
        self.menubar.Append(self.file,'&File')
        self.openitem = self.file.Append(wx.ID_ANY,'&Open')
        self.Bind(wx.EVT_MENU,self.openevent,self.openitem)
        self.runitem = self.file.Append(wx.ID_ANY,'&Run')
        self.Bind(wx.EVT_MENU,self.runevent,self.runitem)
        self.exititem = self.file.Append(wx.ID_ANY,'E&xit')
        self.Bind(wx.EVT_MENU,self.exitevent,self.exititem)

        self.background = wx.Panel(self)
        self.background.SetBackgroundColour("white")

        self.textdisp = wx.TextCtrl(self.background, 100,
            style = wx.TE_READONLY | wx.TE_MULTILINE)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.textdisp, proportion=1, border=0, flag=wx.EXPAND)
        self.background.SetSizer(self.vbox)
        self.fileisopen = False
        self.myOK = True
        self.Show()

    def openevent(self, event):
        filedialog = wx.FileDialog(self,
            message = 'Open text file',
            defaultDir = '.',
            defaultFile = 'TestTOC.txt',
            wildcard = 'Text file (*.txt;*.prn)| *.txt;*.prn',
            style = wx.OPEN)
        if filedialog.ShowModal() == wx.ID_OK:
            self.path = filedialog.GetPath()
            self.fileisopen = True

# Display the lines of the file sequentially. Wait for <Enter> between lines by posting a modal message box.

    def runevent(self, event):
        if not self.fileisopen:
            msgbox = wx.MessageDialog(self.background, message="No file is open!", style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Close(True)
        else:
            self.myOK = True
            linenr = 0
            InFile = codecs.open(self.path, 'r')
            textline = InFile.readline()
            while textline <> '' and self.myOK:
                linenr += 1
                textstr = "Line " + repr(linenr) + ": " + textline
                self.textdisp.SetValue(textstr)

                msg = 'Show next line?'
                msgbox = wx.MessageDialog(self.background, message=msg, style=wx.YES_NO)
                if msgbox.ShowModal() == wx.ID_NO:
                    self.myOK = False
                msgbox.Close(True)

                textline = InFile.readline()
            msg = "Finished, # lines = " + repr(linenr)
            msgbox = wx.MessageDialog(self.background, message=msg, style=wx.OK)
            if msgbox.ShowModal() == wx.ID_OK:
                msgbox.Destroy()
            InFile.close()
            self.Destroy()

    def exitevent(self, event):
#        self.Destroy()
        self.Close(True)

#-------------------
''' Main application
'''

app = wx.App(redirect = False)
mywidth = 300
myheight = 150
mytitle = "Text file display"
frame = TextFrame(None, mytitle, (mywidth,myheight))
app.MainLoop()

Now every line of the file displays separately, and I can continue viewing by pressing Enter or quit by choosing NO.

Ideally I would want my message box to be invisible and just respond to Enter to continue, and to some other key, say Esc, to pause, resume at a different line, open another file, or quit. Are there any invisible message boxes on the market?

My deep apologies if you read the previous message uselessly. I would have edited or deleted it but didn't know how.

I guess the person who developed wxPython as a wrapper for wxWindows (written in C++) didn't do much about documentation, leaving that to his book he published later. The rub was that the editor of the book introduced a lot of errors and made the book not very friendly to use.

I always use the wxPython api when i want to find something out, its a very very useful skill to be able to do that, because of the lack of documentation you really have to try and use what you do have.

I once wrote a small explanation on wxTextCtrl, ill attach it to the post, its a pdf. One bit of it goes over the side of the page, sorry bout that :P

Hope it helps

Sneekula, thanks for your help. I feel like my WxPython expertise has gone up from level 0 to at least 0.1. And I am reading the very clear GUI tutorials on this site, thanks for these too.

paulthom, thanks for your note. I learned most of the little I know about wxpython from your very practical tutorials on www.wxpython.webs.com/. The down-home language is entertaining and explicit. I like your layout on www.thecodecookie.com also, and am looking forward to seeing more. Thanks again!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.