删除机制
- 需要先找到一个节点,可以创建一个
list
自己来管理;也可以通过findChild、findChildren
来查找 - 利用
deleteLater
来删除,注意这个删除是在回到主循环后才执行的,可以理解成释放一个信号
# deleteDemo.py
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.__setttingWindow()
self.__buildUI()
self.count = 0
# ================== 功能函数 ==================
def __setttingWindow(self):
self.resize(640, 480)
def __buildUI(self):
grid = QGridLayout(self)
# 创建几个标签
for i in range(4):
label = QLabel(f"label-{i}")
grid.addWidget(label, 0, i)
# 创建一个删除按钮
btn = QPushButton("删除", clicked=self.do_deleteLabel)
grid.addWidget(btn, 1, 0)
btn = QPushButton("增加", clicked=self.do_addLabel)
grid.addWidget(btn, 1, 1)
# ================== 槽函数 ==================
def do_deleteLabel(self):
label = self.findChild(QLabel)
if label is None:
print("删完了")
else:
label.deleteLater()
def do_addLabel(self):
layout = self.layout()
label = QLabel(f"newlabel-{self.count}")
layout.addWidget(label, 0, self.count)
self.count = (self.count + 1) % 4
if __name__ == '__main__':
app = QApplication([])
w = Demo()
w.show()
app.exec_()
可重入和线程安全
函数可重入(reentrant):在多个线程上各自创建实例,各个调用同一个函数是安全的;
函数线程安全(thread-safe):多个线程调用同一个实例的同一个函数是安全的;
列表组件
QListWidget
定位:item、row
两者也可以互相转换
增加:addItem()、addItems()、insertItem()
删除:takeItem()
常用signal:currentRowChanged
注意:创建空的listWidget时,currentRow是-1;而当加入item(非空)后,会设置currentItem为0,触发一次currentRowChanged
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.__setttingWindow()
self.__buildUI()
# ================== 功能函数 ==================
def __setttingWindow(self):
self.resize(640, 480)
def __buildUI(self):
grid = QGridLayout(self)
# 左边的listWidgets
self.listNames = QListWidget()
print(self.listNames.currentRow())
grid.addWidget(self.listNames, 0, 0, 1, 2)
self.listNames.addItems(["小红", "小明", "小呆"])
self.listNames.currentRowChanged.connect(self.do_currentChanged)
# 按钮组
grid.addWidget(QPushButton("增加", clicked=self.do_addItem), 1, 0)
grid.addWidget(QPushButton("删除", clicked=self.do_deleteItem), 1, 1)
# ================== 槽函数 ==================
def do_addItem(self):
# 在末尾增加一个
self.listNames.addItem("新增名字")
# self.listNames.setCurrentRow(self.listNames.count() - 1)
def do_deleteItem(self):
row = self.listNames.currentRow()
if row >= 0:
self.listNames.takeItem(row)
def do_currentChanged(self, currentRow):
print(f"现在的行是: {currentRow}")
if __name__ == '__main__':
app = QApplication([])
w = Demo()
w.show()
app.exec_()
QTableWidget
创建并设置行列:QTableWidget(3, 3)
设置表头:setHorizontalHeaderLabels()
;
增加:setRowCount()
,新建缺失的行,老的行不变
删除:removeRow()
删除指定行;setRowCount()
删除多余行
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.__setttingWindow()
self.__buildUI()
# ================== 功能函数 ==================
def __setttingWindow(self):
self.resize(640, 480)
def __buildUI(self):
grid = QGridLayout(self)
# 正上方放表格
self.tableSchools = QTableWidget(3, 3)
grid.addWidget(self.tableSchools, 0, 0, 1, 2)
# 表头
self.tableSchools.setHorizontalHeaderLabels(['名字', '位置', '人数'])
self.tableSchools.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 按钮组
grid.addWidget(QPushButton("增加", clicked=self.do_addRow), 1, 0)
grid.addWidget(QPushButton("删除", clicked=self.do_deleteRow), 1, 1)
# ================== 槽函数 ==================
def do_addRow(self):
self.tableSchools.setRowCount(self.tableSchools.rowCount() + 1)
def do_deleteRow(self):
curRow = self.tableSchools.currentRow()
if curRow >= 0:
self.tableSchools.removeRow(curRow)
if __name__ == '__main__':
app = QApplication([])
w = Demo()
w.show()
app.exec_()
QTreeWidget
创建:QTreeWidget()
设置列数:setColumnCount(2)
+ setHeaderLabels(['概况', '详细'])
创建顶层节点:topItem = QTreeWidgetItem(self.typeSchool)
设置信息:topItem.setText(0, '人民小学')
、topItem.setText(1, 'xx省xx市人民小学')
加顶层节点:self.treeSchool.addTopLevelItem(topItem)
加入非顶层节点:利用其父节点,parentItem.addChild(newItem)
删除非顶层节点:利用父节点:curItem.parent().removeChild(curItem)
注意: 引入了type
的机制,可以用于描述item
的级别;有多个列,设置text时要指定列号;删除、增加都得借助父节点
# treeWidget.demo
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Demo(QWidget):
typeSchool, typeClass = range(2)
def __init__(self):
super(Demo, self).__init__()
self.__setttingWindow()
self.__buildUI()
# ================== 功能函数 ==================
def __setttingWindow(self):
self.resize(640, 480)
def __buildUI(self):
grid = QGridLayout(self)
# 左边的treeWidgets
self.treeSchool = QTreeWidget()
grid.addWidget(self.treeSchool, 0, 0, 1, 2)
self.treeSchool.setColumnCount(2)
self.treeSchool.setHeaderLabels(['概况', '详细'])
# 创建2个顶层节点
topItem = QTreeWidgetItem(self.typeSchool)
topItem.setText(0, '人民小学')
topItem.setText(1, 'xx省xx市人民小学')
self.treeSchool.addTopLevelItem(topItem)
topItem = QTreeWidgetItem(self.typeSchool)
topItem.setText(0, '憨憨小学')
topItem.setText(1, 'xx省xx市憨憨小学')
self.treeSchool.addTopLevelItem(topItem)
# 按钮组
grid.addWidget(QPushButton("增加", clicked=self.do_addItem), 1, 0)
grid.addWidget(QPushButton("删除", clicked=self.do_deleteItem), 1, 1)
# ================== 槽函数 ==================
def do_addItem(self):
# 在顶层节点下增加
parentItem = self.treeSchool.currentItem()
if parentItem.type() == self.typeClass:
parentItem = parentItem.parent()
newItem = QTreeWidgetItem(self.typeClass)
newItem.setText(0, '分校')
newItem.setText(1, f'{parentItem.data(0, Qt.DisplayRole)}的分校')
parentItem.addChild(newItem)
def do_deleteItem(self):
curItem = self.treeSchool.currentItem()
if curItem.type() == self.typeSchool:
return
# curItem.deleteLater()
curItem.parent().removeChild(curItem)
def do_currentChanged(self, currentRow):
# print(f"现在的行是: {currentRow}")
pass
if __name__ == '__main__':
app = QApplication([])
w = Demo()
w.show()
app.exec_()
感觉三个组件由于形式差距大,导致API也差得比较多;开始时可以结合其表现形式来熟悉各个函数的使用。