[tkinter] trouble running imported modules in main program

Post here if you need help with creating a Graphical User Interface in Python.

[tkinter] trouble running imported modules in main program

Postby snakeinmyboot » Tue Aug 06, 2013 7:28 pm

Hello,

I am currently just starting to learn the basics of the tkinter module and ive run into a problem. To teach myself I am messing around by creating separate modules containing basic GUI apps like a tip calculator and kilometer converter, then creating a main program that displays buttons you can click that will create instances of the modules (tip calculator, kilometer converter). So far ive managed to successfully make the basic GUI apps works just fine, and have been able to import them into my main program and get them to launch in a new window when i click the buttons and everything, but heres my problem.

Everything displays ok, like the labels, entry boxes, and buttons, but when I actually click the buttons (which are supposed to trigger a method within the module and display a label containing the calculated data).. nothing happens. When I run the modules by themselves everything works just fine (testing by making the module create an instance of itself but i # them out before running the main program).

here is all my code, forgive me if its sloppy or confusing to read

The Tip Calculator Module
Code: Select all
import tkinter

import tkinter.messagebox

class Tip_Calc:

    def __init__(self):

        # create main window

        self.main_window = tkinter.Tk()

        self.main_window.title('Tip Calculator')

        self.main_window.geometry('325x150')

        # create frames

        self.top_frame = tkinter.Frame(self.main_window)

        self.center_frame = tkinter.Frame(self.main_window)

        self.bottom_frame = tkinter.Frame(self.main_window)

        # top frame widgets

        self.bill_prompt = tkinter.Label(self.top_frame,
                                            text = 'How much is your bill? $')

        self.bill_entry = tkinter.Entry(self.top_frame, width = 8)

        self.bill_prompt.pack(side = 'left')

        self.bill_entry.pack(side = 'left')

        # center frame widgets

        self.percent_prompt = tkinter.Label(self.center_frame,
                                            text = 'What percentage would ' +
                                            'you like to tip? ')

        self.percent_entry = tkinter.Entry(self.center_frame, width = 5)

        self.percent_sign = tkinter.Label(self.center_frame, text = '%')

        self.percent_prompt.pack(side = 'left')

        self.percent_entry.pack(side = 'left')

        self.percent_sign.pack(side = 'left')

        # calculation frame widgets

        self.calctip = tkinter.StringVar()

        self.calc_label = tkinter.Label(self.bottom_frame, \
                                        textvariable = self.calctip)
                                   
        self.calc_label.pack(side = 'top')

                                               
        # bottom frame widgets

        self.calc_button = tkinter.Button(self.bottom_frame, \
                                          text = 'Calculate', \
                                          command = self.calculate)

        self.quit_button = tkinter.Button(self.bottom_frame, \
                                          text = 'Quit', \
                                          command = self.main_window.destroy)
                                       
        self.calc_button.pack()

        self.quit_button.pack()       
                                         
        # pack frames

        self.top_frame.pack()

        self.center_frame.pack()

        self.bottom_frame.pack()

       # enter main loop

        tkinter.mainloop()

    def calculate(self):

        try:
           
            bill = float(self.bill_entry.get()) / 100

            percent = float(self.percent_entry.get())

            tip = format(bill * percent, ',.2f')

            self.calctip.set('The amount you will tip is $' + tip)

        except:

            self.error_message  = tkinter.messagebox.showinfo('Error', \
                                                              'Enter numbers ' \
                                                              'only')
       
# create object

#tip_calc = Tip_Calc()


The Kilometer Converter module
Code: Select all
import tkinter

import tkinter.messagebox


class Kilo_Conv:

    def __init__(self):

        # main window

        self.main_window = tkinter.Tk()

        self.main_window.title('Kilometer Converter')

        self.main_window.geometry('280x190')

        # frames

        self.frame1 = tkinter.Frame(self.main_window)

        self.frame2 = tkinter.Frame(self.main_window)

        self.frame3 = tkinter.Frame(self.main_window)

        self.blank_frame = tkinter.Frame(self.main_window)

        self.frame4 = tkinter.Frame(self.main_window)

        # frame1 widgets

        self.kilo_prompt = tkinter.Label(self.frame1, text = 'Enter a ' + \
                                         'distance in kilometers')

        self.kilo_entry = tkinter.Entry(self.frame1, width = 8)

        self.kilo_prompt.pack(side = 'left')

        self.kilo_entry.pack(side = 'left')

        # frame 2 widgets

        self.calc_kilo = tkinter.StringVar()

        self.kilo_calc_label = tkinter.Label(self.frame2, \
                                             textvariable = self.calc_kilo)

        self.kilo_calc_label.pack()

       

        # frame 3 widgets

        self.convert_to = tkinter.Label(self.frame3, text = 'Convert to....')

        self.miles_button = tkinter.Button(self.frame3, \
                                           text = 'Miles', \
                                           command = self.conv_miles)

        self.yards_button = tkinter.Button(self.frame3, \
                                           text = 'Yards', \
                                           command = self.conv_yards)

        self.feet_button = tkinter.Button(self.frame3, \
                                           text = 'Feet', \
                                           command = self.conv_feet)

        self.inches_button = tkinter.Button(self.frame3, \
                                           text = 'Inches', \
                                           command = self.conv_inches)

        self.convert_to.pack()

        self.miles_button.pack(side = 'left')

        self.yards_button.pack(side = 'left')

        self.feet_button.pack(side = 'left')

        self.inches_button.pack(side = 'left')

        # blank frame widget

        self.blank_label = tkinter.Label(self.blank_frame)

        self.blank_label.pack()

        # frame 4 widgets

        self.quit_button = tkinter.Button(self.frame4, text = 'Quit', \
                                          command = self.main_window.destroy)

        self.quit_button.pack()

        # pack frame

        self.frame1.pack()

        self.frame2.pack()

        self.frame3.pack()
       
        self.blank_frame.pack()

        self.frame4.pack()


        # main loop

        tkinter.mainloop

    def conv_miles(self):

        try:           

            kilo = float(self.kilo_entry.get())

       
                                                             

            miles = format(float(kilo * 0.62137), '.3f')

            milesmsg = self.kilo_entry.get(), 'kilometers =', miles, 'miles'

            self.calc_kilo.set(milesmsg)

        except:

            self.error_message = tkinter.messagebox.showinfo('Error', \
                                                             'Enter numbers ' \
                                                             'only')


    def conv_yards(self):

        try:
   
            kilo = float(self.kilo_entry.get())

            yards = format(float(kilo * 1093.6), '.2f')

            yardsmsg = self.kilo_entry.get(), 'kilometers =', yards, 'yards'

            self.calc_kilo.set(yardsmsg)

        except:

            self.error_message = tkinter.messagebox.showinfo('Error', \
                                                             'Enter numbers ' \
                                                             'only')

       
    def conv_feet(self):

        try:

            kilo = float(self.kilo_entry.get())

            feet = int(kilo * 3280)

            feetmsg = self.kilo_entry.get(), 'kilometers =', feet, 'feet'

            self.calc_kilo.set(feetmsg)

        except:

            self.error_message = tkinter.messagebox.showinfo('Error', \
                                                             'Enter numbers ' \
                                                             'only')


    def conv_inches(self):

        try:

            kilo = float(self.kilo_entry.get())

            inches = int(kilo * 39370)

            inchesmsg = self.kilo_entry.get(), 'kilometers =', inches, 'inches'

            self.calc_kilo.set(inchesmsg)

        except:

            self.error_message = tkinter.messagebox.showinfo('Error', \
                                                             'Enter numbers ' \
                                                             'only')

# create object
#kilo_conv = Kilo_Conv()                                       


The Main Program
Code: Select all
import tkinter

import tkinter.messagebox

import tipcalculator

import kiloconverter


class Simple_Apps:

    def __init__(self):

        # main window

        self.main_window = tkinter.Tk()

        self.main_window.title('Simple Apps')

        self.main_window.geometry('400x300')


        # frames

        self.frame1 = tkinter.Frame(self.main_window)

        self.frame2 = tkinter.Frame(self.main_window)

        self.frame3 = tkinter.Frame(self.main_window)

        self.frame4 = tkinter.Frame(self.main_window)

        # top frame widgets

        self.tip_button = tkinter.Button(self.frame1, \
                                         text = 'Tip Calculator', \
                                         command = self.tip_calc)

        self.kilo_button = tkinter.Button(self.frame1, \
                                          text = 'Kilometer Converter', \
                                          command = self.kilo_conv)

        self.tip_button.pack()

        self.kilo_button.pack()


        # pack frames

        self.frame1.pack()


        # main loop

        tkinter.mainloop

    def tip_calc(self):

        tip_app = tipcalculator.Tip_Calc()

    def kilo_conv(self):

        kilo_app = kiloconverter.Kilo_Conv()
                                         

imple_apps = Simple_Apps()


Any idea what im doing wrong here?
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: trouble running imported modules in main program

Postby Yoriz » Tue Aug 06, 2013 7:36 pm

Hiya, Gui's should only have one mainloop.
You have a mainloop in each one, one mainloop should deal with the events from all the windows.
New Users, Read This
Join the #python-forum IRC channel on irc.freenode.net!
Spam topic disapproval technician
Windows7, Python 2.7.4., WxPython 2.9.5.0., some Python 3.3
User avatar
Yoriz
 
Posts: 789
Joined: Fri Feb 08, 2013 1:35 am
Location: UK

Re: trouble running imported modules in main program

Postby snakeinmyboot » Tue Aug 06, 2013 8:01 pm

Yoriz wrote:Hiya, Gui's should only have one mainloop.
You have a mainloop in each one, one mainloop should deal with the events from all the windows.



I didnt even think about that. However, I just went in and # 'd out the mainloop code in the Tip Calculator and the Kilometer Converter and tried running the main program, but its behaving exactly the same. Thanks for that bit of info though.
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: [tkinter] trouble running imported modules in main progr

Postby snakeinmyboot » Tue Aug 06, 2013 11:07 pm

I am also having another weird problem with this code but i figured I shouldnt make a new topic for it. When the modules run smoothly by themselves, the label display is presented oddly.

Image

for some reason those brackets around "kilometers =" are always there and I cant get them to go away.
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: [tkinter] trouble running imported modules in main progr

Postby snakeinmyboot » Wed Aug 07, 2013 3:11 am

No help here people? Cmon I know y'all are smarter than me at this!
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: [tkinter] trouble running imported modules in main progr

Postby wuf » Wed Aug 07, 2013 1:28 pm

snakeinmyboot wrote:No help here people? Cmon I know y'all are smarter than me at this!

No worries mate! Try this:
Code: Select all
            miles = format(float(kilo * 0.62137), '.3f')
            milesmsg = '{0} kilometers = {1} miles'.format(kilo, miles)

wuf ;)
wuf
 
