Как создать пользовательский заголовок окна в Tkinter?

Как я могу создать собственный заголовок окна в Tkinter? Я попытался сделать это с помощью следующего кода: <br/> <pre><code class="python">from tkinter import Tk, Label, font, Frame, Button

root = Tk()
root['bg'] = '#232428'
root.geometry('350x500')
root.resizable(False, False)
root.overrideredirect(True)
custom_font = font.Font(family='Impact', size=16)

header_frame = Frame(root, bg='#3F3F3F', relief='raised', bd=0)
header_frame.pack(fill='x')
close_button = Button(header_frame, text='x', bg='#3F3F3F', fg='white', activebackground='#C70039',
                      activeforeground='white', bd=0, highlightthickness=0, command=root.destroy, font=custom_font)
close_button.pack(side='right', padx=5)
header_label = Label(header_frame, text='Test',
                     font=custom_font, fg='#FFFFFF', bg='#3F3F3F')
header_label.pack(pady=5)

content_frame = Frame(root, bg='#232428')
content_frame.pack(fill='both', expand=True)


def on_drag_start(event):
    root._offset_x = event.x_root - root.winfo_x()
    root._offset_y = event.y_root - root.winfo_y()


def on_drag(event):
    x = event.x_root - root._offset_x
    y = event.y_root - root._offset_y
    root.geometry(f"+{x}+{y}")


header_frame.bind('&lt;Button-1&gt;', on_drag_start)
header_frame.bind('&lt;B1-Motion&gt;', on_drag)
header_label.bind('&lt;Button-1&gt;', on_drag_start)
header_label.bind('&lt;B1-Motion&gt;', on_drag)

root.mainloop()</code></pre> <br/> <br/> Однако, при выходе из фокуса окна (например, если я щелкаю за пределами окна), оно исчезает и оказывается на фоне, не отображаясь на панели задач, и не ведя себя как полноценное окно. Я хочу, чтобы это было полноценное окно, и мне хотелось бы реализовать такой функционал: <br/>
  • 5 сентября 2024 г. 16:43
Ответы на вопрос 1
Для создания пользовательского заголовка окна в Tkinter и обеспечения его функционирования, как у обычного окна, можно использовать флаг `overrideredirect(False)` и добавить обработку событий мыши для перемещения окна. Ниже приведен пример, где заголовок окна создается с помощью `Frame`, а функциональность окна делается более "обычной".

Вот исправленный пример кода с предложенной функциональностью:

```python
from tkinter import Tk, Label, font, Frame, Button

root = Tk()
root['bg'] = '#232428'
root.geometry('350x500')
root.resizable(False, False)

custom_font = font.Font(family='Impact', size=16)

# Создаем заголовок окна
header_frame = Frame(root, bg='#3F3F3F', relief='raised', bd=0)
header_frame.pack(fill='x')

# Кнопка закрытия
close_button = Button(header_frame, text='x', bg='#3F3F3F', fg='white', activebackground='#C70039',
                      activeforeground='white', bd=0, highlightthickness=0, command=root.destroy, font=custom_font)
close_button.pack(side='right', padx=5)

# Метка с названием
header_label = Label(header_frame, text='Test', font=custom_font, fg='#FFFFFF', bg='#3F3F3F')
header_label.pack(pady=5)

# Основной контент
content_frame = Frame(root, bg='#232428')
content_frame.pack(fill='both', expand=True)

# Перемещение окна
def on_drag_start(event):
    root._offset_x = event.x_root - root.winfo_x()
    root._offset_y = event.y_root - root.winfo_y()

def on_drag(event):
    x = event.x_root - root._offset_x
    y = event.y_root - root._offset_y
    root.geometry(f"+{x}+{y}")

# Привязка событий
header_frame.bind('<Button-1>', on_drag_start)
header_frame.bind('<B1-Motion>', on_drag)
header_label.bind('<Button-1>', on_drag_start)
header_label.bind('<B1-Motion>', on_drag)

# Обработка того, что окно не должно исчезать
def on_focus_out(event):
    root.lift()  # Поднять окно
    root.focus_force()  # Убедиться, что окно остается в фокусе

root.bind('<FocusOut>', on_focus_out)

root.mainloop()
```

### Объяснение изменений:

1. Убрана строка `overrideredirect(True)`, так как этот флаг убирает стандартный рамки окна и делает его "плавающим", что может привести к нежелательному поведению.

2. Добавлена обработка события `<FocusOut>`, чтобы окно не исчезало из фокуса. При потере фокуса мы просто поднимаем окно, используя метод `lift()`.

Теперь ваше окно будет вести себя, как обычное окно, и не будет исчезать из панели задач. Вы также сможете его перемещать с помощью заголовка, который вы создали.
Похожие вопросы