这个简单的脚本我有以下问题:
from Tkinter import *
root = Tk()
while 1:
pass
我认为,在第二行之后,每个人都会期望出现一个Tkinter窗口。但事实并非如此! 如果我将这一行放入Python控制台(没有无限循环),它就可以工作。
[我想在这里添加一张图片,但是因为我是新手,所以我可以: - ()
但是运行脚本(双击Windows资源管理器中的* .py文件)只会产生一个空的Python控制台!
背景: 其实我想用Snack for Python。这是基于Tkinter。这意味着我必须首先创建一个Tk()实例。在Python控制台中一切正常。但我想用至少一个Python脚本编写一个更大的程序,因此我不能每次都将整个程序输入控制台: - )
我已经安装了Python 2.7和Tcl / Tk 8.5(请记住:它可以在控制台中运行)
编辑:所以这是我的解决方案:
首先,我创建了一个类CSoundPlayer:
from Tkinter import*
import tkSnack
class CSoundPlayer:
def __init__(self, callbackFunction):
self.__activated = False
self.__callbackFunction = callbackFunction
self.__sounds = []
self.__numberOfSounds = 0
self.__root = Tk()
self.__root.title("SoundPlayer")
tkSnack.initializeSnack(self.__root)
def __mainFunction(self):
self.__callbackFunction()
self.__root.after(1, self.__mainFunction)
pass
def activate(self):
self.__activated = True
self.__root.after(1, self.__mainFunction)
self.__root.mainloop()
def loadFile(self, fileName):
if self.__activated:
self.__sounds.append(tkSnack.Sound(load=fileName))
self.__numberOfSounds += 1
# return the index of the new sound
return self.__numberOfSounds - 1
else:
return -1
def play(self, soundIndex):
if self.__activated:
self.__sounds[soundIndex].play()
else:
return -1
然后,应用程序本身必须在类中实现,因此在移交给CSoundPlayer()构造函数时定义main():
class CApplication:
def __init__(self):
self.__programCounter = -1
self.__SoundPlayer = CSoundPlayer(self.main)
self.__SoundPlayer.activate()
def main(self):
self.__programCounter += 1
if self.__programCounter == 0:
self.__sound1 = self.__SoundPlayer.loadFile("../mysong.mp3")
self.__SoundPlayer.play(self.__sound1)
# here the cyclic code starts:
print self.__programCounter
CApplication()
如您所见,mainloop()不是在构造函数中调用,而是在activate()方法中调用。这是因为CApplication永远不会获得对CSoundPlayer对象的引用,因为它停留在mainloop中。 CApplication类的代码本身会产生很多开销。实际的“应用程序代码”放在CApplication.main()中 - 代码只能通过程序计数器控制一次。
现在我将它放到下一级并将MIDI设备的轮询过程放在CApplication.main()中。因此,我将使用MIDI命令作为播放声音文件的触发器。我希望性能足以适应延迟。
您有任何优化建议吗?
答案 0 :(得分:1)
您必须启动事件循环。没有事件循环,tkinter无法实际绘制窗口。移除while
循环并将其替换为mainloop
:
from Tkinter import *
root = Tk()
root.mainloop()
如果您需要进行轮询(如问题的评论中所述),请编写一个轮询的函数,并使用after
定期运行该函数:
def poll():
<do the polling here>
# in 100ms, call the poll function again
root.after(100, poll)
您在控制台中不需要主循环的原因取决于您对控制台&#34;的含义。在IDLE和其他一些交互式解释器中,tkinter在交互式运行时有一种特殊的模式,不需要你调用mainloop。本质上,mainloop是控制台输入循环。