Tkinter : Как динамически настраивать содержимое в соответствии с желаемым размером дисплея [Проблема, вызванная pyautogui]

#tkinter

Вопрос:

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

Ранее у меня сложилось впечатление, что я, возможно, пропустил что-то, из-за чего виджеты не выровнены в соответствии с размером дисплея, но после дальнейшего расследования я обнаружил, что виновником был импорт pyautogui. Вы можете протестировать приведенный ниже код, чтобы лучше понять проблему

Возможно , вы не заметите эту проблему на экране ноутбука, но если вы запустите тот же код на дисплее большего размера, чем у вашего ноутбука, вы увидите разницу.

Сначала прокомментируйте импорт pyautogui и запустите код, вы увидите индикатор выполнения нормального размера. Without_pyautogui_import

Второе : Раскомментируйте pyautogui и запустите код, вы увидите, что размер индикатора выполнения был значительно уменьшен. Image_after_import_pyautogui

В этом примере я использовал только индикатор выполнения, чтобы воссоздать проблему , но если у вас есть экран, заполненный всеми виджетами, вы увидите огромный разрыв между виджетами, которые не выровнены должным образом.

Странно то, что я даже не создал объект для pyautogui, импорта достаточно, чтобы испортить виджеты. Есть какие-нибудь предложения?

 from tkinter import *
from tkinter.ttk import *
import pyautogui

tk=Tk()
progress=Progressbar(tk,orient=HORIZONTAL,length=100,mode='determinate')

def bar():
    import time
    progress['value']=20
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=50
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=80
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=100

progress.pack()
Button(tk,text='foo',command=bar).pack()
mainloop()

 

Комментарии:

1. Есть много способов сделать это. В двух словах, это сводится к хорошему дизайну и использованию функций pack и. grid Не зная более подробной информации о вашей конкретной проблеме, мы не сможем дать лучший совет.

2. @BryanOakley Я обновил свой вопрос, а также обнаружил проблему. Пожалуйста, посмотрите и дайте мне знать, если у вас есть какие-либо предложения.

Ответ №1:

Возможно, pyautogui использует имя tk во время его создания и перезаписывает ожидаемые значения по умолчанию; вероятно, во время инициализации PyMsgBox. Я бы избегал этого ключевого слова и вместо этого попытался использовать его root в качестве имени корневого окна, поскольку это, как правило, приемлемая практика во многих примерах, которые я видел.

 #! /usr/bin/env python3

from tkinter import *
from tkinter.ttk import *
##  import pyautogui

title = 'Progressbar'
root = Tk() ; root .title( title )
root .bind( '<Escape>',  lambda e: root .destroy() )

'''
root .attributes( '-zoomed',  True )
root .update_idletasks()
Width, Height = root .winfo_width(),  root .winfo_height()
'''

##  Might have better results by specifying windowsize
Width, Height = 600, 400
root .geometry( f'{Width}x{Height}' )

progress = Progressbar( root, orient=HORIZONTAL, length=100, mode='determinate' )

def bar():
    import time
    progress['value'] = 20
    root .update_idletasks()
    time .sleep(1)
    progress['value'] = 50
    root .update_idletasks()
    time .sleep(1)
    progress['value'] = 80
    root .update_idletasks()
    time .sleep(1)
    progress['value'] = 100

progress .pack()
Button( root, text='foo', command=bar ) .pack()
mainloop()
 

Комментарии:

1. Спасибо за ваш быстрый ответ, В моем реальном приложении я использую rootwin вместо tk при создании экземпляра Tk(). Я скопировал это из stackoverflow просто для того, чтобы дать представление о проблеме. Я не знал, что экземпляр называется tk. Но, вы можете использовать любое имя для создания экземпляра, проблема все еще сохраняется. Я новичок в python и tkinter, но простой импорт ничего не построит, если вы не создадите объект. пожалуйста, поправьте меня, если я ошибаюсь. Еще раз спасибо.

2. Хорошо, хорошо, вы пытались указать размер окна, или это просто выбор любой ширины пикселя, удобной для отображения?

3. Да, у меня определен размер окна.

4. Все еще не уверен. Не вижу никаких изменений в ценности, которые я ожидал увидеть. print( vars( progress ), 'nn', progress .config(), 'nn', tk .config() ) Вы используете текущие версии этих модулей?

5. Как я уже упоминал в вопросе, вы не увидите разницы на ноутбуке, но если вы запустите его на большом дисплее, вы увидите изменения. Он отлично работает на экране ноутбука 1368*768 независимо от того, импортирован ли у вас pyautogui или нет. Я не уверен, что вы тестировали его на ноутбуке с большим экраном. если это было на ноутбуке, то вы не увидите того поведения, о котором я говорил.