Python 在 Tkinter 中循环?
Python While loop in Tkinter?
我是 Python 的新手(主要是编程),我正在从事一个项目,以输出信标莫尔斯电码并在信标之间收听莫尔斯电码。
我有信标工作,可能不是最好的代码,但它确实有效,但是当循环开始时,Tkinter 屏幕冻结并且停止信标按钮在所有信标完成之前不起作用。
我想无限地 运行 信标,只需使用停止信标按钮来停止它,但到目前为止我似乎无法弄清楚如何停止循环。
#!usr/bin/env python
import sys
import re
import tkMessageBox
from Tkinter import *
import pygame
import time
CODE = {'A': '.-', 'B': '-...', 'C': '-.-.',
'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..',
'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---',
'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-',
'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..',
'0': '-----', '1': '.----', '2': '..---',
'3': '...--', '4': '....-', '5': '.....',
'6': '-....', '7': '--...', '8': '---..',
'9': '----.'
}
ONE_UNIT = 0.5
THREE_UNITS = 3 * ONE_UNIT
SEVEN_UNITS = 7 * ONE_UNIT
PATH = 'morse_sound_files/'
def verify(string):
keys = CODE.keys()
for char in string:
if char.upper() not in keys and char != ' ':
sys.exit('Error the charcter ' + char + ' cannot be translated to Morse Code')
beaconout = ''
beaconTEXT = 'this is text that is default'
def ask_quit():
if tkMessageBox.askokcancel("Quit", "are you sure you want to quit?"):
root.destroy()
def getinput():
incomingTEXT = incoming.get()
outboundTEXT = outbound.get()
beaconTEXT = beaconmessage.get(1.0,"end")
beaconout = outboundTEXT+" "+outboundTEXT+" "+outboundTEXT+" "+beaconTEXT+""+incomingTEXT
print beaconout
beaconout = beaconout.replace('\n', ' ')
print beaconout
print 'Welcome to Alphabet to Morse Code Translator v.01'
msg = beaconout
#verify(msg)
print
pygame.init()
for char in msg:
if char == ' ':
print ' '*7,
time.sleep(SEVEN_UNITS)
else:
print CODE[char.upper()],
pygame.mixer.music.load(PATH + char.upper() + '_morse_code.ogg')
pygame.mixer.music.play()
time.sleep(THREE_UNITS)
root = Tk()
root.geometry("800x600+300+300")
frame = Frame(root, width=1000, height=600)
label1 = Label(root, text="To: Call Sign:")
label2 = Label(root, text="Your Call Sign:")
label3 = Label(root, text="Enter your message:")
outbound = StringVar()
outboundcallsign = Entry(root, textvariable=outbound)
incoming = StringVar()
inboundcallsign = Entry(root, textvariable=incoming)
beacon = StringVar()
beaconmessage = Text(root, height=1, width=30)
label1.grid(row=1, sticky=E)
label2.grid(row=2, sticky=E)
label3.grid(row=3, sticky=E)
outboundcallsign.grid(row=1, column=1)
inboundcallsign.grid(row=2, column=1)
beaconmessage.grid(row=4, columnspan=4)
cbox = Checkbutton(root, text="message is ready to beacon?")
cbox.grid(columnspan=2)
submitbut = Button(root,text="Start Beacon", command = getinput)
submitbut.grid(row=14,column=1)
submitbut.bind("<Button-1>")
cancelbut = Button(root,text="Stop Beacon", command=ask_quit)
cancelbut.grid(row=14, column=3)
root.mainloop()
"I would like to run the beacon infinitely and just use the stop beacon button to stop"
运行 "Beacon" 代码在一个单独的进程中,因为你想同时做两件事,[1] 信标代码和 [2] 检查按钮按下(尽管它可能会找到一种创造性的方法来使用 "after" 检查按钮是否按下,恕我直言,这样做更明显也更省事)。退出按钮将取消该过程。为简单起见,此示例使用计数器而不是信标代码。
from multiprocessing import Process
from functools import partial
try:
import Tkinter as tk ## Python 2.x
except:
import tkinter as tk ## Python 3.x
class ProgressBar():
def __init__(self, root):
self.root=root
self.root.geometry("75x50+900+100")
self.ctr=1
def counter(self):
""" a separate process in a separate GUI
"""
self.top_count=tk.Toplevel(self.root)
self.top_count.geometry("75x50+750+50")
self.label_ctr = tk.IntVar()
self.label_ctr.set(self.ctr)
label = tk.Label(self.top_count, textvariable=self.label_ctr)
label.pack()
self.change_counter()
def change_counter(self):
self.ctr += 1
self.label_ctr.set(self.ctr)
self.top_count.after(750, self.change_counter)
def stop_process(process_id, PB):
process_id.terminate()
PB.top_count.destroy() ## destroy Toplevel to stop "after"
## shut down Tkinter
##root.quit()
root = tk.Tk()
PB=ProgressBar(root)
pr1=Process(target=PB.counter(), args=())
pr1.start()
tk.Button(root, text="Exit", bg="orange",
command=partial(stop_process, pr1, PB)).pack()
root.mainloop()
如果你不想破坏 Toplevel 那么你可以使用一个变量,在下面这两个函数被改变的情况下,ctr > 0 但是要在两个进程之间进行通信需要一个管理器字典或列表。
def change_counter(self):
self.ctr += 1
self.label_ctr.set(self.ctr)
if self.ctr > 0:
self.top_count.after(750, self.change_counter)
def stop_process(pr1, PB):
PB.ctr = -10
pr1.terminate()
## PB.top_count.destroy()
我是 Python 的新手(主要是编程),我正在从事一个项目,以输出信标莫尔斯电码并在信标之间收听莫尔斯电码。
我有信标工作,可能不是最好的代码,但它确实有效,但是当循环开始时,Tkinter 屏幕冻结并且停止信标按钮在所有信标完成之前不起作用。
我想无限地 运行 信标,只需使用停止信标按钮来停止它,但到目前为止我似乎无法弄清楚如何停止循环。
#!usr/bin/env python
import sys
import re
import tkMessageBox
from Tkinter import *
import pygame
import time
CODE = {'A': '.-', 'B': '-...', 'C': '-.-.',
'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..',
'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---',
'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-',
'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..',
'0': '-----', '1': '.----', '2': '..---',
'3': '...--', '4': '....-', '5': '.....',
'6': '-....', '7': '--...', '8': '---..',
'9': '----.'
}
ONE_UNIT = 0.5
THREE_UNITS = 3 * ONE_UNIT
SEVEN_UNITS = 7 * ONE_UNIT
PATH = 'morse_sound_files/'
def verify(string):
keys = CODE.keys()
for char in string:
if char.upper() not in keys and char != ' ':
sys.exit('Error the charcter ' + char + ' cannot be translated to Morse Code')
beaconout = ''
beaconTEXT = 'this is text that is default'
def ask_quit():
if tkMessageBox.askokcancel("Quit", "are you sure you want to quit?"):
root.destroy()
def getinput():
incomingTEXT = incoming.get()
outboundTEXT = outbound.get()
beaconTEXT = beaconmessage.get(1.0,"end")
beaconout = outboundTEXT+" "+outboundTEXT+" "+outboundTEXT+" "+beaconTEXT+""+incomingTEXT
print beaconout
beaconout = beaconout.replace('\n', ' ')
print beaconout
print 'Welcome to Alphabet to Morse Code Translator v.01'
msg = beaconout
#verify(msg)
print
pygame.init()
for char in msg:
if char == ' ':
print ' '*7,
time.sleep(SEVEN_UNITS)
else:
print CODE[char.upper()],
pygame.mixer.music.load(PATH + char.upper() + '_morse_code.ogg')
pygame.mixer.music.play()
time.sleep(THREE_UNITS)
root = Tk()
root.geometry("800x600+300+300")
frame = Frame(root, width=1000, height=600)
label1 = Label(root, text="To: Call Sign:")
label2 = Label(root, text="Your Call Sign:")
label3 = Label(root, text="Enter your message:")
outbound = StringVar()
outboundcallsign = Entry(root, textvariable=outbound)
incoming = StringVar()
inboundcallsign = Entry(root, textvariable=incoming)
beacon = StringVar()
beaconmessage = Text(root, height=1, width=30)
label1.grid(row=1, sticky=E)
label2.grid(row=2, sticky=E)
label3.grid(row=3, sticky=E)
outboundcallsign.grid(row=1, column=1)
inboundcallsign.grid(row=2, column=1)
beaconmessage.grid(row=4, columnspan=4)
cbox = Checkbutton(root, text="message is ready to beacon?")
cbox.grid(columnspan=2)
submitbut = Button(root,text="Start Beacon", command = getinput)
submitbut.grid(row=14,column=1)
submitbut.bind("<Button-1>")
cancelbut = Button(root,text="Stop Beacon", command=ask_quit)
cancelbut.grid(row=14, column=3)
root.mainloop()
"I would like to run the beacon infinitely and just use the stop beacon button to stop"
运行 "Beacon" 代码在一个单独的进程中,因为你想同时做两件事,[1] 信标代码和 [2] 检查按钮按下(尽管它可能会找到一种创造性的方法来使用 "after" 检查按钮是否按下,恕我直言,这样做更明显也更省事)。退出按钮将取消该过程。为简单起见,此示例使用计数器而不是信标代码。
from multiprocessing import Process
from functools import partial
try:
import Tkinter as tk ## Python 2.x
except:
import tkinter as tk ## Python 3.x
class ProgressBar():
def __init__(self, root):
self.root=root
self.root.geometry("75x50+900+100")
self.ctr=1
def counter(self):
""" a separate process in a separate GUI
"""
self.top_count=tk.Toplevel(self.root)
self.top_count.geometry("75x50+750+50")
self.label_ctr = tk.IntVar()
self.label_ctr.set(self.ctr)
label = tk.Label(self.top_count, textvariable=self.label_ctr)
label.pack()
self.change_counter()
def change_counter(self):
self.ctr += 1
self.label_ctr.set(self.ctr)
self.top_count.after(750, self.change_counter)
def stop_process(process_id, PB):
process_id.terminate()
PB.top_count.destroy() ## destroy Toplevel to stop "after"
## shut down Tkinter
##root.quit()
root = tk.Tk()
PB=ProgressBar(root)
pr1=Process(target=PB.counter(), args=())
pr1.start()
tk.Button(root, text="Exit", bg="orange",
command=partial(stop_process, pr1, PB)).pack()
root.mainloop()
如果你不想破坏 Toplevel 那么你可以使用一个变量,在下面这两个函数被改变的情况下,ctr > 0 但是要在两个进程之间进行通信需要一个管理器字典或列表。
def change_counter(self):
self.ctr += 1
self.label_ctr.set(self.ctr)
if self.ctr > 0:
self.top_count.after(750, self.change_counter)
def stop_process(pr1, PB):
PB.ctr = -10
pr1.terminate()
## PB.top_count.destroy()