觉得tkinter界面不好看?Extkinter带你制作进阶版窗口(ExButton篇)

本文介绍了如何使用自定义的ExButton组件来美化Tkinter应用程序的界面,展示了ExButton的多种样式和功能,包括按钮的颜色、字体颜色、高亮效果等,并提供了详细的使用示例和源代码。ExButton不仅支持基本的点击事件,还支持按钮组的高亮显示,使得界面交互更加友好。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用了tkinter很长时间了,一直都是觉得tkinter功能挺到位,但就是不够美观,所以就有了这个窗口美化计划(我管它叫Extkinter),这篇文章介绍一下它的第一个组件:按钮(ExButton)

运行效果

先上图,看看使用ExButton做出来界面的实际运行效果

这里只是一个使用示例,按钮可以点,但没有实际作用(本来想录制一个gif动图的但ps一直抽风)

使用方法

先放出上面运行效果界面的代码

from Extkinter import *
import tkinter.ttk as ttk


class Main(Tk):
    def __init__(self):
        super().__init__()
        self.top_frame = None
        self.button_frame_1 = None
        self.button_frame_2 = None
        self.main_frame_1 = None
        self.main_frame_2 = None
        self.top_button_arr = []
        self.left_button_arr = []
        self.main_button_arr = []
        self.initialize()
        self.frame_initialize()
        self.interface_initialize()

    def initialize(self):
        self.title("数据管理系统")
        self.geometry("1000x620+%d+%d" % (self.winfo_screenwidth() / 2 - 500,
                                          self.winfo_screenheight() / 2 - 390))
        self.resizable(False, False)

    def frame_initialize(self):
        self.top_frame = Canvas(self, bg="black", height=60, width=1000, highlightthickness=0)
        self.top_frame.place(x=0, y=0)
        self.button_frame_1 = Canvas(self, bg="White", height=255, width=180, highlightthickness=0)
        self.button_frame_1.place(x=30, y=90)
        self.button_frame_2 = Canvas(self, bg="White", height=215, width=180, highlightthickness=0)
        self.button_frame_2.place(x=30, y=375)
        self.main_frame_1 = Canvas(self, bg="White", height=55, width=730, highlightthickness=0)
        self.main_frame_1.place(x=240, y=90)
        self.main_frame_2 = Canvas(self, bg="White", height=440, width=730, highlightthickness=0)
        self.main_frame_2.place(x=240, y=150)

    def interface_initialize(self):
        # 布置顶层界面
        Label(self.top_frame, text="数据管理系统", bg="black", fg="white", font=("华文细黑", 18)).place(x=30, y=13)
        top_button_1 = ExButton(self.top_frame, height=60, width=130, text="首页", font=("华文细黑", 15),
                                style="vertical_color", command=self.pass_command)
        top_button_1.set(button_list=self.top_button_arr, font_color=("White", "White"), color=("Black", "Black"),
                         active_color=("DeepSkyBlue", "Black"))
        top_button_1.place(x=300, y=0)
        top_button_2 = ExButton(self.top_frame, height=60, width=130, text="产品购买", font=("华文细黑", 15),
                                style="vertical_color", command=self.pass_command)
        top_button_2.set(button_list=self.top_button_arr, font_color=("White", "White"), color=("Black", "Black"),
                         active_color=("DeepSkyBlue", "Black"))
        top_button_2.place(x=430, y=0)
        top_button_3 = ExButton(self.top_frame, height=60, width=130, text="关于我们", font=("华文细黑", 15),
                                style="vertical_color", command=self.pass_command)
        top_button_3.set(button_list=self.top_button_arr, font_color=("White", "White"), color=("Black", "Black"),
                         active_color=("DeepSkyBlue", "Black"))
        top_button_3.place(x=560, y=0)
        top_button_4 = ExButton(self.top_frame, height=60, width=120, text="登录", font=("华文细黑", 12),
                                command=self.pass_command)
        top_button_4.set(font_color=("White", "White"), color=("Black", "Black"))
        top_button_4.place(x=880, y=0)

        # 布置按钮界面
        Label(self.button_frame_1, text="数据库", bg="white", font=("微软雅黑", 16)).place(x=30, y=10)
        left_button = ExButton(self.button_frame_1, height=40, width=180, text="数据中心", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=55)
        left_button = ExButton(self.button_frame_1, height=40, width=180, text="创建数据", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=95)
        left_button = ExButton(self.button_frame_1, height=40, width=180, text="导入数据", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=135)
        left_button = ExButton(self.button_frame_1, height=40, width=180, text="导出数据", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=175)
        left_button = ExButton(self.button_frame_1, height=40, width=180, text="设置", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=215)

        # 布置第二层按钮界面
        Label(self.button_frame_2, text="个人中心", bg="white", font=("微软雅黑", 16)).place(x=30, y=10)
        left_button = ExButton(self.button_frame_2, height=40, width=180, text="账号管理", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=55)
        left_button = ExButton(self.button_frame_2, height=40, width=180, text="我的收藏", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=95)
        left_button = ExButton(self.button_frame_2, height=40, width=180, text="我的数据", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=135)
        left_button = ExButton(self.button_frame_2, height=40, width=180, text="购买记录", font=("微软雅黑", 11),
                               command=self.pass_command)
        left_button.set(button_list=self.left_button_arr, color=("White", "White"),
                        active_color=("DeepSkyBlue", "#F0F0F0"))
        left_button.place(x=0, y=175)

        # 布置页眉
        Label(self.main_frame_1, text="数据中心", bg="White", font=("幼圆", 15)).place(x=30, y=13)
        seek_button = ExButton(self.main_frame_1, text="搜索", height=20, width=50, command=self.pass_command,
                               font=("幼圆", 12))
        seek_button.place(x=650, y=18)
        seek_entry = ttk.Entry(self.main_frame_1)
        seek_entry.place(x=480, y=18)

        # 布置主界面内容
        main_button = ExButton(self.main_frame_2, text="推荐", height=35, width=70, command=self.pass_command,
                               font=("华文细黑", 11), style="vertical_color")
        main_button.set(button_list=self.main_button_arr, active_color=("#F0F0F0", "#F0F0F0"))
        main_button.place(x=0, y=0)
        main_button = ExButton(self.main_frame_2, text="热点", height=35, width=70, command=self.pass_command,
                               font=("华文细黑", 11), style="vertical_color")
        main_button.set(button_list=self.main_button_arr, active_color=("#F0F0F0", "#F0F0F0"))
        main_button.place(x=70, y=0)
        main_button = ExButton(self.main_frame_2, text="社区", height=35, width=70, command=self.pass_command,
                               font=("华文细黑", 11), style="vertical_color")
        main_button.set(button_list=self.main_button_arr, active_color=("#F0F0F0", "#F0F0F0"))
        main_button.place(x=140, y=0)
        Label(self.main_frame_2, text="Python数据爬取\t\t2021-8-8", bg="White", font=("华文细黑", 13)).place(x=25, y=50)
        Label(self.main_frame_2, text="班级成绩数据分析\t\t2021-8-9", bg="White", font=("华文细黑", 13)).place(x=25, y=85)
        Label(self.main_frame_2, text="股票走势数据\t\t2021-8-10", bg="White", font=("华文细黑", 13)).place(x=25, y=120)
        Label(self.main_frame_2, text="硬件价格走势\t\t2021-8-10", bg="White", font=("华文细黑", 13)).place(x=25, y=155)

    def pass_command(self):
        pass