Posts: 37
Joined: Fri Feb 08, 2013 6:42 am

Re: [tkinter] trouble running imported modules in main progr

Postby driscollis » Wed Aug 07, 2013 6:35 pm

Your code works for me as soon as I changed line 55 in your main app to be tkinter.mainloop() instead of tkinter.mainloop

I'm using Python 3 on Windows 7.
driscollis
 
Posts: 2
Joined: Wed Aug 07, 2013 6:33 pm
Location: Texas

Re: [tkinter] trouble running imported modules in main progr

Postby snakeinmyboot » Thu Aug 08, 2013 4:08 am

wuf wrote:
snakeinmyboot wrote:No help here people? Cmon I know y'all are smarter than me at this!

No worries mate! Try this:
Code: Select all
            miles = format(float(kilo * 0.62137), '.3f')
            milesmsg = '{0} kilometers = {1} miles'.format(kilo, miles)

wuf ;)



although my main problem hasnt been solved yet, this was SUPER helpful and solved my secondary problem! This will save me so much time on future projects...why on earth did they not teach us this simple awesome feauture in my intro programming class...
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: [tkinter] trouble running imported modules in main progr

Postby snakeinmyboot » Thu Aug 08, 2013 4:09 am

driscollis wrote:Your code works for me as soon as I changed line 55 in your main app to be tkinter.mainloop() instead of tkinter.mainloop

I'm using Python 3 on Windows 7.


Thanks for the tip. I just did this, but its still not working for me.
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am

Re: [tkinter] trouble running imported modules in main progr

Postby wuf » Thu Aug 08, 2013 10:33 am

Hi snakeinmyboot

For additional windows which belong to a application main window you should use the 'Toplevel'-Widget. This kind of window does not need an additional 'mainloop'-call. The main window which you create with:
Code: Select all
self.main_window = tk.Tk()
needs as only one a 'mainloop'-call. As our friend 'driscollis' already told the mainloop-call has to end with brackets:
Code: Select all
self.main_window.mainloop()

And a tip of mine. Have a closer look at the PEP-8 style guide. http://www.python.org/dev/peps/pep-0008/ This guide gives good advise how to write and style python scripts.

I have made some modification to your script. They should work under Python 2.7 and Python 3.1. Have tested them with Linux Kubuntu.

The main script 'main.py':
Code: Select all
try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkMessageBox as messagebox
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.messagebox as messagebox
   
import tipcalculator
import kiloconverter

class Simple_Apps(object):

    def __init__(self):

        self.main_window = tk.Tk()
        self.main_window.title('Simple Apps')
        self.main_window.geometry('200x100+20+20')
        self.main_window.config(bg='steelblue')

        self.frame1 = tk.Frame(self.main_window, bg=self.main_window['bg'])
        self.frame1.pack(expand=True)

        self.tip_button = tk.Button(self.frame1, highlightthickness=0,
            text='Tip Calculator', command=self.tip_calc)
        self.tip_button.pack(fill='x', pady=2)

        self.kilo_button = tk.Button(self.frame1, highlightthickness=0,
            text='Kilometer Converter', command=self.kilo_conv)
        self.kilo_button.pack(fill='x', pady=2)

        self.end_button = tk.Button(self.frame1, highlightthickness=0,
            text='End', command=self.main_window.destroy)
        self.end_button.pack(fill='x', pady=2)

        self.main_window.mainloop()

    def tip_calc(self):

        tip_app = tipcalculator.Tip_Calc()

    def kilo_conv(self):

        kilo_app = kiloconverter.Kilo_Conv()

