【问题标题】:Tkinter w.destroy() blocks/resets window resizeTkinter w.destroy() 块/重置窗口调整大小
【发布时间】:2016-06-11 19:25:45
【问题描述】:

我有一个使用 tkinter 的 Python 3.5 应用程序,并在画布中动态创建/删除小部件。我注意到在窗口调整大小回调期间使用 w.destroy() 销毁小部件时,回调正确完成,但窗口正在重置为其原始大小。

我尝试使用 self.after(1000, self.resize) 延迟 w.destroy() 并且这种方法有效,但是在触发回调时向下拖动/按住光标时,调整大小会跳回无论如何。

有人建议即时删除小部件并释放内存吗?

更新: 作为一种解决方法,我使用 w.delete=True 标记要删除的小部件,并在“后”回调中删除标记为删除的小部件。

这是一个简化的示例来说明问题:

更新:将代码简化为重现问题的最低限度。

from tkinter import ALL, N, E, W, S, Canvas, Tk, ttk


class Resize(Tk):
    def __init__(self):
        super().__init__()
        self.init = True
        self.canvas = None
        self.position_window()
        self.create_canvas()

    def resize(self):
        if self.init:
            self.init = False
            return
        # delete(ALL) will remove the widget from the display, but widget 
        # remains in memory as child of canvas. Resizing works ok.
        self.canvas.delete(ALL)
        # widget.destroy() will release memory of widget, but blocks/resets resizing.
        # Window gets resized by 1-2 pixels and jumps back to its original size.
        [child.destroy() for child in self.canvas.winfo_children()]

    def create_canvas(self):
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.canvas = Canvas(self)
        self.canvas.grid(row=0, column=0, sticky=(N, S, W, E))
        self.canvas.bind('<Configure>', lambda *args: self.resize())

        entry = ttk.Label(self.canvas, text='Some dummy text')
        self.canvas.create_window(20, 20, window=entry, anchor='w')

    def position_window(self):
        self.resizable(1, 1)
        sceenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        self.update_idletasks()
        width = 600
        height = 300
        left = sceenwidth / 2 - width / 2
        top = (screenheight / 2 - height / 2) / 3
        self.geometry("%dx%d%+d%+d" % (width, height, left, top))


if __name__ == '__main__':
    Resize().mainloop()

【问题讨论】:

  • 你为什么要删除它们,然后它们会立即重新创建它们?您要解决的真正问题是什么?
  • @BryanOakley 上面的代码只是一个示例,用于重现在回调期间销毁小部件时滚动中止的问题。我同意代码可能不是很合乎逻辑...基于您在其他地方的一些指责,我正在创建一个 Table 小部件,该小部件仅通过在画布中显示少数行来处理数千行。调整画布大小时,我删除了多余的行及其小部件。那时,调整大小正在重置,没有任何错误。顺便提一句。我已经简化了代码。
  • 您找到解决方案了吗?我的项目也有类似的问题
  • @DV,错过了您的评论...不,没有找到解决方案。除非您将使用 Electron/Angular 称为解决方案 :-)

标签: python-3.x tkinter window-resize tkinter-canvas


【解决方案1】:

我没有尝试您的代码,但我自己的项目也遇到了同样的问题。

窗口不只是在destroy() 上调整大小/重置; &lt;Configure&gt; 事件似乎被打断了。 无论我调整多少或多少,窗口总是恢复到第一个 &lt;Configure&gt; 回调。正因为如此,或者随之而来的是,Button-1 会自动释放,从而阻止窗口调整大小手柄跟随鼠标。

换句话说,窗口边缘从鼠标下方“滑出”,就像当鼠标移得太远时,Windows 中的滚动条会在滚动中重置。

无论如何,一个解决方案是使用 ttk.Sizegrip 并禁止使用窗口边框调整顶级窗口的大小。

【讨论】:

  • 如何禁止调整顶层窗口的大小?我试过 root.resizable(False, False)。而且 sizegrip 根本不起作用。
【解决方案2】:

https://stackoverflow.com/a/65605907/7281120

我在其他地方回答了这个问题。我最终投票了

win32api.GetKeyState(0x01) >= 0

并存储释放鼠标时要销毁的东西的列表,这样做是安全的。

【讨论】:

    猜你喜欢
    • 2011-05-18
    • 1970-01-01
    • 2017-11-18
    • 2013-07-10
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多