Why use a class? Because it makes the job easier, assuming you know how to do object oriented programming, and assuming you're writing a non-trivial GUI. Using objects allows you to easily divide your code into modular units that are self contained, and modularizing your code is generally considered to be a best practice.
GUI programming readily lends itself to an object-oriented style, since a GUI is made up entirely of objects -- labels, buttons, scrollbars, text areas, etc. Since you're already using objects, organizing your code into larger objects makes sense. The toolbar is an object, the statusbar is an object, the navigation pane is an object, the main area is an object, each notebook tab is an object, and so on.
Even when your code isn't very complex, from a more practical standpoint it lets you define bindings and callbacks earlier in the file than the definition of the function you're calling, which I think makes a lot of sense.
Consider a simple example:
import tkinter as tk
def quit(event=None):
sys.exit()
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack()
label.bind("<1>", quit)
root.mainloop()
To me, the flow of that code is all wrong. I have to define the quit method before I reference it, and the creation of the root window and the call to mainloop are separated by all of the other code.
By using classes, however, I can write the code in a more natural order:
class MyWindow(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Hello, world")
label.pack()
label.bind("<1>", self.quit)
def quit(self, event=None):
sys.exit()
root = tk.Tk()
MyWindow(root).pack()
root.mainloop()
The main body of the GUI is right at the top of the file, and supporting code is below it. Now, of course, you can use functions to achieve much of the same thing. In my opinion, though, classes make it all just a little easier.
Another advantage is that I can now easily change the containing window without having to change anything about the "main" window (and visa versa). That is, I can add borders, or a complete new section to the main GUI, but I don't have to touch a single line of code inside of MyWindow. Contrast that with the procedural code where you might have to change the label.pack()
statement, and the pack (or grid) statements of all of the other widgets in the UI.
All that being said, however, using an object oriented approach isn't necessary to write good, clean, maintainable code. It can be, but it can also lead to poor code. At the end of the day, an object-oriented approach is just a tool. Whether you use it or not, and whether you use it correctly or not depends on a lot of factors. So it may very well be that for you, and for the code you write, a functional style is perfectly acceptable. I do think you'll find that as your programs get more complex, an object-oriented approach will make it easier to organize and maintain your code.