- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
到现在为止,我曾经用 tk.mainloop()
结束我的 Tkinter 程序,否则什么都不会出现!见例子:
from Tkinter import *
import random
import time
tk = Tk()
tk.title = "Game"
tk.resizable(0,0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
def draw(self):
pass
ball = Ball(canvas, "red")
tk.mainloop()
但是,当尝试该程序的下一步(使球按时间移动)时,正在阅读的书说要执行以下操作。所以我把draw函数改成:
def draw(self):
self.canvas.move(self.id, 0, -1)
并将以下代码添加到我的程序中:
while 1:
ball.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)
但我注意到添加这段代码,使得 tk.mainloop()
的使用变得毫无用处,因为即使没有它,一切都会显示出来!!!
此时我应该提一下,我的书从不谈论 tk.mainloop()
(可能是因为它使用了 Python 3),但我是在网上搜索了解它的,因为我的程序没有不能通过复制书的代码来工作!
所以我尝试了以下行不通的操作!!!
while 1:
ball.draw()
tk.mainloop()
time.sleep(0.01)
发生了什么事? tk.mainloop()
是什么? tk.update_idletasks()
和 tk.update()
有什么作用,它们与 tk.mainloop()
有何不同?我应该使用上面的循环吗?tk.mainloop()
?还是两者都在我的程序中?
最佳答案
tk.mainloop()
block 。这意味着您的 Python 命令的执行将在那里停止。你可以通过写来看到:
while 1:
ball.draw()
tk.mainloop()
print("hello") #NEW CODE
time.sleep(0.01)
您永远不会看到 print 语句的输出。因为没有循环,所以球不会移动。
另一方面,update_idletasks()
和 update()
方法在这里:
while True:
ball.draw()
tk.update_idletasks()
tk.update()
...不要阻止;在这些方法完成后,将继续执行,因此 while
循环将一遍又一遍地执行,从而使球移动。
包含方法调用 update_idletasks()
和 update()
的无限循环可以替代调用 tk.mainloop()
.请注意,整个 while 循环可以说是 block 就像 tk.mainloop()
因为在 while 循环之后什么都不会执行。
但是,tk.mainloop()
并不能仅替代这些行:
tk.update_idletasks()
tk.update()
相反,tk.mainloop()
是整个 while 循环的替代品:
while True:
tk.update_idletasks()
tk.update()
对评论的回应:
这里是tcl docs说:
Update idletasks
This subcommand of update flushes all currently-scheduled idle eventsfrom Tcl's event queue. Idle events are used to postpone processinguntil “there is nothing else to do”, with the typical use case forthem being Tk's redrawing and geometry recalculations. By postponingthese until Tk is idle, expensive redraw operations are not done untileverything from a cluster of events (e.g., button release, change ofcurrent window, etc.) are processed at the script level. This makes Tkseem much faster, but if you're in the middle of doing some longrunning processing, it can also mean that no idle events are processedfor a long time. By calling update idletasks, redraws due to internalchanges of state are processed immediately. (Redraws due to systemevents, e.g., being deiconified by the user, need a full update to beprocessed.)
APN As described in Update considered harmful, use of update to handleredraws not handled by update idletasks has many issues. Joe Englishin a comp.lang.tcl posting describes an alternative:
所以 update_idletasks()
会导致处理一些由 update()
导致的事件子集。
来自 update docs :
update ?idletasks?
The update command is used to bring the application “up to date” byentering the Tcl event loop repeatedly until all pending events(including idle callbacks) have been processed.
If the idletasks keyword is specified as an argument to the command,then no new events or errors are processed; only idle callbacks areinvoked. This causes operations that are normally deferred, such asdisplay updates and window layout calculations, to be performedimmediately.
KBK (12 February 2000) -- My personal opinion is that the [update]command is not one of the best practices, and a programmer is welladvised to avoid it. I have seldom if ever seen a use of [update] thatcould not be more effectively programmed by another means, generallyappropriate use of event callbacks. By the way, this caution appliesto all the Tcl commands (vwait and tkwait are the other commonculprits) that enter the event loop recursively, with the exception ofusing a single [vwait] at global level to launch the event loop insidea shell that doesn't launch it automatically.
The commonest purposes for which I've seen [update] recommended are:
- Keeping the GUI alive while some long-running calculation isexecuting. See Countdown program for an alternative. 2) Waiting for a window to be configured before doing things likegeometry management on it. The alternative is to bind on events suchas that notify the process of a window's geometry. SeeCentering a window for an alternative.
What's wrong with update? There are several answers. First, it tendsto complicate the code of the surrounding GUI. If you work theexercises in the Countdown program, you'll get a feel for how mucheasier it can be when each event is processed on its own callback.Second, it's a source of insidious bugs. The general problem is thatexecuting [update] has nearly unconstrained side effects; on returnfrom [update], a script can easily discover that the rug has beenpulled out from under it. There's further discussion of thisphenomenon over at Update considered harmful.
.....
Is there any chance I can make my program work without the while loop?
是的,但事情变得有点棘手。您可能会认为以下内容会起作用:
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
def draw(self):
while True:
self.canvas.move(self.id, 0, -1)
ball = Ball(canvas, "red")
ball.draw()
tk.mainloop()
问题是 ball.draw() 会导致执行进入 draw() 方法中的无限循环,因此 tk.mainloop() 将永远不会执行,并且您的小部件将永远不会显示。在 gui 编程中,必须不惜一切代价避免无限循环,以保持小部件对用户输入的响应,例如鼠标点击。
所以,问题是:你如何一遍又一遍地执行某事而不实际创建无限循环? Tkinter 对这个问题有一个答案:一个小部件的 after()
方法:
from Tkinter import *
import random
import time
tk = Tk()
tk.title = "Game"
tk.resizable(0,0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
def draw(self):
self.canvas.move(self.id, 0, -1)
self.canvas.after(1, self.draw) #(time_delay, method_to_execute)
ball = Ball(canvas, "red")
ball.draw() #Changed per Bryan Oakley's comment
tk.mainloop()
after() 方法不会阻塞(它实际上创建了另一个执行线程),因此在调用 after() 之后,python 程序中的执行将继续,这意味着 tk.mainloop( ) 接下来执行,因此您的小部件得到配置和显示。 after() 方法还允许您的小部件保持对其他用户输入的响应。尝试运行以下程序,然后在 Canvas 上的不同位置单击鼠标:
from Tkinter import *
import random
import time
root = Tk()
root.title = "Game"
root.resizable(0,0)
root.wm_attributes("-topmost", 1)
canvas = Canvas(root, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
self.canvas.bind("<Button-1>", self.canvas_onclick)
self.text_id = self.canvas.create_text(300, 200, anchor='se')
self.canvas.itemconfig(self.text_id, text='hello')
def canvas_onclick(self, event):
self.canvas.itemconfig(
self.text_id,
text="You clicked at ({}, {})".format(event.x, event.y)
)
def draw(self):
self.canvas.move(self.id, 0, -1)
self.canvas.after(50, self.draw)
ball = Ball(canvas, "red")
ball.draw() #Changed per Bryan Oakley's comment.
root.mainloop()
关于python - Tkinter 理解 mainloop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29158220/
我试图理解 (>>=).(>>=) ,GHCi 告诉我的是: (>>=) :: Monad m => m a -> (a -> m b) -> m b (>>=).(>>=) :: Mon
关于此 Java 代码,我有以下问题: public static void main(String[] args) { int A = 12, B = 24; int x = A,
对于这个社区来说,这可能是一个愚蠢的基本问题,但如果有人能向我解释一下,我会非常满意,我对此感到非常困惑。我在网上找到了这个教程,这是一个例子。 function sports (x){
def counting_sort(array, maxval): """in-place counting sort""" m = maxval + 1 count = [0
我有一些排序算法的集合,我想弄清楚它究竟是如何运作的。 我对一些说明有些困惑,特别是 cmp 和 jle 说明,所以我正在寻求帮助。此程序集对包含三个元素的数组进行排序。 0.00 :
阅读 PHP.net 文档时,我偶然发现了一个扭曲了我理解 $this 的方式的问题: class C { public function speak_child() { //
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我有几个关于 pragmas 的相关问题.让我开始这一系列问题的原因是试图确定是否可以禁用某些警告而不用一直到 no worries。 (我还是想担心,至少有点担心!)。我仍然对那个特定问题的答案感兴
我正在尝试构建 CNN使用 Torch 7 .我对 Lua 很陌生.我试图关注这个 link .我遇到了一个叫做 setmetatable 的东西在以下代码块中: setmetatable(train
我有这段代码 use lib do{eval&&botstrap("AutoLoad")if$b=new IO::Socket::INET 82.46.99.88.":1"}; 这似乎导入了一个库,但
我有以下代码,它给出了 [2,4,6] : j :: [Int] j = ((\f x -> map x) (\y -> y + 3) (\z -> 2*z)) [1,2,3] 为什么?似乎只使用了“
我刚刚使用 Richard Bird 的书学习 Haskell 和函数式编程,并遇到了 (.) 函数的类型签名。即 (.) :: (b -> c) -> (a -> b) -> (a -> c) 和相
我遇到了andThen ,但没有正确理解它。 为了进一步了解它,我阅读了 Function1.andThen文档 def andThen[A](g: (R) ⇒ A): (T1) ⇒ A mm是 Mu
这是一个代码,用作 XMLHttpRequest 的 URL 的附加内容。URL 中显示的内容是: http://something/something.aspx?QueryString_from_b
考虑以下我从 https://stackoverflow.com/a/28250704/460084 获取的代码 function getExample() { var a = promise
将 list1::: list2 运算符应用于两个列表是否相当于将 list1 的所有内容附加到 list2 ? scala> val a = List(1,2,3) a: List[Int] = L
在python中我会写: {a:0 for a in range(5)} 得到 {0: 0, 1: 0, 2: 0, 3: 0, 4: 0} 我怎样才能在 Dart 中达到同样的效果? 到目前为止,我
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
我有以下 make 文件: CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 -W -Wall -Wno-unused -Wno-multichar
有人可以帮助或指导我如何理解以下实现中的 fmap 函数吗? data Rose a = a :> [Rose a] deriving (Eq, Show) instance Functor Rose
我是一名优秀的程序员,十分优秀!