主循环(mainloop())对代码有什么影响?

2024-04-24 18:38:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做一个pythontkinter窗口,在画布上使用自定义的移动小部件来模拟运动。现在,我有一个画布,还有一个不移动的椭圆形小部件。我在基本级别遇到问题;mainloop()。我知道它是在等待用户做些什么,但我很难看到:

  1. 如何控制/查看mainloop()到底在重复什么代码(在哪里,只有tkinter?);

  2. 如何正确地中断它并从另一个函数返回到它,如果它本身不这样做;

  3. 应该重申什么准则?所有tkinter对象,还是只更新更改的对象?改用某种更新操作?最后;

  4. 它们之间的功能区别是什么tkinter.mainloop公司()和窗口.mainloop()? 也许前面的问题可以回答。

我对Swift有一些小经验,昨天晚上开始学习非常类似的Python。我已经尝试了我的代码可能有上百个突变,目前正处于测试阶段。我已经将所有东西移入和移出了主循环的明显范围,甚至在整个屏幕上都有几百个小Python窗口。每件事都做两件事中的一件:它什么也不做,或者给我一个错误。因为我甚至不知道什么在运行,或者它是否在运行,所以我无法诊断任何东西。我的目标就是把一个圆反复移动100像素。我已经四处搜索了消息来源,但可能是我——很难找到一个清晰的消息来源。我把代码都标上了。此页最接近我要查找的内容:Move a ball inside Tkinter Canvas Widget (simple Arkanoid game)。一切似乎都在主循环下。所以,每过一遍都要重新画一遍?不幸的是,这是我的全部剧本;我不能只展示片段。出于某种原因,它只能打开一个小窗口,而不是一个全屏窗口。(编辑:我好像丢失了屏幕大小代码)

import tkinter
import time

# Initial values for circle's corners and start idicator ('b'):
x1 = 10
y1 = 10
x2 = 210
y2 = 210

b = 0

# Window ('window')
window = tkinter.Tk()

# Canvas ('area')
area = tkinter.Canvas(window, width=1368, height=650)
area.place(x=0, y=0)


# Ovals to be placed on 'area'
oval1 = area.create_oval(x1,y1,x2,y2,fill='#42befe')
oval2 = area.create_oval(100,10,300,210,fill='#d00000')

# Turns b to 1 to start shifting when 'butt' is pressed:
def startFunc():
    b = 1
    print('b = 1')

# My button to activate 'startFunc'  
butt = tkinter.Button(window, text='Start movement', command=startFunc)
butt.pack()

# Adjusts the x and y coordinates when they are fed in:
def Shift(A, B, C, D):
    print('Shift activated.')
    window.after(1000)
    print('Edit and return:')
    A += 100
    B += 100
    C += 100
    D += 100
    return(A, B, C, D)


# Problems start about here: my Mainloop section;
# I have little idea how this is supposed to be.
while True:

    if b == 1:
        # Takes adjusted tuple
        n = Shift(x1, y1, x2, y2)
        print('Returned edited tuple.')

        # Changes coordinates
        x1 = n[0]
        y1 = n[1]
        x2 = n[2]
        y2 = n[3]
        print(f'{x1}, {y1}, {x2}, and {y2}')

        # Reiterate moving oval
    oval1 = area.create_oval(x1,y1,x2,y2,fill='#42befe')

    #Does this re-run 'window' relations outside here, or only within the 'while'?
    window.mainloop()

它应该显示一个1368×650的窗口,而不是一个小窗口。按钮除了打印之外什么也不做,这意味着尽管有主循环,最终的while没有运行。它想让它在“while”线内循环,它应该调整坐标并移动我的蓝色圆圈。迭代可能不会触及初始值,否则会重置它们。你知道吗


Tags: andto代码tkinterareawindowcanvasprint
1条回答
网友
1楼 · 发布于 2024-04-24 18:38:14

实际上,调用mainloop与将其添加到代码中而不是调用mainloop()是一样的:

