Центрировать окно TopLevel, сохраняя динамический размер геометрии сетки / пакета? - PullRequest
1 голос
/ 24 мая 2019

Я хочу центрировать окно TopLevel по центру его родительского окна (окно Tk или TopLevel). Проблема в том, что я хочу сохранить динамический размер окна, которое дают .pack() и .grid(), менеджеры геометрии tkinter (размер окна масштабируется в зависимости от того, какой размер нужен).

Я хочу сделать это без необходимости использовать update(), который, как я знаю, решит мою проблему, потому что я не хочу, чтобы окно вспыхивало, а затем быстро мигало в то место, которое должно быть.

Это моя лучшая попытка, проблема в том, что она удаляет динамический размер.

from tkinter import *


def center_to_win(window, master):
    x = master.winfo_x()
    y = master.winfo_y()
    w = window.winfo_reqwidth()
    h = window.winfo_reqheight()
    total_x = x + (master.winfo_width() // 2) - (w // 2)
    total_y = y + (master.winfo_height() // 2) - (h // 2)
    window.geometry("%dx%d+%d+%d" % (int(w), int(h), int(total_x), int(total_y)))


class MainWin(Tk):
    def __init__(self):
        super(MainWin, self).__init__()
        self.update()
        pu = PopUp(self)


class PopUp(Toplevel):
    def __init__(self, master):
        super(PopUp, self).__init__(master)
        for i in range(20):
            label = Label(self, text="label i")
            label.grid(column=0, row=i)
        center_to_win(self, master)


if __name__ == '__main__':
    win = MainWin()
    win.mainloop()

Если кто-нибудь знает, как это сделать, не имея вспыхивающего окна на экране, это было бы очень полезно. :)

1 Ответ

2 голосов
/ 24 мая 2019

Насколько я знаю, окно не может обновляться без update() до выполнения mainloop(). Однако это можно сделать, не мигая, обновив окно, когда оно скрыто. Мы можем использовать window.wm_withdraw(), чтобы скрыть, и window.wm_deiconify(), чтобы показать , задержка не заметна, по крайней мере, в моей системе. window.iconify() также может использоваться вместо window.wm_withdraw(), но его нельзя использовать вместе с transient().

Возможны функции center_to_win() для централизации одного окна в другом.

def center_to_win(window, master):
    window.wm_withdraw()
    window.update()
    x = master.winfo_x()
    y = master.winfo_y()
    w = window.winfo_reqwidth()
    h = window.winfo_reqheight()
    total_x = x + (master.winfo_width() // 2) - (w // 2)
    total_y = y + (master.winfo_height() // 2) - (h // 2)
    window.geometry("%dx%d+%d+%d" % (int(w), int(h), int(total_x), int(total_y)))
    window.wm_deiconify()

Вызов функции просто с помощью center_to_win(self, master) работает совершенно нормально, но я заметил проблему, когда вы устанавливаете геометрию главного окна при запуске, это можно исправить, вызвав функцию, подобную этой self.after(1, center_to_win, self, master). Хотя это было очень случайным и не могло случиться с вами, но в случае, если это произойдет, используйте after(..).


Для динамического определения размера.

Хотя это устраняет проблему с динамическим размером, но вы должны использовать self.grid_rowconfigure(index, weight=1) и self.grid_columnconfigure(index, weight=1) для grid layout.

...

for i in range(20):
    self.grid_rowconfigure(i, weight=1)
    label = Label(self, text="label i")
    label.grid(column=0, row=i)
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...