sobota, 6 maja 2017

Walka z zakładkami.

Funkcjonowanie Tkinter potrafi niejednokrotnie zaskoczyć, co może owocować niespodziewanym działaniem programu. Podczas przełączanie zakładek w widget'cie ttk.Notebook następuje zmiana elementu, który aktualnie posiada focus. Jest on przełączany na elementy umieszczone w zakładce, którą aktywowano. Działanie to może być niepożądane, jeśli w karcie znajduje się np. ttk.Entry, ponieważ spowoduje to zaznaczenie całego obecnego w elemencie tekstu.

Aby temu zapobiec można przekazać parametr "takefocus" o wartości "False", podczas tworzenia instancji "ttk.Entry". Ma to jednak poważne działanie uboczne, ponieważ wyłącza możliwość przełączania aktywnych elementów za pomocą przycisku Tab. Takie rozwiązanie odpada. Ponadto focus zostanie przeniesiony na kolejny obiekt znajdujący się na zakładce.

Inną możliwością jest bind'owanie do danej zakładki metody, w oparciu o "event"
"<Visibility>" i przypisanie jej odpowiedniego wywołania callback. "Event" ten zostaje aktywowany w momencie kiedy dany element staje się widoczny na ekranie.

self.tab_1.bind('<Visibility>', lambda event,
    tab=self.tab_1:callback_method(event, tab))

Następnie używając zdefiniowanej metody callback_method, można przenieść focus na inny element, w tym wypadku na samą zakładkę, która jest przekazywana do tej metody. To rozwiązanie działa, ale pozostawia po sobie pewne artefakty.

Tekst obecny w ttk.Entry nie jest zaznaczony, ale posiada pewne zauważalne pogrubienie. Jeśli możliwość wpisywania teksu do ttk.Entry została zablokowana poprzez ustawienie "state" na wartość "readonly", to tło teksu w takim polu zmienia kolor na biały. Jest to pewnie związane z tym, że tekst został zaznaczony podczas przełączania zakładki, po czym focus został przeniesiony na inny obiekt. W związku z tym, że są to obiekty stylizowane ttk, nie można tego szybko naprawić poprzez zmianę "hightlightthickness", czy "hightlightbackground", prawdopodobnie konieczne byłoby zdefiniowanie odpowiedniego stylu ttk.

Rozwiązanie okazało się proste i było raczej niespodziewane. Otóż podczas przełączanie zakładki focus zostaje przeniesiony zgodnie z obecną hierarchią powstałą między obiektami, a związaną z przypisywaniem danych elementów do siebie. W celu zdefiniowania wielkości samej zakładki konieczne jest utworzenie obiektu typu Frame lub ttk.Frame, która jest najwyżej w hierarchii. Widget'y te mają domyślnie ustawiony parametr "takefocus" na "False". Po zmianie wartości na "True", ramka będzie pierwszym obiektem w kolejce do otrzymania focus'a. Na ramce natomiast nie widać żadnego efektu zaznaczenia, problem został rozwiązany.

Brak komentarzy:

Prześlij komentarz