Python Simple Dialogs

Applications typically have to request input from the user from time to time. Python and tkinter have built in dialogs that help you ask the user basic questions. These dialogs also provide validation to help make sure that the user enters valid input. This is an example program that shows off askquestion, askfloat, askinteger, and askstring.

from tkinter import *
from tkinter.messagebox import askquestion, showinfo
from tkinter.simpledialog import askfloat, askinteger, askstring


class AskDialogDemo(Frame):
    def __init__(self, master=None, cnf={}, **kw):
        super().__init__(master, cnf, **kw)
        self.pack()
        Button(self, text='Ask a Question', command=self.askquestion_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for a Float', command=self.askfloat_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for an Integer', command=self.askinteger_demo).pack(side=LEFT, fill=BOTH, expand=YES)
        Button(self, text='Ask for a String', command=self.askstring_demo).pack(side=LEFT, fill=BOTH, expand=YES)

    def askquestion_demo(self):
        answer = askquestion('Question', 'Do you like corn?')
        if answer:
            showinfo('Answer', answer)
        else:
            self.canceled()

    def askfloat_demo(self):
        num = askfloat('Float', 'Enter a decimal number')
        if num:
            showinfo('Float', 'You entered {}'.format(num))
        else:
            self.canceled()

    def askinteger_demo(self):
        num = askinteger('Integer', 'Enter a whole number')
        if num:
            showinfo('Integer', 'You entered {}'.format(num))
        else:
            self.canceled()

    def askstring_demo(self):
        str = askstring('String', 'Enter a string')
        if str:
            showinfo('String', 'You entered {}'.format(str))
        else:
            self.canceled()

    def canceled(self):
        showinfo('Canceled', 'You canceled')


if __name__ == '__main__':
    AskDialogDemo().mainloop()

Explanation

askquestion

You use askquestion to ask the user a basic yes or no question. It takes two arguments: one for the title, and the other is for the question. The returned value will be a string containing yes or no.

answer = askquestion('Question', 'Do you like corn?')

askfloat

The askfloat function returns decimal numbers. It will also perform validation that makes sure the user enters a valid float. The function will either return the float that the user entered or it will return None if they hit cancel.

num = askfloat('Float', 'Enter a decimal number')

askinteger

This function works like askfloat but it returns integers.

num = askinteger('Integer', 'Enter a whole number')

askstring

You can use askstring to get a string value from the user. It will return None if the user enters a blank string and hits Ok or Cancel.

str = askstring('String', 'Enter a string')

Python Advanced Quit Button

Object orientated programming fits extremely well with GUI programming. Using OOP, we can easily make reusable GUI components. This post shows off a quit button that confirms if the user really wants to exit the application. I got the idea from Programming Python: Powerful Object-Oriented Programming. Here is my implementation of the idea followed by the explanation.

from tkinter import *
from tkinter.messagebox import *


class TkQuitButton(Frame):
    def __init__(self, master=None,
                 auto_pack=True,  # Pack the widget automatically?
                 dialog_title='Confirm',  # Title text for the askyesno dialog
                 dialog_message='Are you sure you want to quit?',  # Message for the askyesno dialog
                 button_text='Quit',  # The quit button's text
                 quit_command=Frame.quit,  # Callback command for when the user wants to quit
                 cnf={}, **kw):

        super().__init__(master, cnf, **kw)
        # Store our fields for later user
        self.quit_command = quit_command
        self.dialog_message = dialog_message
        self.dialog_title = dialog_title
        self.quit_button = Button(self, text=button_text, command=self.quit)

        # Notice that self.quit_button is exposed. This can be useful for when
        # the client code needs to configure this frame on its own
        if auto_pack:
            self.pack_widget()
    
    # This let's us override the packing        
    def pack_widget(self):
        self.pack()
        self.quit_button.pack(side=LEFT, expand=YES, fill=BOTH)

    def quit(self):
        # Call the askyesno dialog
        result = askyesno(self.dialog_title, self.dialog_message)
        if result:
            # if they quit, then execute the stored callback command
            self.quit_command(self)


if __name__ == '__main__':
    TkQuitButton().mainloop()

This class extends the Frame class and packs a button into the frame. There are a few configuration properties that can be passed into the constructor. For example, we can auto_pack the widget so that it uses a default packing scheme. We can specifiy a custom title for the askyesno dialog as well as a custom message. The code even lets use customize the text of the button. We can also use a custom quit handler function should we choose to do so.

We can customize how the widget is packed in two different ways. The first way to access the quit_button property and call pack on it directly. This allows client code to change how this widget is packed into their GUIs. Alternatively, we can subclass this class and just override the pack_widget method.

The default quit implementation uses Tk’s askyesno dialog function to display a confirmation dialog to the user. It’s title and message are set to self.dialog_title and self.dialog_message properties. This allows use to customize what the user sees when the dialog is displayed. If the user presses yes, then we call the self.quit_command function which defaults to Frame.quit. Note that since self.quit is a method, we can customize this behavior by overriding it. Since we use a callback handler to exit the applicaiton, we can also customize how the application exits as well.

Tk Standard Dialogs

Applications generally need to show system dialogs to alert the user to events. In this post, we will cover the yes or no dialog, a warning dialog, information dialog, and an error dialog. Tk uses system calls to show dialogs that are native to the underlying platform. Therefore, dialogs on Windows will look like they should on Windows while Mac OS X dialogs will appear correct for that platform.

askyesno

The askyesno is a dialog that is used to present a user with a yes or no choice. It returns a boolean to the caller.

result = askyesno('Yes No Demo', 'Click on either yes or no')

yesno

showwarning

You use showwarning when you want to warn the user about something.

showwarning('Warning Demo', 'You have been warned')

warning

showinfo

This dialog is used to supply the user with information.

showinfo('Info Demo', 'This is some information')

info

showerror

You should use showerror when you need to report an error to the user.

showerror('Error Demo', 'This is an error')

error

Putting it Together

Standard dialog calls are a useful way to notify the user about something important. Since they block the program’s execution, the user is forced to interact with the dialog. This makes the dialogs ideal for forcing the user to read a message or make a choice. Below is a complete program that demonstrates all of the dialogs.

from tkinter import *
from tkinter.messagebox import *


def ask_yes_no_demo():
    result = askyesno('Yes No Demo', 'Click on either yes or no')
    if result:
        showinfo('Result', 'You clicked on Yes')
    else:
        showinfo('Result', 'You clicked on No')


def warning_demo():
    showwarning('Warning Demo', 'You have been warned')


def info_demo():
    showinfo('Info Demo', 'This is some information')


def error_demo():
    showerror('Error Demo', 'This is an error')


root = Tk()
Button(text='Ask Yes No', command=ask_yes_no_demo).pack(fill=X)
Button(text='Warning', command=warning_demo).pack(fill=X)
Button(text='Info', command=info_demo).pack(fill=X)
Button(text='Error', command=error_demo).pack(fill=X)
Button(text='Quit', command=(lambda: sys.exit(0))).pack(fill=X)
mainloop()