关于Tkinter的几个问题——mainloop、更新方法、有效性等

Posted

技术标签:

【中文标题】关于Tkinter的几个问题——mainloop、更新方法、有效性等【英文标题】:Several questions on Tkinter - mainloop, update method, effectiveness etc 【发布时间】:2015-09-07 07:34:45 【问题描述】:

背景:我正在尝试为构建在 Tkinter 之上的 python 编写图形库。因此,我想从用户那里抽象出所有 Tkinter 的功能,并有方法调用以类似处理的方式顺序修改根窗口。例如,我的库(我们称之为 mylib)将使您能够编写如下代码:

from mylib import * #this would be my library
window(400, 400) #open a new window to add objects to
color('red') #set the color of all subsequent items to red
circle(radius=5, centerx = 0, centery=0) #make a red circle
line(10,10, 20, 20) #red line going from (10, 10) to (20, 20)
color('blue')
line(50, 50, 100, 100) #blue line

我想过这样实现它:

try:
    from tkinter import *
except:
    from Tkinter import *

_root = Tk()


class MyCanvas(Canvas):
    def __init__(self, width=400, height=400):
        master = Toplevel(_root)
        Canvas.__init__(self, master, width=width, height=height)
        self.pack()
        self.items = []
        self.width = width
        self.height = height
        _root.mainloop()


global _c
_c = None

def window():
    _c = MyCanvas()
    _c.pack()

def line(a,b,c,d):
    #config code goes here
    _c.create_line(a,b,c,d)

#test
window()
line(10, 10, 50, 50)

这不起作用,因为 Python 不会退出 mainloop(),所以我尝试了这个: 尝试: 从 tkinter 导入 * 除了: 从 Tkinter 导入 *

_root = Tk()


class MyCanvas(Canvas):
    def __init__(self, width=400, height=400):
        master = Toplevel(_root)
        Canvas.__init__(self, master, width=width, height=height)
        self.pack()
        self.items = []
        self.width = width
        self.height = height



global _c
_c = None

def window():
    _c = MyCanvas()
    _c.pack()

def line(a,b,c,d):
    #config code goes here
    _c.create_line(a,b,c,d)
    _root.update_idletasks()

#test
window()
line(10, 10, 50, 50)

但这也不起作用 - 它只是冻结了。我尝试用更新替换 update_idletasks。窗户又冻结了。如何正确使用更新?

有没有办法在不让用户显式调用的情况下使用 mainloop() 来完成此操作?

或者有没有办法在主循环中编辑小部件?我考虑过使用 after 但我没有看到这将如何解决问题。

如果在给定这些约束的情况下没有答案退出,那么在 PyOpenGL 中编写包是否有用或可移植?我应该从头开始使用 C 编写模块吗?还有什么存在吗?帮帮我!!!

抱歉,问题太长了。我已经做了好几个小时了,但无济于事。

【问题讨论】:

简答:你需要主循环。 怎么样?更新有效,但只是停止响应。没有线程和处理callbakcs的方法吗? 使用 _root.mainloop() 作为脚本的最后一行... 但我正试图将它变成这样的库:mcsp.wartburg.edu/zelle/python/graphics.py 不使用主循环但可以编辑画布。 【参考方案1】:

在我看来,您最好将其编写为 tcl 实现并使用 wish 作为可执行文件。您似乎在做的是定义一种领域特定语言(DSL),您将把它解释为驱动 Tk 的命令。这里似乎没有什么特别需要python的东西。

你需要一个主循环。任何窗口应用程序都必须有一个事件泵,它从系统获取消息并在必要时将它们分派到您的窗口。所有此类应用程序都必须在主 UI 线程仅泵送此消息队列的地方结束。对于 Tk wish 可执行文件,它内置在解释器中。 Wish 获取您的脚本,然后运行事件循环。您可以通过加载客户端代码并将应用程序主函数作为后续事件调用来在 python 库中进行模拟。您可能必须确保客户端代码不调用 mainloop 以避免冲突。

如果您以前从未看过 Tcl/Tk - 您可能想要。您所定义的内容看起来与 Tcl/Tk 应用程序真的相距不远。

【讨论】:

我想要这样的东西。据我所知,他们似乎没有使用 mainloop。相反,他们线程化整个应用程序并使用更新。 cs.xu.edu/csci170/09f/cs1graphics.py 甚至 Zelle 的 graphics.py

以上是关于关于Tkinter的几个问题——mainloop、更新方法、有效性等的主要内容,如果未能解决你的问题,请参考以下文章

Tkinter 理解 mainloop

尝试在 tkinter mainloop 旁边运行一个 while true 循环

Python如何抑制单元测试的tkinter mainloop()

在 Python Tkinter 中,如何在 mainloop 窗口打开后运行代码? [复制]

Python中tkinter的窗口,在mainloop ()之后的语句怎么执行啊、循环以后就不动

Tkinter 嵌套主循环