Tkinter неправильно отображает кадры после Grid_remove() в macOSPython

Программы на Python
Ответить
Anonymous
 Tkinter неправильно отображает кадры после Grid_remove() в macOS

Сообщение Anonymous »

У меня следующая проблема. Я создал настольное приложение для создания счетов для компании моего отца. Машина, для которой я написал это приложение, — это iMac 2011 года выпуска под управлением macOS High Sierra (10.13.6). Поскольку у меня нет Mac для тестирования и возраст целевой системы, я выбрал tkinter для реализации графического пользовательского интерфейса главным образом из-за его кросс-платформенной совместимости (и поскольку я учил, что tkinter довольно старый, поэтому у него хорошие шансы работать на старой OS X).
Теперь, когда мое приложение почти закончено и у меня была возможность протестировать его под OS X, я обнаружил ошибку, связанную с отображением страниц. Мое приложение имеет несколько страниц, из которых пользователь может выбирать. Страницы реализованы в виде фреймов с соответствующим содержимым, размещенным сверху. Для переключения между страницами я написал виджет под названием «pageSwitcher». Этот виджет сохраняет текущий объект страницы в переменной класса (

Код: Выделить всё

self.currentlyDisplayedPage
), и если срабатывает переключение страниц, .grid_remove() текущая страница сохраняет страницу, на которую нужно переключиться (новую текущую страницу), в переменную и отображает новую текущую страницу с помощью вызова .grid().

Проблема описана здесь
Под Linux (Ubuntu 24.04.3 LTS) это работает отлично. Но под OSX (10.13.6) поведение другое. Когда я впервые переключаюсь на страницу, она отображается правильно. Но если я попытаюсь переключиться на страницу, которая отображалась ранее в текущей среде выполнения, она просто не будет отображаться, пока я не выполню одно из следующих действий:
Если я щелкну за пределами приложения (например, рабочего стола), страница будет отображаться правильно. Кроме того, если я наведу указатель мыши на элементы, имеющие привязки событий или , страница отобразится, как только я наведу на них указатель мыши. Кроме того, работают интерактивные элементы, такие как записи и кнопки; как только я нажимаю на запись или кнопку, страница отображается, а в случае кнопки выполняются соответствующие функции. Насколько я вижу, новая страница установлена, и все виджеты присутствуют, но они не отображаются, пока я не выполню одну из операций, подробно описанных выше.
Я пытался это исправить:
Используя .update_idletasks(), чтобы принудительно отобразить страницу. Это сделало его иногда лучше, иногда хуже (страница будет отображаться, но в худшем случае это может занять несколько минут). Поэтому я решил, что это не решение. Я также пытался использовать другую версию Python (с 3.12.12 по 3.14.2), надеясь, что это ошибка в конкретной версии (чего, похоже, не было). Я тестировал это под OSX Sequoia (15.7.3) и (к сожалению) получил те же результаты, поэтому предполагаю, что это не ошибка в конкретной версии OSX.
Я не знаю, почему это происходит и как это исправить. Вот минимальный пример, который выдает ошибку при использовании пустых (цветных) фреймов в качестве страниц:

Код: Выделить всё

import tkinter as tk

class PageSwitcher(tk.Frame):
def __init__(self, parent:tk, desiredHeight:int, desiredWidth:int) -> None:
self.managedPages:list[tk.Frame] = []
self.currentlyDisplayedPage:tk.Frame = None

tk.Frame.__init__(self, parent, height=desiredHeight, width=desiredWidth)
self.grid_propagate(False)
self.rowconfigure(index=(0,2), weight=1)
self.columnconfigure(index=(0,2), weight=1)

def addPage(self, pageToAdd:tk.Frame) -> None:
self.managedPages.append(pageToAdd)

def displayPage(self, pageId:int) -> None:
if self.currentlyDisplayedPage != None:
self.currentlyDisplayedPage.grid_remove()
self.currentlyDisplayedPage = self.managedPages[pageId]
self.currentlyDisplayedPage.grid(row=1, column=1)

class PageSelector(tk.Frame):
def __init__(self, parent:tk, desiredHeight:int, desiredWidth:int, pageSwitchFunction) -> None:
self.pageSwitchFunction = pageSwitchFunction
self.width = desiredWidth
self.managedSelectors:list[PageSelector.Selector] = []

tk.Frame.__init__(self, parent, height=desiredHeight, width=desiredWidth)
self.grid_propagate(False)

def registerPage(self, pageName:str, pageId:int):
selector = self.Selector(
parent=self,
desiredWidth=self.width-10, #For 5px of padding on each side of selector
name=pageName,
pageId=pageId,
selectFunction=self.select
)
selector.grid(row=self.grid_size()[1], column=0, padx=5, pady=2)
self.managedSelectors.append(selector)

def select(self, pageId) -> None:
self.pageSwitchFunction(pageId)

class Selector(tk.Frame):
def __init__(self, parent:tk, name:str, pageId:int, selectFunction, desiredWidth:int) -> None:
self.pageId = pageId
self.selectFunction = selectFunction

tk.Frame.__init__(self, parent, height=32, width=desiredWidth, border=2, relief="raised")
self.grid_propagate(False)

self.name = tk.Label(self, text=name, font="Bold")
self.name.grid(row=1, column=0, padx=5)

self.bind("", self.select)
self.name.bind("", self.select)

def select(self, event:tk.Event) -> None:
self.selectFunction(self.pageId)

def main():
height = 600
width = 600

window = tk.Tk()
window.geometry(f"{width}x{height}")

pageSwitcher = PageSwitcher(window, height, width//2)
pageSelector = PageSelector(window, height, width//2, pageSwitcher.displayPage)
pageSwitcher.grid(row=0, column=1)
pageSelector.grid(row=0, column=0)

pageNamesAndColors = ["red", "orange", "yellow", "green", "lime", "lightBlue", "blue", "purple", "pink"]

for index, color in enumerate(pageNamesAndColors):
newPage = tk.Frame(pageSwitcher, height=height, width=width//2, bg=color)
pageSwitcher.addPage(newPage)
pageSelector.registerPage(pageName=f"{color} Page", pageId=index)

window.mainloop()

main()
Я использую Python 3.14.2 с Tcl/Tk 8.6.17. Я использую Python и tkinter из macports.
Я создаю автономное приложение ondir с помощью pyinstaller. Но ошибка возникает при непосредственном запуске кода и при запуске сборки приложения с помощью pyinstaller.
Если кто-то знает решение, которое не требует, чтобы я сам исправлял Tcl/Tk (я где-то читал, что Tcl/Tk содержит ошибки под OSX) или переписывал все мое приложение в другой среде графического интерфейса, которая «я знаю, работает под OSX», дайте мне знать.

Подробнее здесь: https://stackoverflow.com/questions/798 ... nder-macos
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»