mainloop()的代码范围是多少?

问题描述 投票:0回答:1

我想在画布上创建一个带有自定义移动小部件的python tkinter窗口来模拟运动。现在,我有一个画布,一个不动的椭圆形小部件。我在基层有问题;主循环()。我知道它会等待用户做某事,但我很难看到:

  1. 如何控制/查看mainloop()重复的代码(在哪里,只有tkinter?);
  2. 如果没有自己中断,如何正确地中断它并从另一个函数返回它;
  3. 应该重申什么代码?所有tkinter对象,还是仅更新更改的对象?改为使用某种更新操作?最后;
  4. tkinter.mainloop()和window.mainloop()之间的功能有什么区别?也许以前的问题会回答。

我对Swift有一点经验,昨天晚上开始学习非常相似的Python。我已经尝试了数百个突变到我的代码,目前正处于测试阶段。我已将所有内容移入和移出mainloop的明显范围,甚至在屏幕上都有几百个小的Python窗口。一切都做两件事之一:它什么都不做,或者给我一个错误。由于我不知道什么是运行,或者它正在运行,我无法诊断任何东西。我的目标只是重复移动一百个像素的圆圈。我已经四处寻找消息来源,但是 - 它可能是我 - 一个明显的稀缺。我的代码在这里都标记了。此页面最接近我要找的内容: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'行内循环,这应该调整坐标并移动我的蓝色圆圈。迭代可能不会触及初始值,否则会重置它们。

python tkinter mainloop
1个回答
0
投票

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

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

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


如何控制/查看mainloop()重复的代码(在哪里,只有tkinter?);

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

如果没有自己中断,如何正确地中断它并从另一个函数返回它;

在正在运行的程序中执行此操作非常罕见。通常,调用mainloop是您的程序在用户开始与之交互之前执行的最后一件事,并且一旦退出程序就退出。

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

应该重申什么代码?所有tkinter对象,还是仅更新更改的对象?改为使用某种更新操作?

这个问题很难回答,因为它没有多大意义。当你调用mainloop()时,它会监视所有tkinter对象上的所有事件。

tkinter.mainloop()和window.mainloop()之间的功能有什么区别

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

我的目标只是重复移动一百个像素的圆圈。

通常的做法是创建一个将其移动一百个像素的函数。然后,该函数(或调用它的函数)可以将自己置于将来运行的事件队列中。

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

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

调用它时,它会将项目向右移动100个像素。然后,它将在事件队列上对其自身进行新的调用,以便在大约1000毫秒内拾取和处理。

在本网站上有许多使用after的工作示例,包括您在问题中链接的问题。

一切似乎都在主循环之下。那么,每一次都重绘一切?

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

它应该显示一个1368乘650的窗口,而不是一个小窗口

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

虽然使用place的感觉很简单,但实际上它通常要求你比使用其他几何管理器做更多的工作,并且它导致GUI对变化没有特别的响应。

while True:

你几乎不应该在tkinter中这样做。 Tkinter - 以及几乎所有基于事件的程序 - 都依赖于稳定的事件流。当您有一个无限循环时,它无法处理这些事件。您可以显式调用以更新循环内的屏幕,但这样做效率低,应该避免。如果你需要定期做一些事情,创建一个封装循环体的函数,然后使用aftermainloop在处理事件时运行它。

window.after(1000)

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

while True: ... window.mainloop()

你肯定需要避免在循环中调用mainloop。一个表现良好的tkinter程序应该只调用一次mainloop()

© www.soinside.com 2019 - 2024. All rights reserved.