if __name__ == "__main__":
    run = Main()
    run.mainloop()

基础功能介绍:

def __init__(self, master, command, height=0, width=0, text="", font="宋体", style="horizontal_color")

ExButton的构造函数有以下属性:
1.master为按钮所放置的父物体
2.command为执行的函数(正常的tkinter按钮不一定要绑定函数,但这里必须要,目前还没找到解决方法)
3.height,width为按钮的长度、宽度(像素)
4.text为按钮的文本
5.font为按钮的字体与大小,传入参数为(“字体名字”, 字体大小),和tkinter组件一样
6.style为按钮的样式,如果为"horizontal_color",那么按钮为左右颜色样式(参考运行图片中左边的那一排按钮),如果为"vertical_color",那么按钮为上下颜色样式(参考运行图片中上面的那一排按钮)

set函数介绍:

def set(self, button_list=None, font_color=("#000000", "#000000"), color=("#FFFFFF", "#FFFFFF"),
            active_color=("#FFD1FC", "#F0F0F0"))

在创建完ExButton后,可以使用set函数对其进一步地修改
set参数介绍:
1.button_list
button_list为按钮组功能,需要预先创建一个空列表,再将其传入ExButton set函数中的button_list,这样一来ExButton就被装进了那个列表,一个列表里所有的ExButton只能有一个是被选中状态。根据运行图片,左边的那一排按钮都被装进了left_button_arr,故只会有一个按钮是亮的,上面那一排黑蓝色的按钮被装进了top_button_arr,故上面也只亮一个按钮,两边不会互相影响。如果按钮没被装进任何列表,那么它被点击就不会有高亮显示,但依然能执行函数。(ps.默认界面创建出来时会先高亮列表第一个ExButton)
2.font_color
传入font_color里的两个字符串分别对应按钮未点击、被点击时的字体颜色
3.color与active_color
若style为"horizontal_color",那么传入color和active_color里的两个字符串分别对应按钮未被按下时和按下时的左、右两个颜色。若style为"vertical_color"那么传入color和active_color里的两个字符串分别对应按钮未被按下时和按下时的上、下两个颜色。

