Reply to topic  [ 1 post ] 
 Python Tkinter Application Programming Tutorial 
Author Message
Level 22
Level 22
User avatar

Cash on hand:
Posts: 2231
Joined: Sat Nov 17, 2012 11:10 am
Location: SR388
Group: Special Access
Post Python Tkinter Application Programming Tutorial
So an application is essentially the Visual part of a program, every application is a program or multiple programs, but not every program is an application. Many Programs do have a UI Interface (otherwise called an 'application'), but may be doing other things behind the scenes without telling you.

right, so every idiot should know that it's a good idea to be able to see what a program is doing. just in case anything fishy is going on. usually such fishy actions today are spyware, but there's malware too like google and microcock's "flash must die" programs which pretty much brick your OS from running flash programs, even offline, thats malware. Where google is probably the king of spyware, being the world's largest snooping conglomerate.

So there comes a day when you want to make your own applications.

but making programs and applications in C languages is murder. It was intentionally designed that way to keep privatization of program making from becoming a reality, this was so they could put out a new game which only runs on a new operating system to tempt people into the upgrade of a worse and more invasive operating system, sometimes it's hardware too the best graphics card used to tempt people to sign up for Windows 15 which practically owns everything you write or otherwise make on your computer.

But yeah, that sux. They make it complicated with a steep learning curve and tutorials from all sorts of people who are just trolling on sites like stackexchange etc. because when you copy their code and compile it, it doesn't work. and it'd take an expert to find out why.

That's why we have python. because you don't have to compile python programs to run them. and you can easily get a printout of any and all error messages with a brief explanation of why it can't understand your code into a console window. which you can then look up online and maybe find something helpful.

