Отказ от ответственности: По всей вероятности, это вполне может быть проблемой XY, я был бы признателен, если бы вы указали мне правильное направление.
Цель: У меня есть файл, который я хотел бы, чтобы tkinter прочитал, а затем динамически создал виджеты на основе содержимого файла. Я хочу, чтобы окно всегда открывалось по центру моего курсора.
Ради MCVE давайте рассмотрим простой текстовый файл, который гласит:
Madness?
This
IS
T K I N T E R
И tkinter должен создать 4 виджета с метками, размер главного окна которых можно изменить. Это очень просто ... до тех пор, пока файл не будет зашифрован. Прежде чем я смогу прочитать зашифрованный файл, мне нужно askstring()
сначала ввести пароль (MCVE: давайте также предположим, что мы запрашиваем только key
здесь).
Мои вопросы:
Диалог askstring
всегда находится в положении по умолчанию. Я знаю, что это должно быть относительно родителя (корень) ...
Но я не могу установить geometry()
до того, как создаю виджеты, иначе он не будет изменен в соответствии с виджетами ...
И я не могу заранее определить размер, необходимый для geometry()
, так как не могу открыть файл без пароля (ключа) ...
Вот пример MCVE моей самой успешной попытки:
import tkinter as tk
from tkinter.simpledialog import askstring
from cryptography.fernet import Fernet
class GUI(tk.Tk):
def __init__(self):
super().__init__()
# side note: If I don't withdraw() the root first, the dialog ends up behind the root
# and I couldn't find a way to get around this.
self.withdraw()
self.create_widgets()
# Attempt: I tried doing this instead of self.create_widgets():
# self.reposition()
# self.after(ms=1,func=self.create_widgets)
# The dialog is positioned correctly, but the window size doesn't resize
self.deiconify()
# I have to do the reposition AFTER mainloop or else the window size becomes 1x1
self.after(ms=1, func=self.reposition)
self.mainloop()
def get_key(self):
return askstring('Locked','Enter Key', show='*', parent=self)
def create_widgets(self):
self.lbls = []
with open('test2.txt', 'rb') as file:
encrypted = file.read()
key = self.get_key()
suite = Fernet(key)
self.data = suite.decrypt(encrypted).decode('utf-8')
for i in self.data.split('\n'):
self.lbls.append(tk.Label(self, text=i.strip()))
self.lbls[-1].pack()
def reposition(self):
width, height = self.winfo_width(), self.winfo_height()
self.geometry(f'{width}x{height}+{self.winfo_pointerx()-int(width/2)}+{self.winfo_pointery()-int(height/2)}')
gui = GUI()
Что достигает (с чем я могу жить):
- ✓ Правильный размер в зависимости от содержимого файла
- ✓ Корень расположен в центре курсора
- ⨯ Запрашивает клавишу в центре курсора
Мои вопросы:
Можно ли снова выполнить автоматическое изменение размера корня на основе функции виджетов, аналогичной pack_propagate()
после установки geometry()
? Кажется, как только geometry()
установлен, корень больше не будет распространяться.
Если нет, то как я могу вручную изменить его размер в коде? Я попытался получить общую высоту виджетов height = sum([i.winfo_reqheight() for i in self.lbls])
, но height
просто становится 0
. Но когда я print(self.lbls[-1].winfo_reqheight())
в self.create_widgets()
возвращает 26
каждый, и они на самом деле печатают после моего self.reposition()
вызова, что странно.
В противном случае возможно ли разместить диалоговое окно askstring()
до создания виджетов?
Я в тупике. Мне кажется, что я поступаю об этом неправильно, но я не уверен, как правильно справиться с этой ситуацией, чтобы разорвать цикл зависимости.
Чтобы помочь с воспроизведением, здесь есть зашифрованная строка и ключ:
Данные:
gAAAAABb2z3y-Kva7bdgMEbvnqGGRRJc9ZMrt8oc092_fuxSK1x4qlP72aVy13xR-jQV1vLD7NQdOTT6YBI17pGYpUZiFpIOQGih9jYsd-u1EPUeV2iqPLG7wYcNxYq-u4Z4phkHllvP
Key:
SecretKeyAnyhowGoWatchDareDevilS3ItsAmazing=
Редактировать: На основании ответа @ BryanOakley здесь Я могу вызвать self.geometry("")
для сброса, однако он возвращается к исходному 200x200
размеру и все еще не распространяет виджеты.