simple_apps = Simple_Apps()

The kilometer converter script 'kiloconverter.py':
Code: Select all
try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkMessageBox as messagebox
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.messagebox as messagebox

ERROR_MSG = 'Enter numbers only!'

class Kilo_Conv(tk.Toplevel):

    def __init__(self):

        # Create a toplevel window for the 'Kilometer Converter'
        tk.Toplevel.__init__(self)
        self.title('Kilometer Converter')

        self.main_frame = tk.Frame(self)
        self.main_frame.pack(expand=True, padx=20, pady=20)
       
        self.frame1 = tk.Frame(self.main_frame)
        self.frame1.pack()
       
        self.frame2 = tk.Frame(self.main_frame)
        self.frame2.pack()
       
        self.frame3 = tk.Frame(self.main_frame)
        self.frame3.pack(pady=(0,4))
       
        self.frame4 = tk.Frame(self.main_frame)
        self.frame4.pack()

        self.kilo_prompt = tk.Label(self.frame1,
            text='Enter a distance in kilometers')
        self.kilo_prompt.pack(side='left')

        self.kilo_entry = tk.Entry(self.frame1, highlightthickness=0,
            width=8, bg='white')
        self.kilo_entry.pack(side='left', padx=(4,0))

        self.calc_kilo = tk.StringVar()

        self.kilo_calc_label = tk.Label(self.frame2, fg='blue',
            font=('Helvetica', 12, 'bold'), textvariable=self.calc_kilo)
        self.kilo_calc_label.pack(pady=4)

        self.convert_to = tk.Label(self.frame3, text = 'Convert to....')
        self.convert_to.pack()

        self.miles_button = tk.Button(self.frame3,
            text='Miles', command=self.conv_miles)
        self.miles_button.pack(side='left')
       
        self.yards_button = tk.Button(self.frame3,
            text='Yards', command=self.conv_yards)
        self.yards_button.pack(side='left')
       
        self.feet_button = tk.Button(self.frame3,
            text='Feet', command=self.conv_feet)
        self.feet_button.pack(side='left')

        self.inches_button = tk.Button(self.frame3,
            text = 'Inches', command=self.conv_inches)
        self.inches_button.pack(side='left')

        self.quit_button = tk.Button(self.frame4,
            text='Quit', command=self.destroy)
        self.quit_button.pack()

        self.kilo_entry.focus_set()
       
    def conv_miles(self):

        try:           
            kilo = float(self.kilo_entry.get())
           
            miles = format(float(kilo * 0.62137), '.3f')
            milesmsg = '{0} kilometers = {1} miles'.format(kilo, miles)
           
            self.calc_kilo.set(milesmsg)
        except:
            self.show_error_msg(ERROR_MSG)

    def conv_yards(self):

        try:
            kilo = float(self.kilo_entry.get())

            yards = format(float(kilo * 1093.6), '.2f')
            yardsmsg = '{0} kilometers = {1} yards'.format(kilo, yards)

            self.calc_kilo.set(yardsmsg)
        except:
            self.show_error_msg(ERROR_MSG)
       
    def conv_feet(self):

        try:
            kilo = float(self.kilo_entry.get())

            feet = int(kilo * 3280)
            feetmsg = '{0} kilometers = {1} feet'.format(kilo, feet)
           
            self.calc_kilo.set(feetmsg)
        except:
            self.show_error_msg(ERROR_MSG)
           
    def conv_inches(self):

        try:
            kilo = float(self.kilo_entry.get())

            inches = int(kilo * 39370)
            inchesmsg = '{0} kilometers = {1} inches'.format(kilo, inches)

            self.calc_kilo.set(inchesmsg)
        except:
            self.show_error_msg(ERROR_MSG)
       
    def show_error_msg(self, msg):
        self.error_message = messagebox.showerror(title='Error',
            message=msg, parent=self)

#----- MODULE-TEST ------------------------------------------------------------#
if __name__ == '__main__':
    test_win = tk.Tk()
    test_win.title("Module Test")

    main_frame = tk.Frame(test_win)
    main_frame.pack(expand=True, padx=10, pady=10)
   
    test_label = tk.Label(main_frame, fg='darkolivegreen',
        text="Module: Kilometer Converter", font=('Helvetica', 12, 'bold'))
    test_label.pack(padx=20, pady=5)
   
    button_frame = tk.Frame(main_frame)
    button_frame.pack()
   
    button_end = tk.Button(button_frame, text='Test module',
        command=Kilo_Conv)
    button_end.pack(fill='x')
   
    button_end = tk.Button(button_frame, text='End module test',
        command=test_win.destroy)
    button_end.pack(fill='x')
   
    test_win.mainloop()

The tip calculator script 'tipcalculator.py':
Code: Select all
try:
    #~~ For Python 2.x
    import Tkinter as tk
    import tkMessageBox as messagebox
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
    import tkinter.messagebox as messagebox

ERROR_MSG = 'Enter numbers only!'

class Tip_Calc(tk.Toplevel):

    def __init__(self):

        # Create a toplevel window for the 'Tip Calculator'
        tk.Toplevel.__init__(self)
        self.title('Tip Calculator')

        # create frames
        self.main_frame = tk.Frame(self)
        self.main_frame.pack(expand=True, padx=20, pady=20)
       
        self.top_frame = tk.Frame(self.main_frame)
        self.top_frame.pack(pady=(0,10))
       
        self.top_left_frame = tk.Frame(self.top_frame)
        self.top_left_frame.pack(side='left', expand=True)

        self.top_right_frame = tk.Frame(self.top_frame)
        self.top_right_frame.pack(side='left', expand=True, padx=(4,0))
       
        self.center_frame = tk.Frame(self.main_frame)
        self.center_frame.pack(pady=(0,10))
       
        self.bottom_frame = tk.Frame(self.main_frame)
        self.bottom_frame.pack()

        # Bill
        self.bill_prompt = tk.Label(self.top_left_frame,
            text='How much is your bill? $')
        self.bill_prompt.pack(anchor='e')

        self.bill_entry = tk.Entry(self.top_right_frame,
            bg='white', highlightthickness=0, width=8)
        self.bill_entry.pack(anchor='w')

        # Tip
        self.percent_prompt = tk.Label(self.top_left_frame,
            text='What percentage would you like to tip % ?')
        self.percent_prompt.pack(anchor='e')

        self.percent_entry = tk.Entry(self.top_right_frame,
            bg='white', highlightthickness=0, width=5)
        self.percent_entry.pack(anchor='w', fill='x')

        # Percentage
        self.percent_sign = tk.Label(self.center_frame, fg='blue',
            font=('Helvetica', 12, 'bold'), text='Your tip = ')
        self.percent_sign.pack(side='left')

        # calculation frame widgets
        self.calctip = tk.StringVar()
        self.calctip.set('?')
        self.calc_label = tk.Label(self.center_frame,
            textvariable=self.calctip, fg='blue',
            font=('Helvetica', 12, 'bold'))
        self.calc_label.pack(side='left')

        # bottom frame widgets
        self.calc_button = tk.Button(self.bottom_frame,
            text = 'Calculate', command=self.calculate)
        self.calc_button.pack(fill='x')

        self.quit_button = tk.Button(self.bottom_frame,
            text='Quit', command=self.destroy)
        self.quit_button.pack(fill='x')       

        self.bill_entry.focus_set()
       
    def calculate(self):

        try:
            bill = float(self.bill_entry.get()) / 100

            percent = float(self.percent_entry.get())
            tip = '$ {0}'.format((bill * percent), '.2f')

            self.calctip.set(tip)
        except:
            self.show_error_msg(ERROR_MSG)

    def show_error_msg(self, msg):
        self.error_message = messagebox.showerror(title='Error',
            message=msg, parent=self)

