После нажатия на поле со списком отображается раскрывающийся список. Подождите 2 секунды, страница браузера станет активной, и вы обнаружите, что раскрывающийся список остается видимым, а само тестовое приложение скрыто.
import tkinter as tk
import webbrowser
from tkinter import ttk
root = tk.Tk()
root.geometry("300x200")
combo = ttk.Combobox(root, state = "readonly")
combo['values'] = ["Option 1", "Option 2", "Option 3"]
combo.bind('<Button-1>', lambda event: root.after(2000, lambda: webbrowser.open("https://stackoverflow.com")))
combo.pack()
root.mainloop()
С Python 3.12.4
Я ожидаю, что раскрывающийся список исчезнет вместе с самим тестовым приложением. Также я хотел бы получить <FocusOut>
мероприятие на root
.
🤔 А знаете ли вы, что...
С Python можно создавать кросс-платформенные приложения для Windows, macOS и Linux.
Проблема заключалась в том, что dropdown list
, который вы видите, на самом деле является отдельным окном. если вы посмотрите на его атрибуты с помощью команды «атрибуты», то увидите следующее:
-alpha 1.0 -transparentcolor {} -disabled 0 -fullscreen 0 -toolwindow 0 -topmost 1
Таким образом, ваше окно всегда появляется поверх всех других окон, потому что topmost
установлено в 1. Решение очевидно: установите для «-topmost» значение 0 при создании dropdown list
, чтобы оно не появлялось поверх всего. Вам также необходимо убедиться, что, если он не сопоставлен, вы закрываете его. Итак, код:
import tkinter as tk
from tkinter import ttk
import webbrowser
root = tk.Tk()
root.geometry("300x200")
combo = ttk.Combobox(root, state = "readonly")
combo['values'] = ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5", "Option 6"]
combo.bind('<Button-1>', lambda event: root.after(2000, lambda: webbrowser.open("https://stackoverflow.com")))
combo.pack()
def on_widget_map(event: tk.Event):
root.eval(f"wm attributes {event.widget} -topmost 0")
root.bind_class("ComboboxPopdown", '<Map>', on_widget_map, add='+')
root.mainloop()
Теперь вы можете видеть, что приведенный выше код все еще может работать не полностью. Я думаю, что можно регулярно проверять, находится ли dropdown
ниже root
. Если да, то закройте его. Обновленный код:
...
combo.pack()
def close_if_not_visible(dropdown_list):
if root.eval(f"winfo ismapped {dropdown_list}") == '0':
return
if root.eval(f"wm stackorder {dropdown_list} isabove .") == '1':
root.after(50, lambda: close_if_not_visible(dropdown_list))
else:
root.focus_set()
def on_widget_map(event: tk.Event):
root.eval(f"wm attributes {event.widget} -topmost 0")
root.bind_class(event.widget, '<Unmap>', lambda _e: root.focus_set())
close_if_not_visible(event.widget)
root.bind_class("ComboboxPopdown", '<Map>', on_widget_map, add='+')
root.mainloop()
Если у вас есть какие-либо вопросы по коду или что-то по-прежнему не работает должным образом, не стесняйтесь спрашивать.