Python 图形用户界面开发
GUI:又称图形用户接口,是用户于计算机系统交互的界面,它通过图形方式显示信息。
常用的 Python GUI 库主要有 Tkinter、PyQt、PySide、wxPython、Kivy等。
创建窗口
调用 Tkinter 模块的 Tk() 函数可以创建一个窗口对象。
- 窗口标题的设置:
窗口对象.title(标题) - 窗口大小和位置的设置:
窗口对象.geometry(‘宽 x 高 + x坐标 + y坐标’)
常用控件
| 控件 | 名称 | 描述 | 控件 | 名称 | 描述 |
| Button | 按钮 | 在程序中显示按钮 | Menu | 菜单 | 显示菜单栏 |
| Canvas | 画布 | 提供绘制功能 | Message | 消息框 | 类似于标签,可以显示多行文本 |
| Checkbutton | 多选框 | 在程序中显示多选框 | Radiobutton | 单选按钮 | 显示单选按钮 |
| Combobox | 下拉框 | 显示下拉框 | Scale | 进度条 | 显示滑块控件 |
| Entry | 文本框 | 显示单行文本内容 | Scrollbar | 滚动条 | 显示滚动条 |
| Frame | 框架 | 用于放置其他窗口部件 | Text | 文本框 | 显示多行文本 |
| Label | 标签 | 显示文本或位图 | Messagebox | 消息框 | 弹出一个消息框 |
| Listbox | 列表框 | 显示选择列表 |
| 属性 / 参数 | 描述 |
| master | 父窗口指针 / 上级容器(如 Tk 类对象) |
| text | 控件标题(部分控件有 Button、Label……) |
| bd | 控件边框的大小,默认为 2 像素 |
| image | 控件上要显示的图片 |
| font | 字体、大小、粗细。例如,font = (‘行楷’ ,15 ,’bold’) |
| fg | 字体颜色 |
| bg | 背景颜色 |
| height | 高度,单位为像素 |
| width | 宽度 |
- 标签 Label:
- 语法:
Label(master ,** options)- master:用于指定本控件的父窗口对象
- options:是对 Label 控件的各种属性配置选项(包括文本、字体、颜色、对齐方式等)
- 语法:
| 属性选项 | 说明 | 属性选项 | 说明 |
| text | 文字内容,可以多行,用 \n 分隔 | anchor | 文本在控件中的位置,默认居中 |
| height | 文字行数(注意:不是像素) | font | 指定文本的字体字号 |
| width | 文字字符个数(注意:不是像素) | image | 标签控件中显示的图像 |
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
label1 = tkinter,Label(win,text = '资源刺客(wp.itdka.cn)')
photo = tkinter.PhotoImage(file = 'demo.jpg')
label2 = tkinter.Label(win ,image = photo)
label2.pack()
win.mainloop()
- 按钮 Button:
- 语法:
Button(master ,** options)参数用法同 Label 控件
- 语法:
| 属性选项 | 说明 |
| text | 设置按钮上的文字 |
| height | 设置按钮的高度,用文本的字符行数表示 |
| width | 设置按钮的宽度,用文本的字符个数表示 |
| takefocus | 设置焦点 |
| state | 设置按钮的状态:normal(正常)、active(激活)、disabled(禁用) |
| bg | 设置背景颜色 |
| fg | 设置前景颜色 |
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
def show():
label = thinter.Label(win ,text = '你好!')
btn = tkinter.Button(win ,text = '资源刺客(wp.itdka.cn)' ,command = show)
btn.pack()
win.mainloop()
- 单行文本框 Entry:
- 语法:
Entry(master ,** options)参数用法同 Label 控件
- 语法:
| 属性选项 | 说明 |
| font | 文字字体,值是元组,font = (‘字体’ ,’字号’ ,’粗细’) |
| foreground | 文字颜色 |
| show | 指定文本框内容显示为掩码,如密码设置为 * :show = '*' |
| state | 文本框状态,分为只读和可写,值为:disabled / normal |
| textvariable | 文本框的值为 stringVar() 对象 |
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
t1 = tkinter.StringVar()
t1.set('请输入密码:')
e1 = tkinter.Entry(win ,textvariable = t1 ,show = '*')
e1.pack()
def show():
print('密码为:',t.get())
btn = tkinter.Button(win ,text = '资源刺客(wp.itdka.cn)' ,command = show)
btn.pack()
win.mainloop()
- 滚动文本框 ScrolledText:
- 语法:
scrolledtext.ScrolledText(master , ** options)参数用法同 Label 控件
- 语法:
| 属性 / 方法名称 | 说明 |
| width | 文本框的宽度 |
| height | 文本框的高度 |
| scrollbar | 文本框的滚动条 |
| get(‘1.0’ ,tk.END) | 获取文本框中从第一行第一列到最后一行最后一列的内容 |
| insert(tk.INSERT ,’text’) | 将文本插入文本框的当前光标位置 |
| delete(‘1.0’ ,tk.END) | 删除文本框中从第一行第一列到最后一行最后一列的内容 |
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
t1 = tkinter.StringVar()
t1.set('请输入密码:')
src = tkinter.scrolledtext。ScrolledText(win ,width = 20 ,height = 10)
src = insert(0 ,0,'评论内容:')
src.pack()
def show():
text = src.get('1.0' ,tkinter.END)
tkinter.Label(win ,text = text + '已提交!').pack()
btn = tkinter.Button(win ,text = '资源刺客(wp.itdka.cn)' ,command = show)
btn.pack()
win.mainloop()
布局管理方式
Python 定义了三种界面布局管理方式,分别是顺序布局、绝对布局与网格布局
- 顺序布局:
- 一般使用
pack()函数来实现。 - 语法格式:
控件对象.pack(side ,fill ,expand ,anchor ,** options)- side:指定控件相对于其容器的位置(值:top(默认)、bottom、left、right)
- fill:指定控件如何填充其在容器中的空间。(值:x、y、both、None(默认,表不填充其空间))
- expand:一个布尔值,指定控件是否应该在容器控件扩大时增长(只有 fill 设置为 both 时才有效,默认值为 False)
- anchor:指定控件在填充其空间时的对齐方式(值:n、s、e、w、ne、nw、se、sw、None(默认值,表居中对齐))
- options:用于设置其他 pack() 方法的可选属性
- 一般使用
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
labelx = tkinter.Label(win ,text = 'L1' ,bg = 'red')
labely = tkinter.Label(win ,text = 'L2' ,bg = 'red')
labelz = tkinter.Label(win ,text = 'L3' ,bg = 'red')
labela = tkinter.Label(win ,text = 'L4' ,bg = 'red')
laxbelx.pack(side = 'left' ,fill = 'y')
laxbely.pack(side = 'right' ,fill = 'both')
laxbelz.pack(side = 'bottom' ,fill = x')
laxbela.pack(side = 'top' ,fill = 'x')
win.mainloop()
- 绝对布局:
- 一般通过空间调用
place()函数来实现。 - 语法格式:
控件对象.place(x ,y ,width ,height ,relwidth ,relheight ,anchor)- x:表示 x 方向的坐标
- y:表示 y 方向的坐标
- width:指控件的宽度,以像素为单位(设置了
relwidth,则 width 是一个相对于父容器宽度的比例) - height:指控件的高度,以像素为单位(设置了
relheight,则 height 是一个相对于父容器高度的比例) - relwidth:一个布尔值,指宽度是否应该相对于父容器的大小进行缩放(True:进行缩放;反之)
- relheight:一个布尔值,指高度是否应该相对于父容器的大小进行缩放(True:进行缩放,反之)
- anchor:指控件在给定位置时的对齐方式,其取值与顺序布局中的
anchor参数一致,默认居中。
- 一般通过空间调用
import tkinter
win = tkintwe.Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
labelx = tkinter.Label(win ,text = 'L1' ,bg = 'red')
labely = tkinter.Label(win ,text = 'L2' ,bg = 'red')
labelz = tkinter.Label(win ,text = 'L3' ,bg = 'red')
labela = tkinter.Label(win ,text = 'L4' ,bg = 'red')
laxbelx.place(x = 50 ,y = 10)
laxbely.place(x = 20 ,y = 10)
laxbelz.place(x = 10 ,y = 10)
laxbela.place(x = 60 ,y = 10)
win.mainloop()
- 网格布局:
- 一般通过控件调用
grid()函数实现。 - 语法格式:
控件对象.grid(row ,column ,sticky ,columnspan ,rowspan ,padx ,pady)- row:指定 Widget 在网格中的行号
- column:指定 Widget 在网格中的列号
- sticky:指定 Widget 应如何适应其网格单元格的大小(值:n、s、e、w、ne、nw、se、sw)
- columnspan:指定 Widget 应跨越的列数
- rowspan:指定 Widget 应跨越的行数
- padx:指定 Widget 内部左右填充( x 方向)
- pady:指定 Widget 内部上下填充( y 方向)
- 一般通过控件调用
label.grid(row = 0 ,column = 0)
entry.grid(row = 0 ,coloumn = 1 ,columnspan = 3)
其他控件
- Frame 控件:
- 介绍:可以看作时一个矩形区域,它可以包含其他 GUI 控件,并允许用户对这些控件进行布局和控制,多个 Frame 可以实现界面的分割。
| 属性选项 | 说明 |
| background / bg | 设置 Frame 控件的背景颜色 |
| borderwidth / bd | 指定 Frame 的边框宽度,默认值为 2 像素 |
| colormap | 指定用于该控件及其子控件的颜色映射,默认情况下,Frame使用与其父控件相同颜色的映射。 |
| container | True:意味着该窗口将被用作容器,一些其他应用程序将被嵌入(默认值为 False ) |
| width | 设置 Frame 的宽度,默认值为 0 |
| highlightbackground | 指定当前 Frame 没有获得焦点时高亮边框的颜色,默认值由系统指定 |
| highlightcolor | 指定当 Frame 获得焦点时高亮边框的颜色,默认值由系统指定 |
| highlightthickness | 指定高亮边框的宽度,默认值为 0(不带高亮边框) |
| padx | 水平方向上的边距 |
| pady | 垂直方向上的边距 |
| relief | 指定边框样式(值: flat(默认值)、sunken、raised、groove、ridge) |
| takefocus | 指定该控件是否接受输入焦点(用户通过 Tab 键将焦点转移上来),默认值为 False |
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
frame1 = Frame(win ,bg = 'yellow' ,width = 100 ,height = 150)
frame1.pack(fill = 'both' ,expand = True)
Label(frame1 ,text = '我是文本1').pack()
win.mainloop()
- 单选按钮与复选框
注意 :在创建单选按钮 Radiobutton 或 Checkbutton 时,要先声明一个选择状态变量。如chVarDis = tk.IntVar(),该变量记录单选按钮或复选框是否被勾选的状态。
| 属性 / 方法 | 说明 |
| command | 用户选择改变按钮状态,调用相应的方法 |
| text | 按钮上的文字内容 |
| variable | 控件状态变量(值:1 => 被选中;0 => 没有被选中) |
| onvalue | 状态变量值为 1 |
| offvalue | 状态变量值为 0 |
| state | 是否可选,当 state = ‘disabled’ 时,该选项为灰色,不能选择 |
| deselect() | 取消按钮的选中状态 |
| flash() | 刷新 Radiobutton 控件,该方法将重绘 Radiobutton 控件若干次(即在 active 和 normal 状态间切换) |
| select() | 将 Radiobutton 控件设置为选中状态 |
from tkinter import *
class Application(Frame):
num = 0
mark = "ABCDEFG"
def __init__(self ,master ,tit ,opts ,txt = None ,radVar = None):
super().__init__(master)
Application.num ++
self.master = master
self.tit = tit
self.txt = StringVar()
self.radVar = IntVar()
self.opts = opts
self.grid(row = self.num)
self.createWidget()
def radCall(self):
self.txt.set(self.mark[self.radVar.get()])
def createWidget(self):
Label(self ,text = '{}.{30}'.format(self.num ,self.tit) ,font = {'宋体' ,'16'} ,fg = 'red').grid(row = 0 ,column = 0 ,columnspan = 4 ,sticky = NW)
self.txt.set('答案:')
ans = entry(self ,textvariable = self.txt ,width = 15 ,font = ('宋体' , '16')).grid(row = 0 ,coloumn = 4 ,columnspan = 2)
for col in range(len(self.opts)):
curRad = Radiobutton(self ,text = f'self.mark[col]、self.opts[col]' ,variable = self.radVar ,value = col ,command = self.radCall).grid(column = 0 ,row = col + 1 ,sticky = W)
if __name__ == "__main__":
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
Application(win ,f'题目是什么?' ,['网络','程序' ,'游戏' ,'音乐'])
win.mainloop()
- 下拉列表:
注意 :使用下拉列表时要先声明一个取值变量:number = tkinter.StringVar()。该变量记录在下拉列表中预设的值中所选的字符值,在下拉列表中所预设的值为一个元组。
| 参数 | 含义 |
| textvariable | 可以设置 Combobox 的变量值 |
| value | Combobox 的选项内容以元组方式存在 |
| postcommand | 设置下拉选项改变时所调用的函数 |
from tkinter import *
from tkinter import ttk
class Application(Frame):
def __init__(self ,master ,value ,result = None):
super().__init__(master)
Application.num ++
self.master = master
self.value = value
self.result = StringVar()
self.grid(row = 0)
self.createWidget()
def radCall(self):
self.txt.set(self.mark[self.radVar.get()])
def createWidget(self):
Label(self ,text = '二级学院').grid(row = 0 ,column = 0)
cb = ttk.Combobox(self ,value = self.value ,textvariable = self.result ,postcommand = self.getResult)
cb.grid(row = 0 ,column = 1)
def getResult():
print(self.result.get())
if __name__ == "__main__":
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
Application(win ,('网络','程序' ,'游戏' ,'音乐'))
win.mainloop()
- 列表框:
注意 :- 直接创建的 Listbox 控件是空的,若添加文本可以调用
insert(index ,str)函数- index:插入的索引号,通常是项目的序号,从 0 开始
- str:要插入的文本
- 若要删除某一行数据,则需要调用
curselection()函数获取被选中的行号,然后再调用delete()函数删除即可。
- 直接创建的 Listbox 控件是空的,若添加文本可以调用
| 方法 | 说明 |
| activate(index) | 用于选择指定索引处的行 |
| curselection() | 返回一个元组,其中包含所选元素的行号,从 0 开始技术。如果未选择任何元素,则返回一个空元组 |
| delete(first , last = None) | 用于删除给定范围内的行 |
| get(first , last = None) | 用于获取给定范围内存在的列表项 |
| index(i) | 用于将具有指定索引的行放在窗口小部件的顶部 |
| insert(index , * elements) | 用于在指定的索引之前插入具有指定数量元素的新行 |
| nearest(y) | 返回列表框小部件的 y 坐标的最近一行的索引 |
| see(index) | 用于调整列表框的位置,使索引指定的行可见 |
| size() | 返回 Listbox 小部件中存在的行数 |
| xview() / yview | 用于使小部件可 水平 / 垂直滚动 |
| xview_moveto(fraction) / yview_moveti(fraction) | 用于使列表框可以按列表框中存在的最长行的宽度的一小部分水平、垂直滚动 |
| xview_scroll(number , what) / yview_scroll(number , what) | 用于使列表框可以按指定的字符数水平 / 垂直滚动 |
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
num = 1
Button(win ,text = '添加一条记录' ,command = addInfo).pack()
Button(win ,text = '删除一条记录' ,command = deleteInfo).pack()
lb = Listbox(win ,width = 100 ,height = 100)
lb.pack()
def addInfo():
global num
info = '第{}条记录'.format(num)
lb.insert(0 ,info)
num++
def deleteInfo():
global lb
selected = lb.curselection()
if selected:
lb.delete(selected[0])
else:
print('不存在!')
win.mainloop()
菜单
- 实现步骤:
- 创建菜单对象:
Tkinter.Menu(窗口对象) - 把菜单防止到窗口中:
窗口容器对象.config(menu = 菜单对象) - 在菜单栏中创建菜单:
菜单名称 = Menu(菜单对象 ,teaoff = 0) - 为菜单添加文字标签:
菜单对象.addcascade(label = '文字标签' , menu = 菜单名称) - 在菜单中添加菜单项:
add_command(label = '菜单项名称' ,command = 功能函数名)
- 创建菜单对象:
消息框与对话框
消息框是一种程序向用户显示信息的方式。
Tkinter 的 Messagebox模块提供了多种消息框,主要分为无返回值的消息框和有返回值的消息框。
| 消息框名称 | 函数 |
| 提示框 | showinfo() |
| 警告框 | showwarning() |
| 错误框 | showerror() |
| 消息框名称 | 函数 |
| 是 / 否 对话框 | askquestion() |
| 重试 / 取消 对话框 | askretrycancel() |
| 是 / 否 / 取消 对话框 | askyesnocamcel() |
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
def getans():
ans = askquestion('询问框' ,'是否确定?')
if ans == 'yes':
print('确定')
else:
print('取消')
# ...
win.mainloop()
对话框用以接收用户的简单输入对话框,并返回用户的输入内容,位于 Tkinter 的 Simpledialog 包中。
| 方法 | 说明 |
| askstring() | 接收字符串 |
| askinteger() | 接收字符串、整数 |
| askfloat() | 接收浮点数 |
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
def getans():
ans = askstring('解锁' ,'密码?')
if ans == '111':
print('确定')
else:
print('取消')
# ...
win.mainloop()
文件对话框:当需要手动选择文件或手动选择文件存储路径时,就需要用到 Tkinter 库中 Filedialog 模块中所提供的函数。
| 方法 | 说明 |
| askopenfilename() | 打开文件对话框,用于选择一个文件,返回文件路径,类型为字符串 |
| askopenfilenames() | 打开文件对话框,用于选择多个文件,返回一个元组,包括所有选择文件的路径 |
| asksavesfilename() | 保存文件对话框,用于选择文件的保存路径和文件名 |
| askdirectory() | 选择目录对话框,用于选择一个目录,返回目录路径 |
函数参数扩展:
- title:指定文件对话框的标题栏文本
- defaultextension:指定文件的后缀。例如:defaultextension = ‘.jpg’,允许使用 * 通配符。
- filetypes:指定筛选文件类型的下拉菜单选项,该选项的值时由二元组构成的列表,每个二元组由(类型名,后缀)构成。例如:filetypes = [(‘文本’ , ‘.txt’) , (‘栅格’ , ‘.tif’)]
- initialdir:指定打开保存文件的默认路径,默认路径是当前文件夹
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
def getans():
filename = askopenfilename()
print(filename)
# ...
win.mainloop()
颜色选择对话框:在文本编辑器应用程序中,为了让用户能够设置文本颜色或背景色的颜色,通常会使用颜色对话框。
from tkinter import *
win = Tk()
win.title('资源刺客(wp.itdka.cn)')
win.geometry('300 X 300 + 50 + 50')
def getans():
color = askcolor()
print(color)
# ...
win.mainloop()
鼠标事件与键盘事件
控件对象.bind(event , handle):监听和处理鼠标事件,如单击、双击、拖动和鼠标移动等。- event:是一个字符串,表示要绑定的事件类型(如下表)
- handle:是一个函数,即当事件发生时将被调用的函数,这个函数通常会接收一个参数,即事件对象 event。
| 事件 | 说明 |
| <ButtonPress – n> | 鼠标按钮 n 被按下,n 为1 代表左键,2 代表中键,3 代表右键 |
| <ButtonRelease – n> | 鼠标按钮 n 被松开 |
| <Bn-Motion> | 再按住鼠标按钮 n 的同时,移动鼠标 |
| <Enter> | 鼠标进入控件 |
| <Leave> | 鼠标离开控件 |
| 事件 | 说明 |
| <KeyPress> | 按下任意键 |
| <KeyRelease> | 松开任意键 |
| <KeyPress-Key> | 按下指定的 key 键 |
| <KeyRelease-Key> | 松开指定的 key 键 |
| <Prefix-Key> | 在按住 Prefix 的同时,按下指定的 key 键。其中 Prefix 项时 Alt、Shfit、Control 中的一项,也可以是他们的组合,如 <Control-Alt-Key> |
from tkinter import *
class Application(Frame):
def __init__(self ,master ,bg = 'red'):
super().__init__(master)
self.master = master
self.bg = bg
self.config(bg = self.bg ,width = 50 ,height = 50)
self.pack()
self.bind('<Button-1>',self.getPos)
self.bind('<Enter>',self.inFrame)
self.bind('<Leave>',self.outFrame)
self.bind('<Control - s>',lambda event:print('保存'))
# ...
win.mainloop()
数据库编程
程序运行过程中产生的数据,通常都是临时保存在缓存或者存储在文件中,但是如果数据比较复杂,使用存储在文件中的数据时需要对数据进行格式化操作,非常不便。如果要永久保存数据,且方便后期对数据进行查询、删除、更新等操作,通常需要将数据保存在数据库中。
操作步骤:
- 连接数据库:
connect()- connect() 函数返回数据库连接对象,该对象代表与对应数据库建立了连接。
| 参数名 / 方法名 | 说明 | 参数名 / 方法名 | 说明 |
| dsn | 数据源名称 | password | 密码 |
| host | 主机名 | db | 数据库名称 |
| port | 端口号 | charset | 数据库字符集 |
| user | 用户名 | ||
| cursor() | 获取该连接的游标对象,执行数据库 | roolback() | 回滚事务 |
| commit() | 提交事务 | close() | 关闭数据库连接 |
- 创建游标对象:
数据库连接对象.cursor()- 要操作数据库,仅创建连接对象是不够的,必须获取游标对象才能进行后续操作。
| 方法名 | 说明 |
| excute(sql [,params]) | 执行数据库操作的 SQL 语句 |
| excutemany(sql ,seq_of_params) | 用于批量数据操作,批量添加数据 |
| fetchone() | 用于获取查询结果的下一跳数据 |
| fetchall() | 用于获取查询结果的所有数据 |
| fetchmany() | 用于获取查询结果中指定数量的数据 |
- 执行 SQL 语句
- 获得游标对象后,就可以使用上表的相应方法进行数据库的各种操作。
- 关闭游标与数据库连接
游标对象.close()连接对象.close()
SQLite 数据库编程
介绍:SQLite 是一种嵌入式的轻量级数据库,它不需要另外的安装,直接集成在各种应用程序中。
使用:首先需要使用 import 语句导入 SQLite 3 模块,然后即可使用该模块中的 connect() 方法连接数据库文件并得到连接对象
import sqlite3
conn = sqlite3.connect('text.db')
MySQL 数据库编程
介绍:MySQL 是一个小型关系型数据库管理系统,由于其软件体积小、运行速度快、操作方便等优点,目前被广泛应用于 Web 上的中小型网站的后台数据库中。
使用:在 Python 3 中使用 PyMySQL 库来实现对 MySQL 的连接,在此之前需要操作的电脑已经安装了 MySQL 数据库。PyMySQL 库是一个纯 Python 库,可以直接安装使用(使用下面的安装命令)
pip intsall pymysql
导入 PyMySQL 模块就可以使用该模块下的 connect() 方法连接指定的数据。
例如:
import pymysql
conn = pymysql.connect(host = '127.0.0.1' ,port = 3306 ,user = 'root' ,password = '123456' ,db = 'test1' ,charset = 'utf8')
![[学习笔记 Day03]Python基础:从命令行,到数据可视化的界面-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250923154612655.png)

![[学习笔记 Day01]C++基础:简单的程序设计,始于梦想的开始!-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250922171813209.webp)
![[学习笔记 Day02]Vue基础:前端造梦,继续干!-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250919193418264.jpeg)


![[Dotnet-ef 工具] ORM 工具生成实体模型步骤及常见问题!-资源刺客](https://images.kodo.cdn.itdka.cn/wp-contents/uploads/2026/03/20260326200207417-818064be8e4c5751f8ce12720bbecbfb.jpeg)

![[最新]使用 OpenWrt 系统实现校园网 + 某为5G通信壳网络分流-资源刺客](https://images.kodo.cdn.itdka.cn/wp-contents/uploads/2026/03/20260303220540153-openwrt.png)

![[自动化 + 手残党专属]宝塔安装AllinSSL证书管理教程-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/11/20251112122722716.png)



暂无评论内容