Python基礎之tabview


以前寫過界面,但是沒有記錄下來,以至於現在得從頭學習一次,論做好筆記的重要性。

現在學習的是怎么寫一個tabview出來,也就是用tkinter做一個界面切換的效果。參考鏈接:https://blog.csdn.net/yingshukun/article/details/89150105

tabview.py

import tkinter as tk
import tkinter.ttk as ttk


class TabView(tk.Frame):
    _tabs = []
    _tab_view = []
    _tab_text = []
    _current = 0  # 當前選中tab的索引
    _generate_func = None
    _select_listen = None
    _remove_listen = None

    '''
        select_listen: tab選中事件回調函數,回調函數包含一個index參數
        remove_listen: tab刪除事件回調函數,返回值必須是一個布爾值,True表示刪除,反之不刪除
        generate_body: 生成body控件的回調函數,返回值應該是一個widget,用於添加到body中
    '''

    def __init__(self, master=None, select_listen=None,
                 remove_listen=None, generate_body=None, cnf=None, **kw):
        super().__init__(master, cnf, **kw)
        # 選項卡
        self._top = tk.Frame(self)
        self._top.bind("<Double-Button-1>", self._tab_add)
        self._top.pack(fill="x")

        # 分割線
        ttk.Separator(self, orient=tk.HORIZONTAL).pack(fill="x")

        # 主體view
        self._bottom = tk.Frame(self)
        self._bottom.pack(fill="both", expand="yes")
        self._photo = tk.PhotoImage(file="remove.gif")

        # 事件回調
        if select_listen:
            if callable(select_listen):
                self._select_listen = select_listen
            else:
                raise Exception("select_action is not callable")

        if remove_listen:
            if callable(remove_listen):
                self._remove_listen = remove_listen
            else:
                raise Exception("remove_action is not callable")

        if generate_body:
            if callable(generate_body):
                self._generate_func = generate_body
            else:
                raise Exception("generate_body is not callable")

    # 添加選項卡
    def add_tab(self, view, text):
        self._add_body(view)
        self._create_tab(text)

    #  刪除選項卡
    def remove_tab(self, index):
        self._tab_text.pop(index)

        self._tabs[index].destroy()
        self._tab_view[index].destroy()

        self._tabs.pop(index)
        self._tab_view.pop(index)

        if index > 0:
            self._current = index - 1
            self._active()

    @property
    def body(self):
        return self._bottom

    def _create_tab(self, text):
        # 選項卡單元
        tab_container = tk.Frame(self._top, relief=tk.RAISED, bd=1)

        # 標題、刪除按鈕
        _tab_text_view = tk.Label(tab_container, text=text, padx=8)
        _tab_remove_view = tk.Label(tab_container, image=self._photo)

        _tab_text_view.bind("<Button-1>", self._tab_click)
        _tab_remove_view.bind("<Button-1>", self._tab_remove)

        _tab_text_view.pack(side=tk.LEFT)
        _tab_remove_view.pack(side=tk.LEFT)
        tab_container.pack(side=tk.LEFT)
        self._tab_text.append(_tab_text_view)
        self._tabs.append(tab_container)
        self._active()

    def _add_body(self, view):
        self._tab_view.append(view)
        view.place(relwidth=1.0, relheight=1.0)

    # 刷新當前激活狀態
    def _active(self):
        for i, item in enumerate(self._tabs):
            if i == self._current:
                item.config(relief=tk.RAISED, bd=3)
                # lift方法,讓當前widget處於最頂層
                self._tab_view[self._current].lift()
            else:
                item.config(bd=1)

    def _tab_add(self, event):
        self._current = len(self._tabs)
        if not self._generate_func:
            self.add_tab(tk.Frame(self.body), "Untitled")
        else:
            self.add_tab(self._generate_func(), "Untitled")

    # 刪除事件回調
    def _tab_remove(self, event):
        current_widget = event.widget.winfo_parent()
        select_index = self._index(current_widget)

        is_remove = True
        if self._remove_listen:
            is_remove = self._remove_listen(select_index)

        if is_remove:
            if select_index != -1:
                self.remove_tab(select_index)

    # 選項卡點擊事件回調
    def _tab_click(self, event):
        current_widget = event.widget.winfo_parent()
        select_index = self._index(current_widget)
        if select_index != -1:
            self._current = select_index
            self._active()

            if self._select_listen:
                self._select_listen(select_index)

    # 返回當前選項卡的索引
    def _index(self, el):
        index = [i for i, x in enumerate(self._tabs) if str(x) == el]
        return index[0] if index else -1
View Code

 

 

對於上面tabview的類,或許會有不太明白的地方,一一解析。

1. Frame

frame其實就像一個布局,一個一個的分區,然后分別往上面添加控件。

2. Bind

綁定事件,比如鼠標單擊,雙擊時需要操作什么

 

這兩個詳細的可以參考:https://www.cnblogs.com/sunzebo/articles/9643620.html

 

3. callable()函數

callable() 函數用於檢查一個對象是否是可調用的。如果返回 True,object 仍然可能調用失敗;但如果返回 False,調用對象 object 絕對不會成功。鏈接:https://www.runoob.com/python/python-func-callable.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM