Google Answers Logo
View Question
 
Q: Need a Python program using Tkinter ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: Need a Python program using Tkinter
Category: Computers > Programming
Asked by: donkan-ga
List Price: $7.00
Posted: 08 Dec 2002 01:37 PST
Expires: 07 Jan 2003 01:37 PST
Question ID: 121280
I've downloaded Python 2.2.2 for Windows and have started to learn
Python using IDLE. My eventual goal is to create some simple programs
that use Tkinter, and that I can put on my Win98 desktop to use when I
need them. I'd like someone to create an example of the kind of thing
I am after:

I have a file, phone.txt at C:\My Documents\phone.txt ., with about
100 lines containing names, phone numbers, and notes. The file has one
line for each contact, e.g.,

Mister Rain (Mist'er Rain) (sprinkler repair) 555-1190
McCully Betty at WebWare 678-555-8843 (she's there Tu-F 9-4:30, M 9-1,
cell phone off)

When I had a shell account, I kept phone.txt there and found it very
useful to search it using grep. I'd enter, for example, "grep -i
repair" and be shown all the lines that have "repair" or "Repair" in
them. This is what I'd like the Python program to do, the equivalent
of searching phone.txt with grep -i. And do it within a TKinter GUI
that I can call by clicking on an icon on my desktop.

I hope this request is clear.
Answer  
Subject: Re: Need a Python program using Tkinter
Answered By: leapinglizard-ga on 10 Dec 2002 16:57 PST
Rated:5 out of 5 stars
 
Below is a script called grepper.py that I wrote to your
specifications. You'll notice that in the second line of the script, I
assign a string value to the variable read_from_file. This value,
which you should feel free to modify, is the name of the file that
grepper.py will initially attempt to open.

At launch, the top pane of the application window shows the initial
file name. In the upper right corner is the Open button, which you can
use at any time to select a new file.

The middle pane consists of a box where you can enter a search string.
This string will be interpreted as a case-insensitive regular
expression and applied to every line of the opened file. Don't worry
if you're not familiar with the special syntax of regular expressions;
plain strings such as "repair" and "body shop" will be interpreted
literally.

As soon as you press the Enter key, grepper.py starts searching
through the contents of the file. This may take a while in the case of
novels and other long documents. Note that if the search string is
empty, all lines will be displayed.

The bottom pane shows the results of your search. If grepper.py was
unable to open the specified file, it displays an error message.
Otherwise, those lines that matched the regular expression are
displayed, along with the respective line numbers in gray, and with
every matching substring in red.

Pressing the Escape key causes the application to quit.
Triple-clicking in the search box selects the entire string; then, you
can use Backspace to immediately clear the box, or just start typing
to replace the string.

Code follows. As you know, Python is sensitive to indentation, so I've
made the lines extra-short in order to avoid spurious line breaks.


#==begin grepper.py
read_from_file = 'C:\My Documents\phone.txt'

import sys, os, string, re
from Tkinter import *
from tkFileDialog import *

class Grepper:
    def __init__(self):
        self.fname = read_from_file
        self.root = Tk()
        self.root.title('grepper.py')
        self.root.bind('<KeyPress>', self.key_press)
        root_frame = Frame(self.root, bg='white')
        root_frame.pack(expand=YES, fill=BOTH)

        top_frame = Frame(root_frame, bg='white')
        top_frame.pack(side=TOP, expand=NO, fill=X)
        self.fname_label = Label(top_frame, text=self.fname,
            fg='dark blue', bg='white',
            font=('helvetica', 12, 'normal'))
        self.fname_label.pack(side=LEFT, expand=YES, fill=X)
        self.open_button = Button(top_frame, text='Open',
            command=self.open, bg='antiquewhite',
            font=('helvetica', 12, 'bold'))
        self.open_button.pack(side=RIGHT, expand=NO)

        regex_frame = Frame(root_frame, bg='white')
        self.regex_entry = Entry(regex_frame, width = 60,
            bg='cornsilk', fg='dark red',
            font=('helvetica', 12, 'bold'))
        self.regex_entry.pack(side=LEFT, expand=YES, fill=X)
        self.regex_entry.bind('<KeyPress>', self.key_press)

        text_frame = Frame(root_frame, bg='white')
        text_frame.pack(side=BOTTOM, expand=YES, fill=Y)
        regex_frame.pack(side=BOTTOM, expand=NO, fill=X)
        self.lines_text = Text(text_frame, fg='black', bg='white',
            width=80, height=20, font=('courier', 10, 'normal'))
        self.lines_text.pack(side=LEFT, expand=YES, fill=BOTH)
        self.lines_y_scrollbar = Scrollbar(text_frame,
            orient=VERTICAL, command=self.lines_text.yview)
        self.lines_text.configure(
            yscrollcommand=self.lines_y_scrollbar.set)
        self.lines_y_scrollbar.pack(side=RIGHT, expand=YES, fill=Y)
        self.lines_text.tag_config('match', foreground='dark red',
            background='white')
        self.lines_text.tag_config('bold', font=('helvetica', 12,
            'bold'))
        self.lines_text.tag_config('number', foreground='gray')
        self.lines_text.tag_config('error', foreground='red')
        self.lines_text.configure(state=DISABLED)

        self.ctrlRE = re.compile('\\r')
        self.open(0)
        self.grep()
        self.root.mainloop()

    def key_press(self, event):
        keysym = event.keysym.lower()
        if keysym in ['escape']:
            self.root.quit()
        elif keysym in ['enter', 'return']:
            self.grep()
    def open(self, ask=1):
        if ask:
            self.fname = askopenfilename(initialdir=self.open_dir)
        self.open_dir = os.path.split(self.fname)[0]
        self.fname_label.configure(text=self.fname)
        if os.path.isfile(self.fname):
            self.lines = open(self.fname).readlines()
        self.grep()

    def clear(self):
        self.regex_entry.configure(text='')
        self.grep()

    def grep(self):
        self.lines_text.configure(state=NORMAL)
        self.lines_text.delete('1.0', END)
        if not os.path.isfile(self.fname):
            self.lines_text.insert(END, 'Error: ', 'error',
                self.fname, 'bold', ' is not a file', 'error')
            self.lines_text.configure(state=DISABLED)
            return
        self.lineRE = re.compile(self.regex_entry.get(),
            re.IGNORECASE)
        blank = 0
        if not self.regex_entry.get().split():
            blank = 1
        i = 0
        for line in self.lines:
            i = i+1
            line = self.ctrlRE.sub('', line)
            findall = self.lineRE.findall(line)
            if not findall:
                continue
            self.lines_text.insert(END, '%4d: ' % i, 'number')
            if blank:
                self.lines_text.insert(END, line)
                continue
            split = self.lineRE.split(line)
            for j in range(len(findall)):
                self.lines_text.insert(END, split[j])
                self.lines_text.insert(END, findall[j], 'match')
            self.lines_text.insert(END, split[-1])
        self.lines_text.configure(state=DISABLED)

Grepper()

#==end grepper.py


I tested this script using python-2.2.1 and tk-8.3.3 under Linux, but
it should work just fine in Windows. The only possible exception I
foresee is that the rules of your window manager are slightly
different from mine. For example, you might have to double-click and
not triple-click in the search box in order to select the entire
string.

If you have trouble running the script, please let me know so that I
have a chance to meet your needs before you assign a rating.

Cheers,

leapinglizard

Request for Answer Clarification by donkan-ga on 03 Feb 2003 16:37 PST
The script is terrific, as I said, but I've realized that there is one
defect. When I run it, I'd like the focus to be in the search box,
ready to go.

Clarification of Answer by leapinglizard-ga on 07 Feb 2003 00:07 PST
No problem. Change the last two lines of the __init__ function so that
they look like this:

        self.regex_entry.focus_set()
        self.root.mainloop()

You must make sure that all lines in this block are indented with
exactly the same  number of tabs and spaces, or else you'll get a
syntax error. I'm glad you've gained some benefit from my script. I'm
very fond of Python myself, and I use it all the time to write
labor-saving little applications such as this one.

leapinglizard

Clarification of Answer by leapinglizard-ga on 07 Feb 2003 00:11 PST
I'm afraid I didn't word the previous clarification very well. I don't
mean that you should change the second-last line of the __init__
function, but that you should add one additional line, so that the
final block looks like this:

        self.ctrlRE = re.compile('\\r')
        self.open(0)
        self.grep()
        self.regex_entry.focus_set()
        self.root.mainloop()

leapinglizard

Request for Answer Clarification by donkan-ga on 07 Feb 2003 01:17 PST
ll,

Sticking 
self.regex_entry.focus_set()
in the code did the trick. Thanks!

I don't understand this yet, but I'm working on it.

donkan-ga

Clarification of Answer by leapinglizard-ga on 07 Feb 2003 01:32 PST
Any time.

leapinglizard
donkan-ga rated this answer:5 out of 5 stars and gave an additional tip of: $8.00
ll, Grepper works perfectly! You went way beyond what I requested by
putting in some very cool features. I hope you enjoyed creating
grepper, because it must have taken a lot more than $7 of your time.
Thanks very much. I hope to learn a lot from the code.

I'm adding an $8 tip, to make it $15--still way too cheap.

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy