好友
阅读权限35
听众
最后登录1970-1-1
|
本帖最后由 jumpbull 于 2024-11-1 20:33 编辑
6、单选框(Radiobutton、QRadioButton)
PyQt5 在单选框上的使用就没 tkinter 方便,我先列个对比表,再给代码
类型 | tkinter | PyQt5 | 分组 | 使用 tkinter.IntVar() 变更绑定即可分组 | 需要用 QButtonGroup() 按钮分组对象,再将单选框逐个绑定,代码量多,还好能使用 QtDesigner 在设计时能分组 | 判断选项 | 直接通过绑定的 tkinter.IntVar() 的值进行判断,非常方便 | 可用绑定的按钮分组的按下信号绑定方法槽,通过判断获取单选框的文本来判断,有点不太方便,后面还会给出自定义信号槽的方式来判断(觉得这个方法更合理) | 添加图片 | 支持 | 支持 |
tkinter 代码
[Python] 纯文本查看 复制代码 self.int_var=tkinter.IntVar() # 定义 tkinter 专用变量
# 每个 Radiobutton 单选框都绑定单击事件 clickRadiobutton ,用来做单击或切换时的处理
r1=tkinter.Radiobutton(box,text="选项1",variable=self.int_var,value=0,command=clickRadiobutton) #绑定 tkinter 变量,同时也按变量来分组
r1.pack(side=tkinter.LEFT,padx=2)
r2=tkinter.Radiobutton(box,text="选项2",variable=self.int_var,value=1,command=clickRadiobutton) # 第二个选项,注意每个选项的 value
r2.pack(side=tkinter.LEFT,padx=2)
r3=tkinter.Radiobutton(box,text="选项3",variable=self.int_var,value=2,command=clickRadiobutton) # 第三个选项,每个选项的 value 必须不一样
r3.pack(side=tkinter.LEFT,padx=2)
# 初始化选择
self.int_var.set(1) # 根据 Radiobutton 定义时的 value 值,这里是设置为“选项2”
# 选项判断
if self.int_var.get()==0:# 选项1
parint("我选了第一项")
elif self.int_var.get()==1:# 选项2
parint("我选了第二项")
else: # 选项3
parint("我选了第三项")
PYQt5 代码
判断单选框的选择情况,这里介绍两种方法,各有优缺点,大家自行选择或使用其他方式。一种是利用分组对象的单击信号,可以获得当前所选单选框的文本进行判断,代码简单好理解,但由于要判断文本内容,容易误判,特别是在修改单选框文字时常会忘记同步修改判断代码;另一种通过自定义信号、槽,获取当前选择单选框的序号来判断,缺点是代码量大。下面给出两种方式的代码:
[Python] 纯文本查看 复制代码 self.radio_button1 = QRadioButton("选项1") # 创建单选框
self.radio_button2 = QRadioButton("选项2")
self.radio_button3 = QRadioButton("选项3")
self.button_group = QButtonGroup() # 创建按键分组
self.button_group.addButton(self.radio_button1) # 加入分组
self.button_group.addButton(self.radio_button2)
self.button_group.addButton(self.radio_button3)
self.layout.addWidget(self.radio_button1) # 绑定布局
self.layout.addWidget(self.radio_button2)
self.layout.addWidget(self.radio_button3)
# 第一种方式:判断单选框文本
self.button_group.buttonClicked.connect(self.onButtonClicked) # 绑定按键分组信号槽
...
def onButtonClicked(self, button): # 单击其中一个单选框时触发
if button.text() = "选项1" : #选中第1个单选框时
...
elif button.text() = "选项2" : #选中第2个单选框时
...
else: #选中第3个单选框时
...
# 第二种方式:判断选中单选框的序号
from PyQt5.QtCore import pyqtSignal # 引用自定义信号模块
from functools import partial # 相关模块,因为后面语句使用 lambda 无效
class main(QMainWindow): # 窗口类
customSignal = pyqtSignal(int) # 在成员变量处声明自定义信号
...
radioButtons=[self.radio_button1 , self.radio_button2 , self.radio_button3] # 生成单选框列表
for i range(len(radioButtons)): # 遍历单选框
radioButtons[i].clicked.connect(partial(self.customSignal.emit , index)) # 定义每个单选框的单击信号,试过使用 lambda 无效
# self.button_group.addButton(radioButtons[i]) # 加入按键分组
# self.layout.addWidget(radioButtons[i]) # 绑定布局
self.customSignal.connect(self.onButtonClicked) # 自定义信号绑定槽
...
def onButtonClicked(self, index): # index 为单选框序号(按 radioButtons 列表顺序)
if index == 0 : #选中第1个单选框时
...
elif index == 1 : #选中第2个单选框时
...
else: #选中第3个单选框时
...
7、复选框(Checkbutton、QCheckBox)
在 tkinter 中通常绑定 tkinter.intVar() 变量来判断是否为选择状态,而 PyQt5 则是直接用 check.isChecked() 来判断。均支持图片、文本或图片加文本方式出现。PyQt5 中也可以用 QButtonGroup() 给多个复选框分组,相当于把单选框换在复选框的样式,也只能选中其中一个且必须选中一个,意义不大。
tkinter 代码
[Python] 纯文本查看 复制代码 self.int_var=tkinter.IntVar() # tkinter 专用整型变量
check=tkinter.Checkbutton(root,text='选我',variable=self.int_var, command=onClickCheck) # 绑定变量
check.pack(side=tkinter.LEFT,padx=3)
def onClickCheck(): # 单击事件
if self.int_var.get(): # 判断是否选中
...
else:
self.int_var.set(1) # 强制选中,默认选中为 1 ,未选中为 0
PYQt5 代码
[Python] 纯文本查看 复制代码 self.checkbox = QCheckBox("同意条款")
self.checkbox.stateChanged.connect(self.checkbox_changed)# 设置状态改变信号
def checkbox_changed(self, state): #状态改变槽
if state == Qt.Checked:
print("复选框被勾选")
else:
print("复选框未被勾选")
# 判断状态
if self.checkbox.isChecked() : # 是否选中
print("已启用")
else:
print("未启用")
8、多行文本输入框(Text、QTextEdit)
对于这个控制,tkinter 和 PyQt5 对它的操控还是很丰富的,各有特色,都支持富文本显示,总体来说还是 PyQt5 更强一些,这里就对它的一些常用功能进行对比学习
项目 | tkinter | PyQt5 | 尺寸 | 定义时的 width 和 height 属性,注意单位是字符数
text=tkinter.Text(frame, width=30,height=10) | text01.setFixedWidth(150) # 宽度(像素
text01.setFixedHeight(150) # 高度(像素) | 设置文本 | text.delete('1.0' , 'end') # 清空内容
text.insert('end' , '文本内容') | text.setPlainText('文本内容')
或
text.setText('文本内容') | 内容中插入文本 | text.insert('end' , '从最后面插入文本')
text.insert('1.0' , '从最前面插入文本,1表示第1行,0 表示字符位置') | self.text01.append('从最后面追加文本')
其他指定位置插入时,需要用到 QTextCursor 光标对象,代码有点多,见下方演示代码。
或者使用 text.append 插入 html 带格式代码 | 插入富文本 | text.tag_config("样式名",foreground="blue",font=("黑体",12,"bold")) # 设置样式标签
text.insert('end' , "文本内容", “样式名”) # 插入格式文本 | 需要 QTextCursor 光标对象配合使用,代码有点多,见下方演示代码。 | 显示HTML内容 | 不支持 | text.setHtml(html) # html 为网页内容文本
print(text.toHtml()) # 返回文本编辑框中的 HTML 内容 | 插入图片 | text.image_create('end'.image=image) # image 为 PIL 图像数据 | cursor.insertImage("image.jpg") # cursor 为光标对象
或
text.append("<img src=\"image.png\" />") | 插入列表 | 不支持 | tlf = QTextListFormat() # 列表样式对象
tlf.setIndent(2) # 缩进值
tlf.setStyle(QTextListFormat.ListDecimal) #列表样式
cl=cursor.insertList(tlf)
cursor.insertText("项目1\n项目2\n项目3") | 插入表格 | 不支持 | table=cursor.insertTable(2,2) # 插入 2行2列的表格
for row in range(2):
for col in range(2):
cursor.insertText('Cell %d,%d' % (row, col))
cursor.movePosition(cursor.NextCell) | 插入小部件 | 小部件 = tkinter.Button(text,text="确定", command=onClick_OK) # 定义小部件
text.window_create(‘end’.window=小部件) | 不支持 |
PyQt5 光标配合代码
[Python] 纯文本查看 复制代码 cursor = self.text01.textCursor() #获取文本光标
# cursor= QTextCursor(self.text01.document()) #或者这样获取光标对象
# 在当前光标处插入富文本
char_format = cursor.charFormat() #光标处的字符格式
char_format.setFontFamily("Arial") #字体名
char_format.setFontPointSize(14) #字体尺寸
char_format.setFontWeight(QFont.Bold) # 粗体
char_format.setFontItalic(True) # 斜体
char_format.setFontUnderline(True) # 下划线
cursor.setCharFormat(char_format) # 字体设置
cursor.insertText("我这富文本")
cursor.insertImage("image.jpg") # 在光标处插入图片
# 简单的指定位置插入文本
def insert_text_at_cursor(textWidget, text, position ,charFormat=None): # 在QTextEdit的指定光标位置插入文本
"""
:textWidget: QTextEdit对象
:text: 要插入的文本
:position: 插入位置,可以是'start'(0)、'end'(-1)或者是具体的字符位置号(从0开始)
:charFormat: 插入文本的字符格式
"""
cursor = textWidget.textCursor()
if position == 'start' or position == 0:
cursor.movePosition(cursor.Start)
elif position == 'end' or position == -1:
cursor.movePosition(cursor.End)
elif isinstance(position, int):
cursor.movePosition(cursor.Start)
for _ in range(position): # 跳过位置前的字符
cursor.movePosition(cursor.NextCharacter) #
else:
raise ValueError("position 参数必须是 'start', 'end' 或者一个字符位置整数")
if charFormat!=None:
cursor.insertText(text , charFormat)
else:
cursor.insertText(text)
textWidget.setTextCursor(cursor)
textWidget.ensureCursorVisible() # 确保插入的文本可见
# 删除指定位置内容
def delete_seletion_text(textWidget, start , end):
cursor.setPosition(start) # 标记选择开始
cursor.setPosition(end,QTextCursor.KeepAnchor) #选择指定内容
cursor.removeSelectedText() # 删除选择部分内容
self.text.setTextCursor(cursor)
9、下拉菜单(Combobox、QComboBox)
tkinter 中下拉菜单提供的功能较弱,不能添加图标,而 PyQt5 可以,判断选择时,tkinter 只能通过项目序或项目文本来判断,PyQt5 还提供了用户数据的判断,比较灵活,它们的示例代码如下:
tkinter 代码
[Python] 纯文本查看 复制代码 self.combobox=ttk.Combobox(self, width=15 , state="readonly") # 只读状态,即只能选择不能输入
self.combobox.pack(side="left", padx=2)
self.combobox['value']=['选项1','选项2','选项3'] # 添加下拉菜单项目
self.combobox.current(0) # 默认选中第一项
self.combobox.bind("<<ComboboxSelected>>",self.onChangeItem) # 绑定选择项目事件
def onChangeItem(self,event):#选择项目事件
print(self.combobox.get()) # 获取当前选中项目的文本
if self.combobox.current()==0 : # 判断当前选项
print("我选了选项1")
elif self.combobox.current()==1:
print("我选了选项2")
else:
print("我选了选项3")
# 非只读时允许输入其他值,这时 self.combobox.current()=-1
PYQt5 代码
[Python] 纯文本查看 复制代码 self.combobox = QComboBox(self)
self.combobox.addItem('选项1','用户数据1')
icon=QIcon('icon.png') #图标
self.combobox.addItem(icon, '选项2','用户数据2') # 带图标的项目
self.combobox.addItems(["选项 3", "选项 4", "选项 5"]) #不能添加用户数据
self.combobox.setEditable(False) # 设为只读
self.combobox.currentIndexChanged.connect(self.combobox_changed)#选项改变信号
def combobox_changed(self, index): # index 为选择序号,类似 tkinter 中的 current()
# 获取当前选中的文本
text = self.combobox.currentText() # 当前选择内容
print(f"当前选中: {text}")
print(self.combobox.currentData()) # 获取用户数据,addItems 时用户数据为 None
10、限制范围输入框(Spinbox、QSpinBox)
限制范围输入框右侧带有上、下两调节按键,支持的数据有浮点、整型,tkinter 还支持字符类型的调整,PyQt5 将整型、浮点分成 QSpinBox 和 QDoubleSpinBox 两种控件,不直接支持字符类型,但可以靠自定义类实现。
tkinter 代码
[Python] 纯文本查看 复制代码 self.int_var=tkinter.IntVar()
self.str_var=tkinter.StringVar()
spb1=tkinter.Spinbox(root, from_=0, to=100, increment=1, textvariable=self.int_var , # 最小值0,最大值 100, 步长 1
command=self.onClickSpb1)
spb1.pack(side=tkinter.LEFT,padx=2)
spb2=tkinter.Spinbox(root,textvariable=self.str_var , values=("项目1","项目1","项目1") , # 定义字符型值
state="readonly", command=self.onClickSpb2) # 只读,即只能通过按键调整值,不能直接输入
spb2.pack(side=tkinter.LEFT,padx=2)
self.int_var.set(5) # 初始化值
def onClickSpb1(self): # 调整值时触发
print(self.int_var.get()) # 获取当前值
PYQt5 代码
[Python] 纯文本查看 复制代码 self.spin = QSpinBox(self)
# 设置QSpinBox的范围从0到 500
self.spin.setRange(0, 500) # 也可以用 self.spin.setMinimum(0)、self.spin.setMaximum(100) 代替
# 设置QSpinBox的初始值为 50
self.spin.setValue(50)
self.spin.setSingleStep(2) # 设置步长
self.spin.setDecimals(2) # 设置精度(小数位数)
spb.setWrapping(True) #数据循环调整
self.spin.setReadOnly(True) # 设为只读
self.spin.setPrefix("$") # 前缀
self.spin.setSuffix(".00")# 后缀
self.spin.valueChanged.connect(self.handle_spin) # 或是str 类时用 textChanged(带前缀、后缀时视为字符,也要用此信号)
def handle_spin(self, i):
print(i)
实现字符枚举的演示
[Python] 纯文本查看 复制代码 class strSpinBox(QSpinBox): # 自定义 SpinBox 类
def textFromValue(self, v: int): # 自定义字符枚举内容
week = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', ]
return week[v]
...
self.mySpinbox= strSpinBox() # 创建自定义对象
self.mySpinbox.setRange(0, 6) # 其中的 6 枚举字符总数 -1 ,即表示范围为 week 列表中的所有项目
|
|