I have a Python command line program I am attempting to convert into a GUI. Before I bury myself in code does anyone have some advice on this process? Is there a method to simply make everything in the CLI program show up in a tkinter frame? For inputs I assume I will need Entry boxes but beyond that can the responses and prompts of the program be displayed simply as Labels?

Thanks very, very much. Learning Python is fun but arduous for the neophyte.

Jack

Recommended Answers

All 3 Replies

Not quite as arduous if you use a template approach, then you only need to customize a few things to fit your task. Here is an example of a general Tkinter template that ask for two numbers (tk.Entry), processes them and displays the result (tk.Label) ...

# a general Tkinter program to enter two data items
# process the data and display the result

try:
    # for Python2
    import Tkinter as tk
except ImportError:
    # for Python3
    import tkinter as tk

def calculate():
    """
    in this case the data items are floating point numbers 
    that are simply added in the example data process
    the result is displayed in a label
    """
    try:
        x = float(enter1.get())
        y = float(enter2.get())
        # the process step, customize to your needs ...
        s = str(x + y)
        label3.config(text=s)
    except ValueError:
        label3.config(text='Enter numeric values for x and y')

def setfocus2(event):
    enter2.focus_set()

        
# create the root window
root = tk.Tk()

# create all the components/widgets
label1 = tk.Label(root, text='Enter number x:', width=28)
enter1 = tk.Entry(root, bg='yellow')
label2 = tk.Label(root, text='Enter number y:')
enter2 = tk.Entry(root, bg='yellow')
button1 = tk.Button(root, text='Add the numbers', command=calculate)
# the result label
label3 = tk.Label(root, text='', bg='green')

# pack widgets vertically in the root window in that order
label1.pack(side='top', fill='x')
enter1.pack(side='top', fill='x')
label2.pack(side='top', fill='x')
enter2.pack(side='top', fill='x')
button1.pack(side='top')
label3.pack(side='top', fill='x')

# cursor in enter1
enter1.focus()
# return key in enter1 sets focus to enter2
enter1.bind("<Return>", func=setfocus2)

# start the event loop
root.mainloop()

You can easily see that most of the code is reusable for all sorts of data entry, data process and display situations. Play with it, and have fun.

Here is the code rewritten in wxpython,so you can compare.
Wxpython is a good gui-toolkit and it look better in windows than Tkinter.
vega_convert_to_wxpython.rar

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle, size=mysize)
         
        #---| Window color |---#
        self.SetBackgroundColour("light blue")
        
        #---| Panel for frame |---#
        panel = wx.Panel(self)       
        
        #---| Static Text |---#
        self.l1 = wx.StaticText(panel, -1, 'Enter nr x:',
                    pos = (45, 10), size = (150,16 )).SetForegroundColour('blue')
        self.l2 = wx.StaticText(panel, -1, 'Enter nr y:',
                    pos = (45, 60), size = (150,16 )).SetForegroundColour('blue')
        self.result = wx.StaticText(panel, -1, '', pos = (20, 120), size = (200,16))            
        
         #---| Text Boxes |---#
        self.text1 = wx.TextCtrl(panel, pos = (20, 30), size = (100,23))        
        self.text2 = wx.TextCtrl(panel, pos = (20, 80), size = (100,23))
        
        #---| Picture_Button |---#
        self.button1 = wx.BitmapButton(panel, -1 ,wx.Bitmap("8.png"),
                                          pos = (140, 35), size = (55,65))
        self.button1.Bind(wx.EVT_BUTTON, self.button_click)  #*bind to event*#                  
        
    def button_click(self, event):        
        """
        in this case the data items are floating point numbers 
        that are simply added in the example data process
        the result is displayed in a label
        """
        try:        
            x = float(self.text1.GetValue())
            y = float(self.text2.GetValue())
            s = str(x + y)
            self.result.SetLabel(str(s))
        except ValueError:            
            self.result.SetLabel('Enter numeric values for x and y')               
         
#---|Set opp window and show |---#
if __name__ == "__main__":
    app = wx.App()   
    mytitle = 'My window'  
    width = 230
    height = 180
    MyFrame(None, mytitle, (width, height)).Show()
    app.MainLoop()

