Есть ли способ добавить кнопки закрытия и добавления вкладок в tkinter.ttk.Notebook?

введите сюда описание изображения Я хочу добиться эффекта, показанного на картинке. Нажмите знак плюса, чтобы добавить тег, нажмите «Закрыть», чтобы закрыть тег.

Я могу сделать это с помощью двух отдельных функций, но не могу сделать это с двумя функциями вместе.

Как мне добиться этого с помощью ttk.Notebook?

О кнопке закрытия см. этот вопрос: есть ли способ добавить кнопки закрытия на вкладки в тетради tkinter-ttk-n‌​.

acw1668 25.07.2024 11:40

Согласно этому методу, моя кнопка «плюс» также имеет значок закрытия, а это не то, что мне нужно.

dragonkyl 25.07.2024 11:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
81
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Чтобы добиться описанного эффекта с помощью ttk.Notebook, вам необходимо создать пользовательскую вкладку, включающую в себя как тег, так и кнопку закрытия. Вот краткий способ сделать это:

Создайте фрейм для вкладки: этот фрейм будет содержать как тег (метку), так и кнопку закрытия. Добавьте рамку в блокнот. Вставьте рамку в ttk.Notebook как вкладку. Привязка кнопки закрытия: прикрепите команду к кнопке закрытия, чтобы удалить вкладку.

пример кода: импортировать tkinter как tk из tkinter import ttk def add_tab():frame = ttk.Frame(notebook) label = ttk.Label(frame, text = "New Tag") label.pack(side = "left") close_btn = ttk.Button(frame, text = "x", команда=lambda: Notebook.forget(frame)) close_btn.pack(side = "right") Notebook.add(frame, text = "") # Корень основного приложения = tk.Tk() блокнот = ttk.Notebook(root) Notebook.pack(expand=True, fill='both') add_button = ttk.Button(root, text = "+", команда=add_tab) add_button.pack() корень.mainloop()

Kadir Baran Aksoy 25.07.2024 11:39

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

TheLizzard 25.07.2024 11:42

Спасибо, но эффект, который мне нужен, - это эффект на моей картинке, очевидно, ваш код далек от того, что мне нужно

dragonkyl 25.07.2024 11:51

С помощью tkinter сложно добиться того, чего вы хотите, потому что вам потребуются два типа вкладок: обычные вкладки с кнопкой закрытия и дополнительная вкладка со значком «добавить».

Не слишком сложный способ добиться результата, достаточно похожего на то, что вам хотелось бы, — это взять класс CustomNotebook из Есть ли способ добавить кнопки закрытия вкладок в tkinter.ttk.Notebook? чтобы получить кнопку закрытия вкладок и добавить дополнительную кнопку «Добавить» в верхнем левом углу блокнота для создания новых вкладок:

class AddBtnNotebook(CustomNotebook):

    def __init__(self, *args, **kwargs):
        CustomNotebook.__init__(self, *args, **kwargs)

        self._img = tk.PhotoImage(data=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\xb3IDATx\x9c\xb5\xd31j\x82A\x14\x04\xe0\xef\x89v\xb1H)hk*/\x912x\x81\x94\x9e\xc0\xce\xcb\xd8\xeb\xa9\xb41`\x93\x80`J\xc9\xa6QX\x7fw\xe1\x8f\x92\x81)fwf\xd8]\xdeJ))\x11\x0b|\xe1\x13\xf3\xaa\xaf\x12\x9e e\xfc\xc1\xb8\xe4\xed(c\xd4\xd0\x81a\xc9X+h\x8d\x87\x0b\xba\x10\x11]\xf4\xb3\xf5\xa7\x82\xb7\x1f\x11\xcf\x99>\xa6\x94N0\xc5\xc1\xf5\xa3\xb5\xe1\xe1\x9c\xb5\xbd#|\xe16p\xac\x1c\xb9\r\xbe;X\xdd\x19\x86U\xa0\x87w\x0c\xb2\x8d\x17\xcc\x1a\xe6%6\x99\xdec]\x9b\xc47\xb7\xf7}\xfd\xcb$\xb6\xc6\xbf\x15\xec\x1a:\xe1\xa3\xe8|\xf4;\xff\x02/@\xbfn\x03\x8cH\xb7\x00\x00\x00\x00IEND\xaeB`\x82')
        self.add_button = ttk.Button(self, image=self._img, command=self.add_tab, padding=0)
        self.add_button.place(relx=1, rely=0, anchor = "ne")
    
    def add_tab(self):
        frame = tk.Frame(self)
        notebook.add(frame, text = "New Tab")

Приведенный выше код также можно напрямую интегрировать в исходный код CustomNotebook, но я не хотел повторять его здесь, поскольку он уже доступен с пояснениями в Есть ли способ добавить кнопки закрытия вкладок в tkinter.ttk.Notebook ?.

Отказ от ответственности: это решение не очень хорошо обрабатывает изменение размера (кнопка добавления перекрывает вкладки) и не всегда находится рядом с последней вкладкой, как на рисунке в вопросе.

Ответ принят как подходящий

Как было предложено в комментариях @acw1668 , для кнопок закрытия вы можете просто использовать код из этого ответа.

Что касается кнопки «Добавить», то я думаю, что существует несколько способов ее создания. Я покажу вам метод, который создаст дополнительную вкладку «Добавить». Основная идея заключается в том, что вы просто устанавливаете для этого состояния вкладки «Добавить» значение «отключено» и добавляете дополнительную логику в код кнопки закрытия для выполнения специальных действий, если вкладка «отключена».

Добавьте вкладку «Добавить» в метод __init__:

