界面开发
需求
开发一个界面,用于配置具体功能属性,最终生成自己想要的c代码。
具体要求:
- 左侧是具体大类栏,如:IO,ADC,PWW
- 右侧为具体属性栏,如:名称,…
- 选择某一具体条目时,显示对应的属性配置
实现的效果:以Davinci为例
涉及用到模块:
- QMenuBar
- QMenu
- QAction
- QTreeWidget
- QStackedWidget
- QWidget
- QLable
- QLineEdit
- QXomboBox(下拉盒)
- Frame
开发思路
- 图形开发基本是置顶而下的,从顶层往下设计
- 代码开发也借鉴图形开发方式,采用继承方式,逐一往下开发
- 为了便于开发,可以采用qt designer和代码开发这两者方式结合开发
图形用于调整界面,代码用于方便补充内容
开发过程
实现方法:
- 1、当单击左边的QTreeWidget时
- 2、处理单击事件:获取当前行,并调用setCurrentIndex来显示QStackedWidget具体窗口
- 3、可以采用QFormLayout属性,在QStackedWidget窗口内可以添加具体内容
- 4、QFormLayout是垂直布局属性(QVBoxLayout),便于软件逐行添加,执行formLayout.addRow(“名称”,“…”)
QTreeWidget
创建QTreeWidget(树形窗口)
self.youSelf_QTreeWidget = QtWidgets.QTreeWidget(被继承的窗口)
创建Item(条目)
item_1 = QtWidgets.QTreeWidgetItem(self.youSelf_QTreeWidget)#创建1级条目
item_11 = QtWidgets.QTreeWidgetItem(item_0 )#1级条目下再创建2级条目
item_111 = QtWidgets.QTreeWidgetItem(item_11 )#1级条目下的2级条目下创建3级条目
问题
1、item文本如果过长,显示不完全,出现省略号
解决方法:
加大MinimumSectionSize的值,比如100等
参考:PyQt5中设置QtreeWidget水平滚动条
开发
1、获取当前鼠标选中的行,进而显示对应的属性
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
'''
#....
'''
self.IOHW_QTreeWidget.clicked.connect(self.onClicked)
def onClicked(self):
item = self.IOHW_QTreeWidget.currentItem()
if item.parent():#它的父类存在
print(item.text(0))#自己的内容
print(item.parent().text(0))
if item.parent().text(0) == "IO":
self.stackedWidget.setCurrentIndex(self.stackedWidget.indexOf(self.page_IO))
if item.parent().text(0) == "ADC":
self.stackedWidget.setCurrentIndex(self.stackedWidget.indexOf(self.page_ADC))
if item.parent().text(0) == "PWM":
self.stackedWidget.setCurrentIndex(self.stackedWidget.indexOf(self.page_PWM))
if item.parent().text(0) == "test":
self.stackedWidget.setCurrentIndex(self.stackedWidget.indexOf(self.page_test))
引用
PyQt5.QtWidgets.QFormLayout:窗体布局
QStackedWidget:堆栈窗体
-
插入窗体
-
在堆栈窗体的某一窗体内放入布局窗体(QFormLayout),并设置成垂直布局(QVBoxLayout)
-
窗体相关生成的代码:
self.page_test = QtWidgets.QWidget() #1、创建的窗体page_test
self.page_test.setObjectName("page_test")
self.verticalLayout_page_test = QtWidgets.QVBoxLayout(self.page_test) #2、将page_test窗体设置成垂直布局
self.verticalLayout_page_test.setObjectName("verticalLayout_page_test")
self.formLayout_page_test = QtWidgets.QFormLayout() #3、创建布局
self.formLayout_page_test.setObjectName("formLayout_page_test")
self.verticalLayout_page_test.addLayout(self.formLayout_page_test) #4、将布局添加到垂直布局中
self.stackedWidget.addWidget(self.page_test) #5、将page_test窗体添加到堆栈窗体内
效果:
- 手动添加的代码,补充内容
'''
# 手动添加,方便开发
'''
# 在page_test中添加行编辑器
self.page_test.edit1 = QtWidgets.QLineEdit()#定义
self.formLayout_page_test.addRow('整数校验', self.page_test.edit1)#添加
# 在page_test中添加下拉编辑器
self.page_test.combo_box = QtWidgets.QComboBox()#定义
self.page_test.combo_box.addItems(['Option1', 'Option2', 'Option3'])#下拉值
self.formLayout_page_test.addRow('整数校验2', self.page_test.combo_box)#添加
垂直布局选择与否
- 选择了垂直布局效果
- 未选择垂直布局效果
PyQt5.QtCore.QSettings()
总结
- 用Qt Designer每次更新UI再用PyUic更新成.py文件时,.py文件总是覆盖自己添加的代码
解决方法就是用继承父类的方法,采用继承方法
python类的继承
数据保存及打开Qsetting
QListWidget、QTableWidget将所选项目保存到Qsettings
aaa
以下是转载
import contextlib
from PyQt5 import QtCore, QtGui, QtWidgets
class SettingsManager:
def __init__(self, filename):
self.m_settings = QtCore.QSettings(filename, QtCore.QSettings.IniFormat)
@property
def settings(self):
return self.m_settings
def read(self, widget):
self.settings.beginGroup(widget.objectName())
if isinstance(widget, QtWidgets.QAbstractItemView):
selectionMode = self.settings.value(
"selectionMode", type=QtWidgets.QAbstractItemView.SelectionMode
)
widget.setSelectionMode(selectionMode)
if isinstance(widget, QtWidgets.QListWidget):
items = self.settings.value("items")
selecteditems = self.settings.value("selecteditems")
# In the first reading the initial values must be established
if items is None:
self.read_defaults(widget)
else:
stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
while not stream.atEnd():
it = QtWidgets.QListWidgetItem()
stream >> it
widget.addItem(it)
stream = QtCore.QDataStream(
selecteditems, QtCore.QIODevice.ReadOnly
)
while not stream.atEnd():
row = stream.readInt()
it = widget.item(row)
if it is not None:
it.setSelected(True)
if isinstance(widget, QtWidgets.QTableWidget):
rowCount = self.settings.value("rowCount", type=int)
columnCount = self.settings.value("columnCount", type=int)
widget.setRowCount(rowCount)
widget.setColumnCount(columnCount)
items = self.settings.value("items")
if items is None:
self.read_defaults(widget)
else:
stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
while not stream.atEnd():
it = QtWidgets.QTableWidgetItem()
i = stream.readInt()
j = stream.readInt()
stream >> it
widget.setItem(i, j, it)
selecteditems = self.settings.value("selecteditems")
stream = QtCore.QDataStream(
selecteditems, QtCore.QIODevice.ReadOnly
)
while not stream.atEnd():
i = stream.readInt()
j = stream.readInt()
it = widget.item(i, j)
if it is not None:
it.setSelected(True)
self.settings.endGroup()
def write(self, widget):
self.settings.beginGroup(widget.objectName())
if isinstance(widget, QtWidgets.QAbstractItemView):
self.settings.setValue("selectionMode", widget.selectionMode())
if isinstance(widget, QtWidgets.QListWidget):
items = QtCore.QByteArray()
stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
for i in range(widget.count()):
stream << widget.item(i)
self.settings.setValue("items", items)
selecteditems = QtCore.QByteArray()
stream = QtCore.QDataStream(
selecteditems, QtCore.QIODevice.WriteOnly
)
for it in widget.selectedItems():
stream.writeInt(widget.row(it))
self.settings.setValue("selecteditems", selecteditems)
if isinstance(widget, QtWidgets.QTableWidget):
self.settings.setValue("rowCount", widget.rowCount())
self.settings.setValue("columnCount", widget.columnCount())
items = QtCore.QByteArray()
stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
for i in range(widget.rowCount()):
for j in range(widget.columnCount()):
it = widget.item(i, j)
if it is not None:
stream.writeInt(i)
stream.writeInt(j)
stream << it
self.settings.setValue("items", items)
selecteditems = QtCore.QByteArray()
stream = QtCore.QDataStream(
selecteditems, QtCore.QIODevice.WriteOnly
)
for it in widget.selectedItems():
# print(it.row(), it.column())
stream.writeInt(it.row())
stream.writeInt(it.column())
self.settings.setValue("selecteditems", selecteditems)
self.settings.endGroup()
def release(self):
self.m_settings.sync()
def read_defaults(self, widget):
if widget.objectName() == "listwidget_1":
widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
for i in range(10):
widget.addItem(QtWidgets.QListWidgetItem(str(i)))
elif widget.objectName() == "listwidget_2":
widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
for i in "abcdefghijklmnopqrstuvwxyz":
widget.addItem(QtWidgets.QListWidgetItem(i))
elif widget.objectName() == "tablewidget":
widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
widget.setRowCount(10)
widget.setColumnCount(10)
for i in range(widget.rowCount()):
for j in range(widget.columnCount()):
it = QtWidgets.QTableWidgetItem("{}-{}".format(i, j))
widget.setItem(i, j, it)
@contextlib.contextmanager
def settingsContext(filename):
manager = SettingsManager(filename)
try:
yield manager
finally:
manager.release()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.listwidget_1 = QtWidgets.QListWidget(objectName="listwidget_1")
listwidget_2 = QtWidgets.QListWidget(objectName="listwidget_2")
tablewidget = QtWidgets.QTableWidget(objectName="tablewidget")
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.listwidget_1)
lay.addWidget(listwidget_2)
lay.addWidget(tablewidget)
self.read_settings()
def closeEvent(self, event):
self.write_settings()
super().closeEvent(event)
def read_settings(self):
with settingsContext("data.ini") as m:
for children in self.findChildren(QtWidgets.QWidget):
if children.objectName():
m.read(children)
def write_settings(self):
with settingsContext("data.ini") as m:
for children in self.findChildren(QtWidgets.QWidget):
if children.objectName():
m.write(children)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())