#----- MODULE-TEST ------------------------------------------------------------#
if __name__ == '__main__':
    test_win = tk.Tk()
    test_win.title("Module Test")

    main_frame = tk.Frame(test_win)
    main_frame.pack(expand=True, padx=10, pady=10)
   
    test_label = tk.Label(main_frame, fg='darkolivegreen',
        text="Module: Tip Calculator", font=('Helvetica', 12, 'bold'))
    test_label.pack(padx=20, pady=5)
   
    button_frame = tk.Frame(main_frame)
    button_frame.pack()
   
    button_end = tk.Button(button_frame, text='Test module',
        command=Tip_Calc)
    button_end.pack(fill='x')
   
    button_end = tk.Button(button_frame, text='End module test',
        command=test_win.destroy)
    button_end.pack(fill='x')
   
    test_win.mainloop()

The module scripts 'tipcalculator.py' and 'kiloconverter.py' i have expanded with module test code. So you can test them without having a main script. Just start the script by its module name. For example:
python kiloconverter.py

Maybe you can study the modified scripts to get some more hints. Wishing you a lot of fun by programming with Python & Tkinter.

Greetings from wuf ;)
wuf
 
Posts: 37
Joined: Fri Feb 08, 2013 6:42 am

Re: [tkinter] trouble running imported modules in main progr

Postby snakeinmyboot » Fri Aug 09, 2013 5:10 am

wuf wrote:
I have made some modification to your script. They should work under Python 2.7 and Python 3.1. Have tested them with Linux Kubuntu.



Thank you SO SO much!!!!!
snakeinmyboot
 
Posts: 13
Joined: Sun Jun 23, 2013 5:56 am


Return to GUI

Who is online

Users browsing this forum: Google [Bot] and 2 guests