...
ttk.Notebook.__init__(self, *args, **kwargs)
self.add(tk.Frame(self), state='disabled')  # "+" tab
...

Измените метод on_close_press, чтобы добавить дополнительную логику в случае нажатия кнопки «Добавить»:

...
index = self.index("@%d,%d" % (event.x, event.y))
if self.tab(index, 'state') == 'disabled':  # "+" tab is pressed
    self.add_new_tab(index)
    return "break"
...

Где add_new_tab ваш метод, создающий новую вкладку.

Теперь добавьте изображение «+» к self.images:

...
tk.PhotoImage("img_add", data='''
    iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAA
    AARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB+SURBVChTY2ZA
    AyJSxtVcPFJq3748Pw8VAgMmKI0EGHkZGZi4oBw4wKIQOyBaISPITSDroHyG//8Z
    7IHkF0ZGxrNQIQZGxv/vmRj+M7xg/M/4FIZBioByH1HE/jO9hGhBAiJSJh2ikqa5
    UC4cUN8zGApBDmdgZPgM5UIBAwMAe9MjkX8aHzEAAAAASUVORK5CYII=''')
...

И, наконец, просто добавьте дополнительный «отключенный» регистр в element_create:

...
("disabled", "img_add"),
...

Полный код (с примером метода add_new_tab):

class CustomNotebook(ttk.Notebook):
    """A ttk Notebook with close buttons on each tab"""

    __initialized = False

    def __init__(self, *args, **kwargs):
        if not self.__initialized:
            self.__initialize_custom_style()
            self.__inititialized = True

        kwargs["style"] = "CustomNotebook"
        ttk.Notebook.__init__(self, *args, **kwargs)
        self.add(tk.Frame(self), state='disabled')  # "+" tab

        self._active = None

        self.bind("<ButtonPress-1>", self.on_close_press, True)
        self.bind("<ButtonRelease-1>", self.on_close_release)

    def on_close_press(self, event):
        """Called when the button is pressed over the close button"""

        element = self.identify(event.x, event.y)
        if "close" in element:
            index = self.index("@%d,%d" % (event.x, event.y))
            if self.tab(index, 'state') == 'disabled':  # "+" tab is pressed
                self.add_new_tab(index)
                return "break"
            self.state(['pressed'])
            self._active = index
            return "break"

    def on_close_release(self, event):
        """Called when the button is released"""
        if not self.instate(['pressed']):
            return

        element =  self.identify(event.x, event.y)
        if "close" not in element:
            # user moved the mouse off of the close button
            return

        index = self.index("@%d,%d" % (event.x, event.y))

        if self._active == index:
            self.forget(index)
            self.event_generate("<<NotebookTabClosed>>")

        self.state(["!pressed"])
        self._active = None

    def add_new_tab(self, add_index):
        """Adds a new tab on button "+" pressed"""
        pass
        # Your code for the new tab there. Example:
        self.insert(add_index, tk.Label(text='Just a test tab'), text='NewTab')
        self.select(add_index)

    def __initialize_custom_style(self):
        style = ttk.Style()
        self.images = (
            tk.PhotoImage("img_close", data='''
                R0lGODlhCAAIAMIBAAAAADs7O4+Pj9nZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg
                d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU
                5kEJADs=
                '''),
            tk.PhotoImage("img_closeactive", data='''
                R0lGODlhCAAIAMIEAAAAAP/SAP/bNNnZ2cbGxsbGxsbGxsbGxiH5BAEKAAQALAAA
                AAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU5kEJADs=
                '''),
            tk.PhotoImage("img_closepressed", data='''
                R0lGODlhCAAIAMIEAAAAAOUqKv9mZtnZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg
                d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU
                5kEJADs=
            '''),
            tk.PhotoImage("img_add", data='''
                iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAA
                AARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB+SURBVChTY2ZA
                AyJSxtVcPFJq3748Pw8VAgMmKI0EGHkZGZi4oBw4wKIQOyBaISPITSDroHyG//8Z
                7IHkF0ZGxrNQIQZGxv/vmRj+M7xg/M/4FIZBioByH1HE/jO9hGhBAiJSJh2ikqa5
                UC4cUN8zGApBDmdgZPgM5UIBAwMAe9MjkX8aHzEAAAAASUVORK5CYII=''')  # "+" image
        )

        style.element_create("close", "image", "img_close",
                            ("active", "pressed", "!disabled", "img_closepressed"),
                            ("active", "!disabled", "img_closeactive"),
                            ("disabled", "img_add"), border=8, sticky='')
        style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})])
        style.layout("CustomNotebook.Tab", [
            ("CustomNotebook.tab", {
                "sticky": "nswe",
                "children": [
                    ("CustomNotebook.padding", {
                        "side": "top",
                        "sticky": "nswe",
                        "children": [
                            ("CustomNotebook.focus", {
                                "side": "top",
                                "sticky": "nswe",
                                "children": [
                                    ("CustomNotebook.label", {"side": "left", "sticky": ''}),
                                    ("CustomNotebook.close", {"side": "left", "sticky": ''}),
                                ]
                        })
                    ]
                })
            ]
        })
    ])

И последнее: помните, что кнопка «Добавить» — это вкладка, поэтому, если вы добавите другие вкладки с помощью команды Notebook.add(), новые вкладки будут добавлены после вкладки «Добавить». Вместо этого вы можете использовать команду notebook. insert().

Примечание. Этот код еще можно улучшить. Например, вы можете добавить дополнительное изображение (и логику), чтобы сделать вкладку «Добавить» более динамичной, точно так же, как это делается с кнопками «закрыть».

Прекрасно работает! Спасибо!

dragonkyl 26.07.2024 03:32

Другие вопросы по теме