while the_program_is_running():
    event = wait_for_event()
    process_the_event(event)

根据经验法则,mainloop()应该在UI初始化并且您已经准备好让用户开始与您的程序交互之后调用一次。当它退出时,后面通常不会有任何代码,程序也会退出。你知道吗


How to control/see exactly what code mainloop() is reiterating (where, and only tkinter?);

我不知道你说的“重申”是什么意思。它不运行任何代码,除了它自己的内部代码。它只是等待事件,然后将它们分派给处理程序。你知道吗

How to properly interrupt it and return to it from another function, if it doesn't do it itself;

在运行的程序中这样做是非常罕见的。通常,调用mainloop是您的程序在用户开始与它交互之前以及一旦退出程序就退出时所做的最后一件事。你知道吗

但是,要回答如何中断它的具体答案,可以调用根窗口的quit方法。这将导致对mainloop()的最新调用返回。你知道吗

What code should be reiterated? All tkinter objects, or only updating changing ones? Use some kind of update operation instead?

这个问题很难回答,因为它没有什么意义。调用mainloop()时,它将监视所有tkinter对象上的所有事件。你知道吗

What is the functionality difference between tkinter.mainloop() and window.mainloop()

它们具有完全相同的效果和行为。奇怪的是,Tkinter选择从任何小部件提供mainloop。最常见的调用方法是从tkinter模块本身或根窗口调用它。你知道吗

My goal is simply to move a circle one hundred pixels repeatedly.

通常的方法是创建一个将其移动100像素的函数。然后,该函数(或调用该函数的函数)可以将自己放在将来运行的事件队列中。你知道吗

例如,以下代码将每秒移动画布对象100像素,直到程序退出:

def move_object():
    the_canvas.move(item_id, 100, 0)
    the_canvas.after(1000, move_object)

当调用它时,它会将项目向右移动100像素。然后,它将在事件队列中为自己放置一个新调用,以便在大约1000毫秒内拾取和处理。你知道吗

在这个站点上有许多使用after的工作示例,包括您在问题中链接到的问题。你知道吗

Everything appears to be under mainloop. So, everything is redrawn every pass?

不,不完全是。唯一需要重绘的对象是需要重绘的对象。在画布上移动对象、调整窗口大小、在窗口上拖动另一个窗口等等,都会在事件队列中放置一个事件,告诉tkinter“这个对象需要重新绘制”。该事件的处理由mainloop自动进行。如果应用程序中没有发生任何事情,则mainloop不会重新绘制任何内容。你知道吗

It ought to show a 1368 by 650 window, not a tiny one

这是因为您没有给主窗口指定大小。您已经为画布指定了一个大小,但是您使用的是place,这不会导致包含的窗口增大或缩小到合适的大小。作为初学者,您应该完全避免使用place,而是使用packgrid,因为packgrid都会自动调整窗口大小,以适应窗口中的所有内容。你知道吗

虽然使用place是因为它的简单性,但实际上,它通常需要您做比使用其他几何图形管理器更多的工作,而且它会产生一个对更改没有特别响应的GUI。你知道吗

while True:

你几乎不应该在特金特这样做。Tkinter和几乎所有基于事件的程序都依赖于稳定的事件流。当您有一个无限循环时,它无法处理这些事件。您可以在循环中显式地调用以更新屏幕,但这是低效的,应该避免。如果需要定期执行某些操作,请创建一个封装循环体的函数,然后使用after使mainloop在循环处理事件时运行它。你知道吗

window.after(1000)

在没有第二个参数的情况下,几乎不应该这样使用after。这种用法在功能上与调用time.sleep(1)没有区别,因为它阻止mainloop处理事件。您应该构造代码以允许mainloop处理稳定的事件流。你知道吗

while True: ... window.mainloop()

你肯定需要避免在循环内调用mainloop。一个性能良好的tkinter程序应该只调用mainloop()一次。你知道吗

相关问题 更多 >