ExButton继承了tkinter Canvas,所以ExButton也能使用pack,place,grid的布局方式。

源代码

这里放一下ExButton的源代码,目前只是初代版本,以后会慢慢更新和优化,如果使用过程中有什么bug或不好用的地方欢迎私信,期待大家的支持!!

"""
version:1.1
作者:椎名mikan
"""
from tkinter import *


class ExButton(Canvas):
    def __init__(self, master, command, height=0, width=0, text="", font="宋体", style="horizontal_color"):
        super().__init__(master, height=height, width=width, highlightthickness=0, cursor="hand2")
        self.height = height
        self.width = width
        self.text = text
        self.font = font
        self.command = command
        self.style = style
        self.click_effect = False
        self.button_list = None
        self.color_1 = None
        self.color_2 = None
        self.active_color_1 = None
        self.active_color_2 = None
        self.font_color = None
        self.active_font_color = None
        self.bind("<Button-1>", self.callback)
        self.set()

    def set(self, button_list=None, font_color=("#000000", "#000000"), color=("#FFFFFF", "#FFFFFF"),
            active_color=("#FFD1FC", "#F0F0F0")):
        self.font_color = font_color[0]
        self.active_font_color = font_color[1]
        self.button_list = button_list
        self.color_1 = color[0]
        self.color_2 = color[1]
        self.active_color_1 = active_color[0]
        self.active_color_2 = active_color[1]
        if self.button_list is not None:
            self.button_list.append(self)
            self.button_list[0].click_effect = True
        self.paint()

    def callback(self, event):
        if event:
            pass
        self.command()
        if self.button_list is not None:
            self.set_active()
            self.paint()

    def set_active(self):
        for i in range(0, len(self.button_list)):
            self.button_list[i].click_effect = False
        self.click_effect = True

    def paint(self):
        if self.button_list is not None:
            for i in range(0, len(self.button_list)):
                if self.button_list[i].style == "horizontal_color":
                    if self.button_list[i].click_effect is True:
                        self.button_list[i].create_rectangle(0, 0, 7, self.button_list[i].height,
                                                             fill=self.button_list[i].active_color_1, outline="")
                        self.button_list[i].create_rectangle(7, 0, self.button_list[i].width,
                                                             self.button_list[i].height,
                                                             fill=self.button_list[i].active_color_2, outline="")
                        self.button_list[i].create_text(self.button_list[i].width / 2, self.button_list[i].height / 2,
                                                        text=self.button_list[i].text, font=self.button_list[i].font,
                                                        fill=self.button_list[i].active_font_color)
                    else:
                        self.button_list[i].create_rectangle(0, 0, 7, self.button_list[i].height,
                                                             fill=self.button_list[i].color_1, outline="")
                        self.button_list[i].create_rectangle(7, 0, self.button_list[i].width,
                                                             self.button_list[i].height,
                                                             fill=self.button_list[i].color_2, outline="")
                        self.button_list[i].create_text(self.button_list[i].width / 2, self.button_list[i].height / 2,
                                                        text=self.button_list[i].text, font=self.button_list[i].font,
                                                        fill=self.button_list[i].font_color)
                elif self.button_list[i].style == "vertical_color":
                    if self.button_list[i].click_effect is True:
                        self.button_list[i].create_rectangle(0, 0, self.button_list[i].width, 5,
                                                             fill=self.button_list[i].active_color_1, outline="")
                        self.button_list[i].create_rectangle(0, 5, self.button_list[i].width,
                                                             self.button_list[i].height,
                                                             fill=self.button_list[i].active_color_2, outline="")
                        self.button_list[i].create_text(self.button_list[i].width / 2, self.button_list[i].height / 2,
                                                        text=self.button_list[i].text, font=self.button_list[i].font,
                                                        fill=self.button_list[i].active_font_color)
                    else:
                        self.button_list[i].create_rectangle(0, 0, self.button_list[i].width, 5,
                                                             fill=self.button_list[i].color_1, outline="")
                        self.button_list[i].create_rectangle(0, 5, self.button_list[i].width,
                                                             self.button_list[i].height,
                                                             fill=self.button_list[i].color_2, outline="")
                        self.button_list[i].create_text(self.button_list[i].width / 2, self.button_list[i].height / 2,
                                                        text=self.button_list[i].text, font=self.button_list[i].font,
                                                        fill=self.button_list[i].font_color)
        else:
            self.create_rectangle(0, 0, 8, self.height, fill=self.color_1, outline="")
            self.create_rectangle(8, 0, self.width, self.height, fill=self.color_2, outline="")
            self.create_text(self.width / 2, self.height / 2, text=self.text, font=self.font, fill=self.font_color)