Or in the case of python's TKinter (because there are microcock garble crapple rubes intentionally answering questions with broken or unmodifiable code on stackexchange because TKinter allows people to make applications, so again they don't want you to be able to do it.) you might find some submodule or subsubmodule that was not in any documentation for Tkinter, and though they use it in a terribly overcomplicated way on stack exchange (so that it'll be a pain to figure out how they were using it, so you wont be able to modify their code to fit a gap in your program) you still might be able to make something work because now you've discovered a new keyword to test.

They deserve a hardy exclamation of "PINGAS!" because thats all they are. microcock stooges.

With that said I have found no source for TKinter examples nor advice which was clear enough to be easily modified to fit random applications. Many work, like python's own "Hello World" tkinter example found in their code repository, but the slightest changes will make it cease to function and put out errors. PINGAS!es.

Lets start with Python Version, it makes a world of difference.

Myself? I was kinda forced by my software to use Python 2.6.2, but Python 2.7 has more available in Tkinter like the ttk module for making better more modern button graphics, so I would suggest that if you have a choice. Python 3, most of the code examples out there for Tkinter are written for Python 3. however python 3 has one glaring disadvantage to 2.7;

Python 3 does not have automatic module importation of any sort! the interpreter is written to essentially treat every module new or standard as an unknown at default, meaning you really need to specify and import every module you are going to use. In python 2.7 we don't have this problem, many Standard and well used modules are on a list and already imported silently in the interpreter at default waiting to be called. to the point in python 2.7 your first guess is to just start using it and see if it needs you to import it, the error will tell you if you need to. and if no error then you're good to go!

in example os and sys modules may not need to be imported, they are base level commonly used things that it knows are kinda always going to be needed for file and data access.

I would suggest 2.7 over 3 any day.

keep in mind if you import a module thats imported at default it wont always give an error, it might just be redundant code.

This brings us to importing modules, as far as I can tell Tkinter Does need to be imported.

but how to import it is important.

many of the documents you find will do
"import Tkinter as tk"

but TKinter has a submodule called Tikinter.Tk() if you do "import as tk" then you have to specify tk.Tk() every time you want to use it. it can also cause errors and inabilities in your program! things like image data are flushed shortly after use, so having a chain of commands longer than a chain of 2 arugments before you save the image data in a placeholder to be used later, will cause a loss of the data and give errors that it can;t find the image data when your bend goes to use it. so having to go through tk.something every damn time can really limit what you can do.

You will get errors if you have 2 import statements for the same module!!!

instead use:
"from Tkinter import *"

Python 3 cannot do this. because python 3 will complain that Tkinter is not already imported. where python 2.6 to 2.7 will happily Import Tkinter and it's subcomponents in this one argument because "from word import" automatically tells python 2 that "word" must be the name of a module, so it goes searching through modules in 1: the program's folder, 2: the python installation folder for "word" then grabs it and all of it's submodules.

Python 3 sux.

right so now that you did "from Tkinter import *" you don't have to do Tkinter.Tk() or tk.Tk(), you merely type Tk() and it knows what you mean because it accesses that submodule directly! saving 1 step in the process chain!

Next, most examples con you into thinking you MUST use a "class" or "function"s because they are used to java or C or some other language where they were taught to slap everything in a class for best result. And it will work, but as specified it becomes excruciatingly complicated very fast, because you need to manage everything through "self.definition =" and that creates an unneeded link in the process chain which could cause something to break. for example adding 2 widgets in the same frame could cause the class to fail epically where the process chain refuses to put the widget in the same frame or even the same window!. at which point when adding features to one of these complicated "class name(Frame):" code bends you'll either get errors, it ignores something further down in the bend, or you'll end up with like 15 windows, one somewhat correct one with each other widget, and some with just the title and no widgets at all.

again, declare "you PINGAS!" and move on when you see these examples on stack exchange. They are giving a specific example which is built to only work for the one thing, adding anything else will break it, and likely it limits a Tkinter.Frame module to that class AND WIDGET ALONE.. (meaning it sucks to be you if you wanted to make another frame with someething else in it!) again they are jackass PINGAS!es whose only goal as an industry specialist is to KEEP YOU OUT of the application market.

Right, So Tk() is called as the master of all windows you will make. So you should set it to an easily callable definition to Dot later. in example:
"PINGAS = Tk()"
some might call it root = Tk(), but you can call it whatever you want to be arrayed in your code everywhere.

Now there are several things which are per code run specific:

Title Tk().title() or in this case PINGAS.title() is used to make a title for the main bar of your window. an example could look like:
"PINGAS.title(string='A Diatribe about my PINGAS!, a Pushy, and Cum!')"

you can also do TK().iconbitmap("image location.ico") to set an image for the window's corner other than the ugly TK icon.

If you ever need to see usage instructions for something like "title" or "Button" and a list or their submodules and types you can do help(module name) like help(Button) in your document and run it, it will print out the info to the console window. it may be long. and the program will not close till you "enter" all the way to the bottom, but it'll have alot of information on things that might help you. in this case help(PINGAS.title) gives very little information, .title( self, string="title of this widget") it says "widget", so I assume you could apply a title to any widget and it'll be the window's title. but you can put multiple widgets in a window so we don't want to create conflicts. it is untested to use .title on a widget like Button.

So lets go through this, you have a window master which is Tk(), inside a window you can have any number of Frame objects, and in each frame object you can have 1: any number of subframes, and 2: practically any number of widgets.

lets cover frames and how to make them.

Tkinter calls Frame a widget, but it's a widget that can have other widgets in it, it's form is Frame(Widget), where Widget is the parent of the Frame. most frames support ["geometry"] = (X, Y) for controlling size of the window, if there are two geometry statements, only the first will work, others will be ignored. They also support ["text"] = "Text here", ["bg"] = '#hex color' or "color ex: white", ["font"] = i.e. ("Times New Roman", 20) and multiple others.

but if you are only using one frame, then everything will be placed underneath eachother at the bottom of each widget's length, this can get too long without a scrollbar essentially making a window too tall for the screen. good thing you can add a scrollbar widget on any frame.

But some widgets come with their own scrollbar, like the exterior modual (non Tkinter, is a regular python widget) ScrolledText.

"from ScrolledText import *"

ScrolledText has a submodule by the same name which can be added to a Tkinter window.

heres an Example:
mytext = ScrolledText(frame_definition)
mytext["wrap"] ='word'
mytext["width"] =100
mytext["height"] =50
mytext["bg"] = 'white'
mytext.pack(fill='both', expand=True, padx=8, pady=8)
mytext.insert('insert', definition_of_text_you_wrote)

lets go over this:
"mytext" is the definition name variable we assigned to this specific widget
"frame_definition" will be the variable/name we gave the frame
["wrap"] tells it to do text wrapping, it can be none, character or word (I'm not sure of how to tell it none or character, but word wrap is just "word" and I know it can do the others)
["width"] tells it how many fullsized text character widths the frame should have (Ignored if you set a Window Geometry and width of the widget is larger than the window geometry!)
["height"] tells it the how many TextLine widths the widget should be from top to bottom.
["bg"] tells it this widget's background color


.pack() this tells it to add it to a window with the frame variable/named in the widget ScrolledText(this_thing) inside the given frame. it also has options to expand the window or not, to fill(not sure what that means) and to add a padding on the sides of the widget on X and Y.

.insert() tells it what is being inserted, and then the thing itself, in this case you'd drop a definition linked to text.

your text definition will look like:

diatribe = '''\ all your text'''

then you'll insert diatribe into the scrolled text.

so long as you are adding things to the master frame of a window or any of the subframes, you are adding things to that window! so keep plopping your master frame into widgets(masterframe) and you're fine.

so, your code should look like:


WindowVariable = Tk()


framevariable = Frame(WindowVariable)

widgetvariable = Widget(framevariable)
widgetvariable['options'] = value
widgetvalue.pack(packing options)

well you must think you're some kinda genius now. but we need to get to images!

BitmapImage ONLY takes an X11 Bitmap image, this can be confusing if you don't know what that is, it's not a .bmp at all, it's a .xbm !

PhotoImage takes a few formats, HOWEVER in python 2.6 it's broken and only takes .gif !

EITHER of these modules will convert an image into data, then immediately lose it after the next statement in the code. I shit you not. this is why you need to keep statements short so there is no chance of a long chain of gotos such as tk.Widget() then it needs to go to tk find what that is, then search through that module and find Widget() and what to do with it. by then your image data is now flushed from memory. "PINGAS! YOU!". so you need to assign the data to something short and simple PRONTO.

"myimage = PhotoImage(file="directory/filename.gif")
boobies = myimage"

"but can't I just immediately use it like?

widgetvariable["image"] = myimage"

"error, pyimage# data not found" on run. you literally need to take the data from one variable and store and save it in another variable Fast, or it's gone..

"Question can I do:

window = Frame(PINGAS)
SubFrame = Frame(window)
secondsubframe = Frame(window)

and so on?"

yes, but unless you want secondsubframe directly below SubFrame you'll need a Grid Widget before the 2 frames. you'll also need to remember where to otherwidget.pack(framename), also remember to add a scrollbar widget to the frame.

and yes it's that simple, most widgets support images as backgrounds, but only as image data. also remember you may need to resize your image to fit the given size of the area. I'll be learning that tomorrow or such.

last you need to define a mainloop for the window master


that needs to go last, and things after that statement only run AFTER the windows close.

if you want to make a button to close a window it needs to be above the mainloop and could be like

mybutton = Button(framename)
mybutton["Command"] = PINGAS.destroy

you can also do Tk().quit instead of .destroy. .destroy ends widget and all it's children, so by specifying Tk() or PINGAS as we called it . destroy we are destroying all windows we made with this program. .quit is tempramental, it will exit the .mainloop of the thing that started it, so frame.quit will end the given frame's mainloop and continue on to whatever is next such as a .destroy for the whole window or all windows made by the script. no you cannot destroy other programs windows this way, not even the program you are programming from.

However in experience usually .quit produces errors WINDOWS ERROR MESSAGE "the program was destroyed in a strange way" OR; nothing happens!!, the window will not close from your button.quit!!!!! even with a .destroy after the mainloop! so.. just destroy it don't worry about using .quit unless you have to.

.destroy can be used on any widget as well! so you can get rid of a specific widget by doing widget.destroy instead of Tk().destroy

Animated images:

You'll want to use .gif, some people will make each separate frame it's own image and load them all as variables then swap them with complicated code. but with gif you can save the image using REPLACE and have each frame of the image be a frame of the animation. in Tkinter we can even tell it what order to play the frames in. However most optimized .gif images will not work because they use COMBINE, so if you load just 1 frame, then thats all you get, where COMBINE is an additive process using multiple frames data starting from frame 0 and going all the way upto the last frame adding them all together to display the outcome, Tkinter can't really handle this by default, you'd need to program this and find a way to store the data from the previous frameconglomerates and add the next frame to it, it's not impossible, I think the data of the image is merely represented by hex colors per pixel so you just add Hex to Hex I think python has a Hexadecimal module. but yeah if you are incontrol of the image's creation; then it's best if you use REPLACE and keep a record of 2 things, 1: the number of frames in the gif, 2: what's on each frame.

Python nor TKinter have a way to find how many frames are in a gif in some simple module (other than the built in SET index, but there is no GET Index, it's WRITE ONLY)! you'd have to use open(file.gif, 'r') and look for frame markers and .split("whatever character combo they use for frame markers") then get the length of the len(list[]) and subtract the header and the footer if they're not also frames. and that's the best you can do. but you'll need to use .quit then, and include a myfile = open() followed by myfile.close() after the mainloop for the given frame. OR create some other condition bend on which to call myfile.close() before the program ends.

Given all that info, this is how you animate an image with frame control on a button:

myimage = PhotoImage(file="file.gif" format="gif -index#)

you add a format= to the end, where you need to specify the format again followed by -index and then the actual number from frame 0 to the last frame, in example in a 3 frame gif you have indecies of 0, 1, and 2. there is no 3! Error!. this is why the first thing you need to know is how many frames are in the gif. if it's 100 frames then it's -index 0 to -index 99 no it will not automatically do this for you! you'll need to code it to increase the frame number after a delay in miliseconds! and then if you want it to loop you'll have to do if framenumber < 99: framenumber = framenumber+1, followed by if framenumber = 99: framenumber= 0.

Now it depends WHERE you're adding it to. for example a Button's image will not change without a Button EVENT to drive it! so you'll need to do:
myimage = PhotoImage(file="file.gif" format="gif -index 0)
imagedata = myimage
mybutton = Button(ParentName)
mybutton['image'] = imagedata

def ButtonFunctionname1(event):
[tab]global myimage
[tab]myimage = PhotoImage(file="file.gif" format="gif -index 1")
[tab]imagedata = myimage

mybutton.bind("<eventtype>", ButtonFunctionname1)

that's to control which frame is played. again if you were just playing all frames in order then you'd modify -index with a +1 on every run until it hits the max, storing the last used index number somewhere.
But let's explain this, starting with "def" this defines a function, sadly you can't get around using a function here. you define the name of the function after def then you must include (event) "event" tells the button that on it's button event it should do the prescribed action, this is separate from button["command"] so you can program your button to do a number of things at once this way without changing the fact that it forexample .destroys the window, this is perfect for things like "Save and Close" functions.

global, this is a python class it lets python know that whatever variable follows it should modify it's previous definition based on whatever happens in the bend(Especially and even when you leave the bend). this is the difference between it only showing then default imageframe vs whatever imageframe you're trying to replace it with! if you don't global the image's definition in the bend; then when you leave your function that definition will be taken from it's original unmodified definition.

Button.config(), .config() tells it you want to change some aspect of the button itself, this can be anything and more than 1 thing. you can config the image, the text, the background color, the fg (text color), the borderwidth, the padx, pady, the command; ANY BUTTON ATTRIBUTES separated by commas. Button.config(image= image definition, borderwidth = #, text = "PINGAS") etc.

.bind(), this tells a widget (any widget) that you want to bind an action to an event. where <eventtype> is the event you want to trigger the action comma the function name you want to run.
in example .bind("<Enter>", function) tells it that when the mouse pointer ENTERS the widget's area, run the function called "function()" but you need to leave off the () in the .bind statement.
There are a bunch of these preset understood events:

Alt The Alt key is held
Control The Ctrl key is held
Shift The Shift key is held
Any This modifier makes an event type general. For example, the event pattern <Any-KeyPress> applies to the keypress of any key.

The following table shows the most commonly used event types:
Type Name Description
36 Activate The state option of a widget changes from inactive to active.
4 Button One mouse button is pressed
5 ButtonRelease One mouse button is released
22 Configure The size of the widget is changed
37 Deactivate The state option of a widget changes from active to inactive.
17 Destroy A widget is being destroyed.
7 Enter The mouse pointer is moved into a visible part of a widget.
12 Expose Some part of the widget or application is visible after having been covered up by another window.
9 FocusIn The input focus was moved into a widget.
10 FocusOut The input focus was moved out of a widget.
2 KeyPress A key is pressed.
3 KeyRelease A key is released
8 Leave The mouse pointer is moved out of a widget.
19 Map A widget is being placed on a container e.g., calling the pack() or grid() method.
6 Motion The mouse pointer is moved entirely within a widget.
38 MouseWheel The user moved the mouse wheel up or down.
18 Unmap A widget is being unmapped and is no longer visible, for example when calling the grid_remove() method on the widget.
15 Visibility At least some part of the application window becomes visible on the screen.
Event Detail

The following table shows several ways to name keys:
.keysym .keycode .keysym_num Key
Alt_L 64 65513 The left-hand alt key
Alt_R 113 65514 The right-hand alt key
BackSpace 22 65288 backspace
Cancel 110 65387 break
Caps_Lock 66 65549 CapsLock
Control_L 37 65507 The left-hand control key
Control_R 109 65508 The right-hand control key
Delete 107 65535 Delete
Down 104 65364 ↓
End 103 65367 end
Escape 9 65307 esc
Execute 111 65378 SysReq
F1 67 65470 Function key F1
F2 68 65471 Function key F2
Fi 66+i 65469+i Function key Fi
F12 96 65481 Function key F12
Home 97 65360 home
Insert 106 65379 insert
Left 100 65361 ←
Linefeed 54 106 Linefeed (control-J)
KP_0 90 65438 0 on the keypad
KP_1 87 65436 1 on the keypad
KP_2 88 65433 2 on the keypad
KP_3 89 65435 3 on the keypad
KP_4 83 65430 4 on the keypad
KP_5 84 65437 5 on the keypad
KP_6 85 65432 6 on the keypad
KP_7 79 65429 7 on the keypad
KP_8 80 65431 8 on the keypad
KP_9 81 65434 9 on the keypad
KP_Add 86 65451 + on the keypad
KP_Begin 84 65437 The center key (same key as 5) on the keypad
KP_Decimal 91 65439 Decimal (.) on the keypad
KP_Delete 91 65439 delete on the keypad
KP_Divide 112 65455 / on the keypad
KP_Down 88 65433 ↓ on the keypad
KP_End 87 65436 end on the keypad
KP_Enter 108 65421 enter on the keypad
KP_Home 79 65429 home on the keypad
KP_Insert 90 65438 insert on the keypad
KP_Left 83 65430 ← on the keypad
KP_Multiply 63 65450 × on the keypad
KP_Next 89 65435 PageDown on the keypad
KP_Prior 81 65434 PageUp on the keypad
KP_Right 85 65432 → on the keypad
KP_Subtract 82 65453 - on the keypad
KP_Up 80 65431 ↑ on the keypad
Next 105 65366 PageDown
Num_Lock 77 65407 NumLock
Pause 110 65299 pause
Print 111 65377 PrintScrn
Prior 99 65365 PageUp
Return 36 65293 Enter key
Right 102 65363 →
Scroll_Lock 78 65300 ScrollLock
Shift_L 50 65505 The left-hand shift key
Shift_R 62 65506 The right-hand shift key
Tab 23 65289 The tab key

You can have MULTIPLE events in one "<>" separating them with dashes "-" in example <Alt-Control-KeyPress-KP_Delete> control and alt are held, and delete is pressed once. all must be true or it will not run the function after it.



got any?

His name is not Robert Paulsen, His name is Gregory Matthew Bruni, he won so hard.

Spoiler: show

This expresses me perfectly. You have been warned. yes I'm nearly bald, and? I'll leave a hot stinky poop in your favourite boot. But I have far more planned I assure you.

Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.

Sat Sep 09, 2023 8:10 pm
Profile E-mail
Display posts from previous:  Sort by  
Reply to topic   [ 1 post ] 

Similar topics

Application Mod
Forum: Approved
Author: nexusvalhees
Replies: 0
Application for 18+
Forum: Approved
Author: RuDe
Replies: 0
Cool open source chat application.
Forum: ./General Spam
Author: Lime
Replies: 4
Tutorial: geting a ftp server running on your home computer
Forum: ./General Spam
Author: cluelessfurball
Replies: 0

Who is online

Users browsing this forum: No registered users and 1 guest

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Mods Database :: Imprint :: Crawler Feeds :: Reset blocks
Designed by STSoftware for PTF.

Portal XL 5.0 ~ Premod 0.3 phpBB SEO