Interesting.. I've been playing around with grid mostly. Here's the program that I wrote. Do you see any special problems I might run into? I'm going to spend a day attempting to integrate this into a GUI. I imagined a space for the clue, space for maybe a hint, then an entry field for the user to input a guess. But then the idea occured to me to throw in an on-screen keyboard. That's another issue which I am working on but in general here's the code I put together.

import random

option = 1
EXIT_OPTION = 2
MAX_TURNS = 5

option = 0

list_of_words = ["cat","dog","house", "boat"]


# Generate random number to select category element
random_number = random.randrange(1,len(list_of_words) - 1)

# Select random word from dictionary
word = list_of_words[random_number].upper()


clue = []

# Build clue list of letter spaces
for each_character in word:
    if each_character != " ":
        clue.append("_")
    else:
        clue.append(" ")

turns_remaining = MAX_TURNS
guessed_letters = []

# Game Loop
while turns_remaining > 0:

    
    for each_letter in clue:
        print each_letter,

    # Prompt user for letter guess & capitalize
    guess = raw_input("\n\nLetter ("+ str(turns_remaining) + ")? ")
    guess = guess.upper()

    # Process valid guess
    if guess not in guessed_letters:

        # Add guess to list of guesses
        guessed_letters.append(guess)

        # Initialize guess boolean
        allow_guess = False
        
        # Check for a match 
        for i in range(len(clue)):

            # Fill in clue if it is (& set guess boolean)
            if guess == word[i]:
                clue[i] = guess
                allow_guess = True

        # Allow user to solve if letter exists in word
        if allow_guess:

            
            for each_letter in clue:
                print each_letter,
            solution = raw_input("\n\nSolve? ").upper()
            if solution == word:
                print "\nCongratulations!"
                
                turns_remaining = 0

        # Inform user guess was not in word name
        else:

            print "\nSorry '" + guess.upper() + "' not in word!"
            

    # Otherwise inform user
    else:
        raw_input("\nLetter already used! <ENTER> to continue...")

    turns_remaining -= 1

    # Check for loser
    if turns_remaining == 0:
        print "\nSorry - you lose!"

Thanks again, you've been a huge help. I'm slowly getting this into my head.

-Jack

Not quite as arduous if you use a template approach, then you only need to customize a few things to fit your task. Here is an example of a general Tkinter template that ask for two numbers (tk.Entry), processes them and displays the result (tk.Label) ...

# a general Tkinter program to enter two data items
# process the data and display the result

try:
    # for Python2
    import Tkinter as tk
except ImportError:
    # for Python3
    import tkinter as tk

def calculate():
    """
    in this case the data items are floating point numbers 
    that are simply added in the example data process
    the result is displayed in a label
    """
    try:
        x = float(enter1.get())
        y = float(enter2.get())
        # the process step, customize to your needs ...
        s = str(x + y)
        label3.config(text=s)
    except ValueError:
        label3.config(text='Enter numeric values for x and y')

def setfocus2(event):
    enter2.focus_set()

        
# create the root window
root = tk.Tk()

# create all the components/widgets
label1 = tk.Label(root, text='Enter number x:', width=28)
enter1 = tk.Entry(root, bg='yellow')
label2 = tk.Label(root, text='Enter number y:')
enter2 = tk.Entry(root, bg='yellow')
button1 = tk.Button(root, text='Add the numbers', command=calculate)
# the result label
label3 = tk.Label(root, text='', bg='green')

# pack widgets vertically in the root window in that order
label1.pack(side='top', fill='x')
enter1.pack(side='top', fill='x')
label2.pack(side='top', fill='x')
enter2.pack(side='top', fill='x')
button1.pack(side='top')
label3.pack(side='top', fill='x')

# cursor in enter1
enter1.focus()
# return key in enter1 sets focus to enter2
enter1.bind("<Return>", func=setfocus2)

# start the event loop
root.mainloop()

You can easily see that most of the code is reusable for all sorts of data entry, data process and display situations. Play with it, and have fun.

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.