在使用Pythontkinter库开发图形用户界面时,如果界面出现卡死的情况,通常是因为主线程中的某个任务运行时间过长,阻塞了tkinter的主事件循环。为了解决这个问题,可以采取以下几种方法: 参考资源链接:[解决Python tkinter界面卡死问题及高频信号知识点总结](https://wenku.csdn.net/doc/5zi62a7mqf?spm=1055.2569.3001.10343) 1. 多线程或多进程处理:通过将耗时的操作放在一个新的线程或进程中执行,可以避免阻塞主事件循环。但是,由于tkinter的GUI更新必须在主线程中完成,所以需要使用线程安全的方式来更新GUI,例如使用`queue.Queue`进行线程间通信。 2. 使用`after()`方法:通过定时器函数`after()`来将长时间的任务分批处理,这样可以让tkinter有机会在批次之间处理其他事件,防止界面卡死。例如,可以将大任务拆分成小块,每处理一小块后调用`after()`来安排下一次执行,直到所有任务完成。 3. 合理使用`update_idletasks()`和`update()`:这两个函数可以帮助tkinter处理未完成的任务和事件。在执行可能会影响GUI响应的任务之前和之后调用它们,可以确保GUI能够及时更新和响应用户操作。 4. 避免无限循环:在代码中要确保循环结构有退出条件,避免无意中创建了无限循环,这会完全停止主事件循环的运行。 通过上述方法,可以有效地解决tkinter界面卡死的问题。具体到你的情况,可以参考《解决Python tkinter界面卡死问题及高频信号知识点总结》这一资源,它仅涵盖了GUI开发中常见的界面卡死问题,还结合了高频信号处理的知识点,为你提供了一个全面的学习视角。 参考资源链接:[解决Python tkinter界面卡死问题及高频信号知识点总结](https://wenku.csdn.net/doc/5zi62a7mqf?spm=1055.2569.3001.10343)
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值