Python tk():在脚本中使用时不会出现任何窗口(控制台可以工作)



我对这个简单的脚本有以下问题:

from Tkinter import *
root = Tk()
while 1:
pass

我想,在第二行之后,每个人都会期待一个Tkinter窗口出现。但事实并非如此!如果我把这一行放入Python控制台(没有无休止的while循环),它就可以工作了。

[我想在这里添加一张图片,但由于我是新手,我被允许:-(]

但是运行脚本(双击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就无法实际绘制窗口。移除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)

控制台中不需要主循环的原因取决于"控制台"的含义。在IDLE和其他一些交互式解释器中,tkinter在交互运行时有一种特殊的模式,不需要调用mainloop。从本质上讲,主循环就是控制台输入循环。

最新更新