어떻게 Tkinter의 이벤트 루프와 함께 자신의 코드를 실행합니까?
제 남동생은 이제 막 프로그래밍에 입문한 참입니다. 그리고 그의 사이언스 페어 프로젝트를 위해 하늘에 있는 새떼의 시뮬레이션을 하고 있습니다.그는 대부분의 코드를 작성했고, 그것은 잘 작동하지만, 새들은 매 순간 움직여야 합니다.
하지만 Tkinter는 자체 이벤트 루프 시간을 독차지하므로 코드가 실행되지 않습니다.하고있다root.mainloop()
실행, 실행 및 계속 실행되며 실행되는 것은 이벤트 처리기뿐입니다.
그의 코드를 메인 루프와 나란히 실행할 수 있는 방법이 있습니까(멀티스레딩이 없으면 혼란스럽고 단순하게 유지되어야 합니다)? 그렇다면 무엇입니까?
지금, 그는 그의 머리를 묶고, 추악한 해킹을 생각해냈습니다.move()
에 대한 기능.<b1-motion>
그래서 그가 버튼을 누르고 마우스를 움직이는 한, 그것은 작동합니다.하지만 더 좋은 방법이 있을 겁니다.
사용after
의 방법Tk
객체:
from tkinter import *
root = Tk()
def task():
print("hello")
root.after(2000, task) # reschedule event in 2 seconds
root.after(2000, task)
root.mainloop()
다음은 다음과 같은 선언과 문서입니다.after
방법:
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""
Bjorn이 게시한 솔루션은 내 컴퓨터에 "RuntimeError: Calling Tcl from other appartment" 메시지를 표시합니다(RedHat Enterprise 5, python 2.6.1).Bjorn은 제가 확인한 한 곳에 따르면 Tkinter와의 잘못된 스레드 처리는 예측할 수 없고 플랫폼에 따라 다르기 때문에 이 메시지를 받지 못했을 수 있습니다.
문제는 그것인 것 같습니다.app.start()
앱에 TK 요소가 포함되어 있기 때문에 TK에 대한 참조로 간주됩니다.나는 이것을 교체하여 고쳤습니다.app.start()
와 함께self.start()
안에서.__init__
또한 모든 Tk 참조가 호출하는 함수 내부에 있거나 호출하는 함수가 호출하는 함수 내부에 있도록 만들었습니다.mainloop()
(이는 "다른 아파트" 오류를 방지하기 위해 매우 중요합니다.)
마지막으로 사용자가 Tk 창을 닫으면 프로그램이 오류와 함께 종료되므로 콜백이 있는 프로토콜 핸들러를 추가했습니다.
개정된 코드는 다음과 같습니다.
# Run tkinter code in another thread
import tkinter as tk
import threading
class App(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
def callback(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.callback)
label = tk.Label(self.root, text="Hello World")
label.pack()
self.root.mainloop()
app = App()
print('Now we can continue running code while mainloop runs!')
for i in range(100000):
print(i)
시뮬레이션에서와 같이 자신의 루프를 작성할 때(내 생각에는),update
하는 일을 하는 기능mainloop
수행: 변경 사항으로 창을 업데이트하지만 루프에서 수행합니다.
def task():
# do something
root.update()
while 1:
task()
다른 옵션은 tkinter가 별도의 스레드에서 실행되도록 하는 것입니다.한 가지 방법은 다음과 같습니다.
import Tkinter
import threading
class MyTkApp(threading.Thread):
def __init__(self):
self.root=Tkinter.Tk()
self.s = Tkinter.StringVar()
self.s.set('Foo')
l = Tkinter.Label(self.root,textvariable=self.s)
l.pack()
threading.Thread.__init__(self)
def run(self):
self.root.mainloop()
app = MyTkApp()
app.start()
# Now the app should be running and the value shown on the label
# can be changed by changing the member variable s.
# Like this:
# app.s.set('Bar')
하지만 조심하세요, 멀티 스레드 프로그래밍은 어렵고 자신의 발을 쏘는 것은 정말 조심하세요.예를 들어 위 샘플 클래스의 멤버 변수를 변경할 때는 Tkinter의 이벤트 루프를 방해하지 않도록 주의해야 합니다.
이것은 GPS 리더와 데이터 발표자가 될 첫 번째 작동 버전입니다.Tkinter는 오류 메시지가 너무 적은 매우 취약한 것입니다.그것은 물건을 올려놓지도 않고, 왜 그런지도 말하지도 않습니다.좋은 위지위그 폼 개발자로부터 오는 것은 매우 어렵습니다.어쨌든, 이것은 1초에 10번 작은 루틴을 실행하고 양식에 정보를 제공합니다.그렇게 되기까지 시간이 좀 걸렸습니다.타이머 값을 0으로 설정하려고 해도 폼이 나타나지 않았습니다.머리가 아파요! 초당 10번 이상이면 충분해요.다른 사람에게 도움이 되길 바랍니다.마이크 모로
import tkinter as tk
import time
def GetDateTime():
# Get current date and time in ISO8601
# https://en.wikipedia.org/wiki/ISO_8601
# https://xkcd.com/1179/
return (time.strftime("%Y%m%d", time.gmtime()),
time.strftime("%H%M%S", time.gmtime()),
time.strftime("%Y%m%d", time.localtime()),
time.strftime("%H%M%S", time.localtime()))
class Application(tk.Frame):
def __init__(self, master):
fontsize = 12
textwidth = 9
tk.Frame.__init__(self, master)
self.pack()
tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
text='Local Time').grid(row=0, column=0)
self.LocalDate = tk.StringVar()
self.LocalDate.set('waiting...')
tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
textvariable=self.LocalDate).grid(row=0, column=1)
tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
text='Local Date').grid(row=1, column=0)
self.LocalTime = tk.StringVar()
self.LocalTime.set('waiting...')
tk.Label(self, font=('Helvetica', fontsize), bg = '#be004e', fg = 'white', width = textwidth,
textvariable=self.LocalTime).grid(row=1, column=1)
tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
text='GMT Time').grid(row=2, column=0)
self.nowGdate = tk.StringVar()
self.nowGdate.set('waiting...')
tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
textvariable=self.nowGdate).grid(row=2, column=1)
tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
text='GMT Date').grid(row=3, column=0)
self.nowGtime = tk.StringVar()
self.nowGtime.set('waiting...')
tk.Label(self, font=('Helvetica', fontsize), bg = '#40CCC0', fg = 'white', width = textwidth,
textvariable=self.nowGtime).grid(row=3, column=1)
tk.Button(self, text='Exit', width = 10, bg = '#FF8080', command=root.destroy).grid(row=4, columnspan=2)
self.gettime()
pass
def gettime(self):
gdt, gtm, ldt, ltm = GetDateTime()
gdt = gdt[0:4] + '/' + gdt[4:6] + '/' + gdt[6:8]
gtm = gtm[0:2] + ':' + gtm[2:4] + ':' + gtm[4:6] + ' Z'
ldt = ldt[0:4] + '/' + ldt[4:6] + '/' + ldt[6:8]
ltm = ltm[0:2] + ':' + ltm[2:4] + ':' + ltm[4:6]
self.nowGtime.set(gdt)
self.nowGdate.set(gtm)
self.LocalTime.set(ldt)
self.LocalDate.set(ltm)
self.after(100, self.gettime)
#print (ltm) # Prove it is running this and the external code, too.
pass
root = tk.Tk()
root.wm_title('Temp Converter')
app = Application(master=root)
w = 200 # width for the Tk root
h = 125 # height for the Tk root
# get display screen width and height
ws = root.winfo_screenwidth() # width of the screen
hs = root.winfo_screenheight() # height of the screen
# calculate x and y coordinates for positioning the Tk root window
#centered
#x = (ws/2) - (w/2)
#y = (hs/2) - (h/2)
#right bottom corner (misfires in Win10 putting it too low. OK in Ubuntu)
x = ws - w
y = hs - h - 35 # -35 fixes it, more or less, for Win10
#set the dimensions of the screen and where it is placed
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.mainloop()
언급URL : https://stackoverflow.com/questions/459083/how-do-you-run-your-own-code-alongside-tkinters-event-loop
'source' 카테고리의 다른 글
Spring Batch에서 여러 데이터 소스 사용 (0) | 2023.08.15 |
---|---|
CSS 필터만 사용하여 검은색을 임의의 색상으로 변환하는 방법 (0) | 2023.08.15 |
MariaDB / 파일 키 관리 암호화:키 파일에 구문 오류가 발생 (0) | 2023.08.15 |
jQuery의 ajax crossDomain 속성을 사용하시겠습니까? (0) | 2023.08.15 |
어떻게 하면 jQuery가 유효한 json으로 표현되는 내 오류 응답을 구문 분석할 수 있습니까? (0) | 2023.08.15 |