I have these functions in my python script the top three of them being related to tkinter and the bottom one being a process not related to the Tk window , how can i execute the pixels() function parallel to the tkinter functions ?
top.mainloop()
C.pack()
colors()
pixels()
Try tkinter's after method. Documentation here.
I see a lot of people who are looking for "running function along side tkinter mainloop" but cannot find after while researching. I guess it just isn't talked about much in documentation to show up on searches (besides SO questions).
Related
Hi I was wondering if anyone could answer my question, how would I go about making a game with graphics in python instead of text based games.
I'm only new though so if it involves another programming language then I'm probably can't do it yet.
Use tkinter module inside of python. To do this simply add from tkinter import * at the start of your program and open a window and use a mainloop to close it at the end. You can research how to use tkinter online on various different websites. I would suggest effbot as it's very useful for tkinter basics.
I would recommend using the tkinter library. You can makes games with graphics instead of text. One example would be here. And it is just Python :)
Trying my first foray into Python and TkInter, and have already gotten some great help here. However, I'm hitting another wall and hoping somebody here can give me a lift to the other side.
My app is pretty simple, conceptually. Just a page with 10-20 rows of labels next to text boxes and option menus (with about 25 items, all identical).
All I want to do is add SUBMIT and QUIT buttons. But, as with most things I'm trying, I get errors every step of they way.
SubmitButton = Button(root, text="Submit", command=greetings)
SubmitButton.place(x=700, y=600)
def greetings():
print("Hello there")
The error (on this particular example) is
NameError: name 'greetings' is not defined
But isn't that what def greetings() does?
Most of the examples I'm seeing refer to things like self/master/frame, but I don't have any of that stuff in my script (at least not explicitly).
Isn't there some easy way to create a custom function and call that function on the click event? Or do I have to go back to the drawing board and try to understand how to use classes and such?
I'm using Python 3.6 and Spyder if that makes any difference.
Thank you for any guidance.
I'm not sure why it's not printing to the console on button push and without seeing your updated snippet I wouldn't be able to tell.
However, the below snippet does work for me and should demonstrate how to handle custom functions on buttons:
from tkinter import *
root = Tk()
def greetings():
print("Hello there")
SubmitButton = Button(root, text="Submit", command=greetings)
SubmitButton.pack()
Also, to answer your question. No, you don't need to use classes or any form of object orientation. However, when it comes to tkinter (and yes this is heavily opinion based) it is often easier to use classes, there are countless reasons why this is and there are plenty of questions and answers on and off this site as to why this is.
This answer probably has the best explanation as to why this is.
I'm wondering how difficult it will be to use invoke matplotlib from a Tcl interpreter and plot to a Tk canvas created on the Tcl side.
I'm wondering what the best way to do this is.
I'm guessing I'll have to create a python interpreter, pass the canvas handle from the Tcl side to python and make use of the C API in both languages. Or is there a more elegant way?
Getting this integration right won't be easy. However, here's what I'm thinking about:
Connecting Python and Tcl
You can run Python inferior to Tcl apparently. According to this wiki page, there's a package called tclpython which can do the basic integration work for you, and the page linked to appears live. The code appears to be here, though it might need some work to make it build. (I've never tried.)
Connecting matplotlib and Tk
You can make matplotlib draw on a Tkinter window, and as long as you can make that Tkinter window with the right options, it will show up. The key is that the underlying system window IDs can be found out from Tk with winfo id $nameOfTheWindow. If you create a frame with the -container option set to true (which turns off some things and turns on a few others; you'll need to set the size explicitly) then that particular frame will be suitable for use with TkAgg on the python/matplotlib side. The key will be to make a toplevel on that side that has the -use option set to the ID retrieved from winfo id. You probably need to make sure that the python side is running its rendering in a separate thread to the outer Tcl/Tk to make the event handling work right (unless you're keen on doing deep event loop hacking; the situation is that you're actually going to have Tcl/Tk inside Python inside Tcl/Tk, as Tkinter works by delegating to a subordinate Tcl/Tk, and getting all this glued together right will be “a bit tricky”).
If that doesn't work, get matplotlib to render as an image (GIF or PNG; the latter is preferred if you've got Tk 8.6) as you can just show that easily via a photo image. This is definitely going to be possible to do without thread games; it's just passing around pure data. Probably slower and not interactive, but that might not matter for what you're doing, and it is easier in the simple case.
You will probably need the second approach if you're on Windows or OSX, as Tk there doesn't actually use X11. (Unless you're using one of the more perverse configuration options, of course.)
I have this following Python Tkinter code which redraw the label every 10 second. My question is , to me it seems like it is drawing the new label over and over again over the old label. So, eventually, after a few hours there will be hundreds of drawing overlapping (at least from what i understand). Will this use more memory or cause problem?
import Tkinter as tk
import threading
def Draw():
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=1)
frame.place(x=10,y=10)
text=tk.Label(frame,text='HELLO')
text.pack()
def Refresher():
print 'refreshing'
Draw()
threading.Timer(10, Refresher).start()
root=tk.Tk()
Refresher()
root.mainloop()
Here in my example, i am just using a single label.I am aware that i can use textvariable to update the text of the label or even text.config. But what am actually doing is to refresh a grid of label(like a table)+buttons and stuffs to match with the latest data available.
From my beginner understanding, if i wrote this Draw() function as class, i can destroy the frame by using frame.destroy whenever i execute Refresher function. But the code i currently have is written in functions without class ( i don't wish to rewrite the whole code into class).
The other option i can think of is to declare frame in the Draw() as global and use frame.destroy() ( which i reluctant to do as this could cause name conflict if i have too many frames (which i do))
If overdrawing over the old drawing doesn't cause any problem (except that i can't see the old drawing), i can live with that.
These are all just my beginner thoughts. Should i destroy the frame before redraw the updated one? if so, in what way should i destroy it if the code structure is just like in my sample code? Or overdrawing the old label is fine?
EDIT
Someone mentioned that python tkinter is not thread safe and my code will likely to fail randomly.
I actually took this link as a reference to use threading as my solution and i didn't find anything about thread safety in that post.
I am wondering what are the general cases that i should not use threading and what are the general cases i could use threading?
The correct way to run a function or update a label in tkinter is to use the after method. This puts an event on the event queue to be executed at some time in the future. If you have a function that does some work, then puts itself back on the event queue, you have created something that will run forever.
Here's a quick example based on your example:
import Tkinter as tk
import time
def Draw():
global text
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=1)
frame.place(x=10,y=10)
text=tk.Label(frame,text='HELLO')
text.pack()
def Refresher():
global text
text.configure(text=time.asctime())
root.after(1000, Refresher) # every second...
root=tk.Tk()
Draw()
Refresher()
root.mainloop()
There are a lot of things I would change about that program from a coding style point of view, but I wanted to keep it as close to your original question as possible. The point is, you can use after to call a function that updates the label without having to create new labels. Plus, that function can arrange for itself to be called again at some interval. In this example I picked one second just so that the effect is easier to see.
You also asked "I am wondering what are the general cases that i should not use threading and what are the general cases i could use threading?"
To put a blunt point on it, you should never use threading if you have to ask a question about when to use threading. Threading is an advanced technique, it is complicated, and it easy to get wrong. It's quite possible for threading to make your program slower rather than faster. It has subtle consequences, such as your programs failing mysteriously if you do things that aren't thread safe.
To be more specific to your situation: you should avoid using threads with tkinter. You can use them, but you can't access widgets from these other threads. If you need to do something with a widget, you must put an instruction in a thread-safe queue, and then in the main thread you need to periodically check that queue to see if there's an instruction to be processed. There are examples of that on this website if you search for them.
If all that sounds complicated, it is. For most of the GUIs you write, you won't need to worry about that. If you can take large processes and break them down into chunks that execute in 100 ms or less, you only need after, and never need threads.
To allow the cleanup with minimal code changes, you could pass previous frames explicitly:
import Tkinter as tk
def Draw(oldframe=None):
frame = tk.Frame(root,width=100,height=100,relief='solid',bd=1)
frame.place(x=10,y=10)
tk.Label(frame, text='HELLO').pack()
frame.pack()
if oldframe is not None:
oldframe.destroy() # cleanup
return frame
def Refresher(frame=None):
print 'refreshing'
frame = Draw(frame)
frame.after(10000, Refresher, frame) # refresh in 10 seconds
root = tk.Tk()
Refresher()
root.mainloop()
Is there any way in python's Tkinter, bwidget or anything similar to show a Windwos' default progress bar?
I already know the bwidget.ProgressBar, but it produces an ugly progress bar while I mean showing a valid windows progress bar - the green, glowing one:
http://imageshack.us/photo/my-images/853/unledtph.png/
I need it because that way Windows will automatically show the progress of my program in the task bar. Plus, it looks better.
If you are using a modern (2.7+) version of Tkinter you can try the ttk.ProgressBar which is part of Tkinter.
You can install the pyttk module separately.
from Tkinter import *
import ttk
root = Tk()
progressbar = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
progressbar.pack(side="bottom")
progressbar.start()
root.mainloop()
As far as the taskbar functionality, that is not available in Tkinter yet (at least to the best of my knowledge). You'll need to make use of the Windows API for that. Although this question is for PyQt, the answers should prove helpful. Hope it gets you started.
The simplest solution would appear to be to use themed Tk with the tkinter.ttk module included in Python 2.7 and 3.1. The Progressbar widget is what you want.
Since you appear to be considering other frameworks you might look at Qt or wxWidgets which look native and have excellent Python bindings.