Приставка Ttk не включается
Обновлено: 21.11.2024
Мне не удается заставить работать виджет ttk.Progressbar. Могу я узнать, в чем проблема и как ее исправить?
Я знаю, что виджет Progressbar работает; когда я комментирую self.sp_pbar.stop(), индикатор выполнения запускается, но это происходит после завершения time.sleep(5), что не является желаемым поведением.
@Lukas Можете ли вы подтвердить, что использование многопоточности — единственный способ получить желаемое поведение графического интерфейса? То есть метод .after использовать нельзя? Я спрашиваю, потому что введение многопоточности делает процесс реализации виджета Progressbar более сложным. Правильно ли я говорю, что мой код должен запускать два процесса одновременно, поэтому метод .after не подходит?
2 ответа 2
Вот что сейчас есть в вашем коде:
вы установили self.espconnecting = False
вы вызываете _connect_esp()
который вызывает _show_conn_progress()
который устанавливает self.espconnecting = True и запускает индикатор выполнения self.sp_pbar.start()
а затем вызывает _update_conn_progress()
который проверяет значение self.espconnecting . Если для self.espconnecting установлено значение True (которое в настоящее время установлено), соединение продолжается, а индикатор выполнения продолжает вращаться, как и ожидалось. Если для self.espconnecting установлено значение False, индикатор выполнения останавливается self.sp_pbar.stop()
Прежде чем .after() сможет выполнить обратный вызов через 500 мс, управление передается обратно в _connect_esp, который устанавливает self.espconnecting = False . Затем .after() вызывает _update_conn_progress(), который предназначен для того, чтобы полоса продолжала двигаться,
но (вот ваша проблема): каково последнее значение self.espconnecting ? =False, следовательно, управление переходит к self.sp_pbar.stop() , что останавливает полосу прогресса. Вот почему, когда вы прокомментируете эту строку, ваш код работает так, как ожидалось, потому что даже если управление разветвится там, ничто не помешает работе индикатора выполнения.
РЕШЕНИЕ
Не устанавливайте self.espconnecting = False в _connect_esp(), потому что до того, как .after() выполнит обратный вызов через 500 мс, управление будет передано обратно в _connect_esp(), который устанавливает self.espconnecting = False, что предотвращает отображение индикатора выполнения. работает.
Это означает, что вам нужно найти другой способ "разорвать соединение", как только оно будет установлено.
Примечание: я действительно не вижу необходимости в time.sleep(5) в коде.
Вот возможный способ решить эту проблему:
time.sleep(5) представляет выполнение другой функции, которая занимает некоторое время. Индикатор выполнения используется для указания в графическом интерфейсе, выполняется ли функция.
self.espconnecting = False в методе _connect_esp() в конце задачи необходимо указать, что процесс подключения завершен. Это уместно. Удаление этого приведет к ошибочному поведению.
Вы правы. дело в том, чтобы найти другой способ разорвать соединение. Я отредактировал свой ответ, проверьте его еще раз.
Спасибо за попытку помочь. ;) Однако я пришел к выводу, что метод .after() не может реализовать неопределенный индикатор выполнения в моем сценарии. Это связано с тем, что метод time.sleep(5), используемый для имитации подключения, просто сообщает компьютеру о переходе в спящий режим на 5 секунд. Во время которого не разрешается запускать даже метод .after(), хотя он требует гораздо более короткого промежутка времени. Счетчик, который вы изначально реализовали, искажает некоторые движения в индикаторе выполнения. Однако всегда есть задержка перед движением. Кроме того, если будет предпринята серия подключений, подделка не сработает.
Я приложил ответ, показывающий, как использовать asyncio для реализации индикатора выполнения. Надеюсь, это может быть полезно для вас.
Метод tkinter .after() нельзя использовать для реализации неопределенного виджета ttk.Progressbar() одновременно с другим текущим процессом. Это связано с тем, что текущий процесс, моделируемый методом time.sleep(5), мешает приложению tkinter запускать другой процесс. Во время остановки даже метод .after() не может работать, несмотря на то, что у него гораздо более короткий интервал ожидания.
Как упоминалось в комментариях @Lukas и ссылках, которыми он поделился, подход к реализации неопределенного ttk.Progressbar(), работающего одновременно с другим процессом приложения, заключается в использовании thread.daemon из модуля потоковой обработки Python для управления параллелизмом.< /p>
В качестве альтернативы можно использовать асинхронную инфраструктуру Python для реализации неопределенного ttk.Progressbar(), работающего одновременно с другим процессом приложения. Недавно я исследовал эту возможность. Предостережение в отношении этого подхода заключается в том, что «процесс остановки», а также активация и завершение ttk.Progressbar должны быть записаны в отдельных сопрограммах.
Ниже мой скрипт показывает, как реализовать asyncio с tkinter 8.6 и его виджетом ttk.Progressbar() в Python 3.6.
С точки зрения макросов кажется, что реализация tkinter в асинхронном цикле обработки событий Python может облегчить разработку более качественных приложений с графическим интерфейсом.Я обнаружил это сам и надеюсь, что этот прикрепленный скрипт поможет другим пользователям tkinter в этом.
Прежде чем мы начнем: это руководство по Python является частью нашей серии руководств по пакетам Python. Вы также можете найти другие темы, связанные с Tkinter!
Tkinter — самый популярный способ создания графических пользовательских интерфейсов (GUI) в Python. Для создания графических интерфейсов Tkinter предоставляет разработчикам ряд стандартных виджетов, включая кнопки, метки и текстовые поля.
Каждый из этих виджетов необходимо расположить таким образом, чтобы он был доступен для пользователя и сфокусирован на виджете, а затем запрограммировать с помощью базовой логики приложения, чтобы они могли работать должным образом в ответ на щелчки мыши и другие действия.
Позиционирование виджетов с помощью менеджеров компоновки
Tkinter имеет три встроенных менеджера компоновки, которые используют геометрические методы для позиционирования виджетов во фрейме приложения:
- pack() организует виджеты в горизонтальные и вертикальные блоки, которые ограничены левым, правым, верхним и нижним позициями. Каждое поле смещено относительно друг друга.
- place() размещает виджеты в двумерной сетке с использованием абсолютных координат x и y.
- grid() находит виджеты в двумерной сетке, используя абсолютные координаты строки и столбца.
Важно: pack(), place() и grid() не должны быть объединены в одном главном окне. Вместо этого выберите один и придерживайтесь его.
Посмотрите видео, в котором представлены фрагменты кода pack, place и grid ниже
Позиционирование виджетов с помощью менеджера компоновки пакетов
pack — это самый простой менеджер компоновки для использования с Tkinter. Вместо объявления точного местоположения виджета pack() объявляет расположение виджетов по отношению друг к другу. Однако точность pack() ограничена по сравнению с place() и grid(), которые используют абсолютное позиционирование. Для простого позиционирования виджетов по вертикали или горизонтали по отношению друг к другу лучше всего использовать pack().
pack() имеет четыре варианта заполнения:
- Внутреннее заполнение
- Внешнее заполнение
- Padx , который перемещается вдоль оси X
- Pady , который перемещается вдоль оси Y
Для получения дополнительной информации о pack() и его параметрах см.: Как расположить кнопки в Tkinter с помощью Pack
Вертикальное позиционирование с пакетом
В этом примере три ярлыка (виджеты, содержащие текст или изображения) расположены вертикально по отношению друг к другу и не дополняются.
Расположение рядом с пакетом
В этом примере три ярлыка расположены рядом друг с другом и разделены отступами:
Позиционирование виджетов с помощью Place Layout Manager
place() позволяет расположить виджет либо с абсолютными координатами x,y, либо относительно другого виджета.
В этом примере три метки расположены по диагонали с использованием координат x,y.
Позиционирование виджетов с помощью Grid Layout Manager
grid() размещает виджеты в двумерной сетке строк и столбцов, аналогичной электронной таблице.
В этом примере четыре ярлыка расположены в сетке строк и столбцов:
Позиционирование виджетов Tkinter.Ttk
Модуль tkinter.ttk (расширение плитки, интегрированное в Tk) обеспечивает доступ к тематическому набору виджетов Tk, включенному в Tk 8.5 и выше.
Шесть новых виджетов добавлены Ttk:
Все шесть являются подклассами Widget.
Существуют различия в кодировании темы Ttk, включая параметры выравнивания и заполнения для шести новых виджетов. Однако позиционирование с помощью менеджеров компоновки пакетов, мест и сетки остается таким же, как у Tk.
Использование ТТК
Чтобы начать использовать Ttk, введите следующий оператор импорта в консоли Python:
Чтобы переопределить виджеты Tk, импорт ttk должен следовать за импортом tk:
Импорт tkinter.ttk после импорта tkinter приводит к тому, что виджеты Ttk автоматически заменяют стандартные виджеты Tk Button, Checkbutton, Entry, Frame, Label, LabelFrame, Menubutton, PanedWindow, Radiobutton, Scale и Scrollbar.
Важно: Основная идея состоит в том, чтобы максимально отделить код, реализующий поведение виджета, от кода, реализующего его внешний вид ( Style() )< /эм>.
Имейте в виду, что хотя виджеты Ttk имеют параметр Style()padding, он не влияет на позиционирование виджета.
Позиционирование виджетов Ttk с помощью Pack
В этом примере файл ttk.кнопка позиционируется с помощью pack() и дополняется.
Дальнейшие шаги
Теперь, когда вы знаете, как добавлять виджеты с помощью Python Tkinter, давайте перейдем к другим вещам, которые вы можете делать с помощью Tkinter:
Python для науки о данных
ActivePython поставляется с наиболее важными пакетами, необходимыми специалистам по обработке и анализу данных, предварительно скомпилирован, поэтому вам и вашей команде не придется тратить время на настройку дистрибутива с открытым исходным кодом. Вы можете сосредоточиться на том, что важно: тратить больше времени на создание алгоритмов и прогностических моделей для больших источников данных и меньше времени на настройку системы.
Читайте также: