【发布时间】:2015-07-06 23:12:45
【问题描述】:
我对这个简单的脚本有以下问题:
from Tkinter import *
root = Tk()
while 1:
pass
我认为,在第 2 行之后,每个人都希望出现一个 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
然后,应用程序本身必须在一个类中实现,因此 main() 是在移交给 CSoundPlayer() 构造函数时定义的:
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 对象的引用,因为它停留在主循环中。 CApplication 类本身的代码会产生很多开销。实际的“应用程序代码”放在 CApplication.main() 中 - 只执行一次的代码由程序计数器控制。
现在我把它放到下一个层次,在 CApplication.main() 中放置一个 MIDI 设备的轮询过程。因此,我将使用 MIDI 命令作为播放声音文件的触发器。我希望性能足以应对适当的延迟。
您有什么优化建议吗?
【问题讨论】:
-
使用 tkinter 提供的 mainloop 代替你自己的循环。删除您的
while循环,并插入此代码:root.mainloop()。你应该看看一个很好的教程...... -
显示窗口。但这不是我想要的。我需要 while 循环来轮询我的触发器输入以通过 Snack 播放声音文件。小吃文档并没有说需要 mainloop() 。我认为 Snack 只需要 Tk() 的一个实例,显示它并不重要。但是由于没有播放声音,我认为 Tk() 根本不起作用。所以我尝试了上面提到的简单脚本,没有任何零食,窗口也没有出现。此外,我想知道为什么我不需要控制台中的 mainloop()。
-
那你想要什么?
-
见上文。我编辑了评论。我在完成之前不小心按了 Enter :-)
标签: python-2.7 tkinter window root tk