python 的GUI封装

发布于:2024-12-18 ⋅ 阅读:(117) ⋅ 点赞:(0)

python 的GUI封装

功能扩展点

  • 进度条控件:
    增加对 ttk.Progressbar 的支持,用于展示进度。

  • 列表框控件:
    提供 Listbox 的创建方法,用于展示和选择多项数据。
    复选框和单选按钮:

  • Checkbutton 和 Radiobutton 控件的支持。
    画布和图形支持:
    提供 Canvas 控件,用于绘制图形或复杂的布局。

  • 布局管理器:
    增加对 pack 和 grid 布局的支持,进一步简化界面布局。
    动态更新方法:

为控件增加动态更新内容的方法,比如 update_text 和 update_value。

import tkinter
import tkinter.messagebox
from tkinter.ttk import Progressbar, Combobox

class GuiBase:
    """基础类,提供窗口的初始化和控制"""
    def __init__(self):
        self.root = tkinter.Tk()  # 初始化窗口
        self.tk = tkinter
        self.controls = {}  # 存放控件

    def show(self):
        """显示窗口"""
        self.root.mainloop()

    def quit(self):
        """关闭窗口"""
        self.root.quit()

class GuiAttributes(GuiBase):
    """窗口属性类,提供窗口属性设置方法"""
    def set_title(self, title):
        """设置窗口标题"""
        self.root.title(title)

    def set_icon(self, path):
        """设置窗口图标"""
        self.root.iconbitmap(path)

    def get_screen_size(self):
        """获取屏幕大小"""
        return self.root.maxsize()

    def set_geometry(self, width, height, x=None, y=None):
        """设置窗口大小和位置"""
        if x is None or y is None:
            screen_width = self.root.winfo_screenwidth()
            screen_height = self.root.winfo_screenheight()
            x = (screen_width - width) // 2
            y = (screen_height - height) // 2
        geometry = f"{width}x{height}+{x}+{y}"
        self.root.geometry(geometry)

    def set_bg_color(self, color):
        """设置背景颜色"""
        self.root.configure(background=color)

    def set_resizable(self, width=False, height=False):
        """设置是否可拉伸"""
        self.root.resizable(width=width, height=height)

    def set_topmost(self, topmost=True):
        """设置窗口置顶"""
        self.root.wm_attributes('-topmost', topmost)

    def hide_title_bar(self):
        """隐藏窗口标题栏"""
        self.root.overrideredirect(True)


class GuiControl(GuiBase):
    """控件类,提供常用控件的创建方法"""
    def create_label(self, text, x, y, font=('黑体', 15), fg='black'):
        """创建标签"""
        label = self.tk.Label(self.root, text=text, font=font, fg=fg)
        label.place(x=x, y=y)
        return label

    def create_button(self, text, command, x, y, font=('宋体', 12), fg='black', relief='groove', cursor='hand2'):
        """创建按钮"""
        button = self.tk.Button(self.root, text=text, font=font, fg=fg, relief=relief, cursor=cursor, command=command)
        button.place(x=x, y=y)
        return button

    def create_entry(self, x, y, show=None, font=('黑体', 15), width=20, fg='black'):
        """创建输入框"""
        entry = self.tk.Entry(self.root, font=font, fg=fg, width=width, show=show)
        entry.place(x=x, y=y)
        return entry

    def create_combobox(self, x, y, values, default_value=None, font=('黑体', 12)):
        """创建下拉框(Combobox)"""
        combobox = Combobox(self.root, values=values, font=font)
        combobox.place(x=x, y=y)
        if default_value:
            combobox.set(default_value)
        return combobox

    def create_multiselect_combobox(self, x, y, values, width=20, height=5, font=('黑体', 12)):
        """创建多选下拉框"""
        # 创建容器框架
        frame = self.tk.Frame(self.root)
        frame.place(x=x, y=y)

        # 创建显示框
        entry_var = self.tk.StringVar()
        entry = self.tk.Entry(frame, textvariable=entry_var, font=font, state='readonly', width=width)
        entry.pack(side=self.tk.TOP, fill=self.tk.X)

        # 创建下拉框
        listbox = self.tk.Listbox(frame, selectmode='multiple', font=font, height=height, width=width)
        for value in values:
            listbox.insert(self.tk.END, value)

        # 切换下拉框显示
        def toggle_listbox(event=None):
            if listbox.winfo_ismapped():
                listbox.pack_forget()  # 隐藏下拉框
            else:
                listbox.pack(side=self.tk.BOTTOM, fill=self.tk.X)  # 显示下拉框

        # 更新选中的值
        def update_selection(event=None):
            selected_items = [listbox.get(i) for i in listbox.curselection()]
            entry_var.set(", ".join(selected_items))
            listbox.pack_forget()  # 隐藏下拉框

        # 绑定事件
        entry.bind("<Button-1>", toggle_listbox)  # 点击显示/隐藏下拉框
        listbox.bind("<<ListboxSelect>>", update_selection)  # 选择后更新值

        return listbox, entry_var


    def create_checkbox(self, text, x, y, var=None, font=('黑体', 12)):
        """创建复选框"""
        if var is None:
            var = self.tk.BooleanVar()
        checkbox = self.tk.Checkbutton(self.root, text=text, font=font, variable=var)
        checkbox.place(x=x, y=y)
        return checkbox, var

    def create_radiobutton(self, text, x, y, value, var=None, font=('黑体', 12)):
        """创建单选按钮"""
        if var is None:
            var = self.tk.StringVar()
        def toggle_selection():
            if var.get() == value:
                var.set("")  # 清空选择

        radiobutton = self.tk.Radiobutton(
            self.root,
            text=text,
            font=font,
            value=value,
            variable=var,
            # command=toggle_selection
        )
        radiobutton.place(x=x, y=y)
        return radiobutton, var

    def create_listbox(self, x, y, width=20, height=10, font=('黑体', 12)):
        """创建列表框"""
        listbox = self.tk.Listbox(self.root, font=font, width=width, height=height)
        listbox.place(x=x, y=y)
        return listbox

    def create_progressbar(self, x, y, length=200, mode='determinate', max_value=100):
        """创建进度条"""
        progressbar = Progressbar(self.root, length=length, mode=mode, maximum=max_value)
        progressbar.place(x=x, y=y)
        return progressbar

    def create_canvas(self, x, y, width=400, height=300, bg='white'):
        """创建画布"""
        canvas = self.tk.Canvas(self.root, width=width, height=height, bg=bg)
        canvas.place(x=x, y=y)
        return canvas

    def create_menu(self, menu_items):
        """创建菜单"""
        menubar = self.tk.Menu(self.root)
        for menu_name, commands in menu_items.items():
            menu = self.tk.Menu(menubar, tearoff=0)
            for command_name, command_func in commands.items():
                menu.add_command(label=command_name, command=command_func)
            menubar.add_cascade(label=menu_name, menu=menu)
        self.root.config(menu=menubar)

    def show_message(self, title, message, message_type='warning'):
        """显示提示框"""
        if message_type == 'info':
            self.tk.messagebox.showinfo(title=title, message=message)
        elif message_type == 'error':
            self.tk.messagebox.showerror(title=title, message=message)
        else:
            self.tk.messagebox.showwarning(title=title, message=message)


class Gui(GuiAttributes, GuiControl):
    """综合类,继承属性类和控件类"""
    pass


class DemoApp(Gui):
    """综合示例应用"""

    def update_progress(self, progressbar):
        """更新进度条"""
        for i in range(101):
            progressbar['value'] = i
            self.root.update_idletasks()

    def show_image(self):
        """展示图片"""
        img = self.tk.PhotoImage(file="path_to_your_image.png")
        label = self.create_label('', 50, 50)
        label.config(image=img)
        label.image = img  # 防止图片被垃圾回收

    def toggle_password_visibility(self):
        """切换密码明文/密文显示"""
        entry = self.controls.get("password")
        button = self.controls.get("toggle_button")
        if entry.cget('show') == '*':
            entry.configure(show='')  # 明文显示
            button.configure(text='●')  # 更改按钮文字
        else:
            entry.configure(show='*')  # 密文显示
            button.configure(text='○')  # 更改按钮文字

    def setup_ui(self):
        """设置UI布局"""

        self.create_label("请输入账号和密码:", x=50, y=20)
        self.create_label("账号:", x=50, y=60)
        self.create_label("密码:", x=50, y=100)

        username_entry = self.create_entry(x=100, y=60)
        self.controls["username"] = username_entry

        password_entry = self.create_entry(x=100, y=100, show='*')
        self.controls["password"] = password_entry

        toggle_button = self.create_button("●", self.toggle_password_visibility, x=280, y=100)
        self.controls["toggle_button"] = toggle_button

        self.create_button("登录", self.submit, x=50, y=150)
        self.create_button("退出", self.quit, x=200, y=150)

        progressbar = self.create_progressbar(x=50, y=200)
        self.create_button("开始进度", lambda: self.update_progress(progressbar), x=200, y=200)

        checkbox, var = self.create_checkbox("记住我", x=50, y=250)
        self.controls["remember_me"] = var

        gender_var = self.tk.StringVar()

        # 创建两个单选按钮,共享同一个变量
        radiobutton1, _ = self.create_radiobutton("男", x=50, y=300, value="male", var=gender_var)
        radiobutton2, _ = self.create_radiobutton("女", x=150, y=300, value="female", var=gender_var)
        self.controls["gender"] = gender_var

        # 下拉框
        self.create_label("单选择您的城市:", x=210, y=250)
        city_combobox = self.create_combobox(x=210, y=300, values=["北京", "上海", "广州", "深圳"], default_value="北京")
        self.controls["city"] = city_combobox


        listbox = self.create_listbox(x=50, y=350)
        for item in ["选项A", "选项B", "选项C"]:
            listbox.insert('end', item)
        self.controls["options"] = listbox


        self.create_label("多选您的兴趣:", x=210, y=350)
        multiselect, selected_values = self.create_multiselect_combobox(
            x=250, y=380, values=["音乐", "运动", "阅读", "旅行"], width=20
        )

        self.create_button(
            "提交兴趣", lambda: self.show_message("兴趣", f"选中兴趣: {selected_values.get()}", "info"), x=50, y=550
        )


        # 菜单
        self.create_menu({
            "文件": {"新建": lambda: self.show_message('提示', '新建文件', 'info'),
                     "退出": self.quit},
            "帮助": {"关于": lambda: self.show_message('关于', '这是一个示例应用', 'error')}
        })

    def submit(self):
        """提交按钮事件"""
        username = self.controls.get("username").get()
        password = self.controls.get("password").get()
        if username == "admin" and password == "admin":
            self.show_admin_page()
        else:
            self.show_message('错误', '账号或密码错误', 'error')

    def show_admin_page(self):
        """显示管理员页面"""
        self.root.destroy()  # 销毁当前窗口
        admin_app = Gui()
        admin_app.set_title("管理员页面")
        admin_app.set_geometry(400, 300)
        admin_app.create_label("欢迎进入管理员页面", x=50, y=50)
        admin_app.create_button("退出", admin_app.quit, x=50, y=150)
        admin_app.show()
    def show_admin_page(self):
        """展示管理员页面"""
        # 清空现有窗口
        for widget in self.root.winfo_children():
            widget.destroy()

        # 布局新的管理员页面
        self.create_label("欢迎进入管理员页面", x=100, y=50, font=('黑体', 20))
        self.create_button("退出", self.quit, x=150, y=150)

    def main(self):
        """主入口"""
        self.set_title("综合示例应用")
        self.set_geometry(500,700)
        self.set_bg_color("#f0f0f0")
        self.set_resizable(False, False)
        self.setup_ui()
        self.show()

if __name__ == '__main__':
    DemoApp().main()

运行效果

可以根据里面代码,进行定制化开发
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到