前言
这一段时间想学习一些python 图形界面的东东,经查询资料得知,使用通过PySide6模块使用QT界面 还是比较靠谱的,于是下载安装了PySide6 ,安装很顺利,使用 pip install pyside6 即可。但是发现QT的类包太多了,不知道从何学起,于是就想先了解一下QT包中的相关一些信息,尝试着做出以下界面。踩过的一些坑,也得到了一些经验,在此记录。
目标:给出一个包模块或一个类,列出其下面的模块、类及函数方法。
一开始想着使用 dir(),发现dir 能显示的均是已经加载过的模块,还是必须在同一个文件中import 过的才可以。试着使用 importlib 动态导入模块,发面 dir 出来的东东不全,几经试验以后来发现 inspect 中的 getmembers() 可以使用。看下图

左边是一个QTreeWidget ,用于树状列表显示模块的相关信息。右边是一个辅助信息展示界面。同时下面的搜索也展示到右边的QListWidget 上面。设置导出功能,可将树状显示的内容按同样的格式保存到文本文件,供模块查询学习。
一、设置图形设计工具
图形界面开发:
使用Qt设计师,安装PySide6 后默认安装了pyside6-designer.exe和pyside6-uic.exe,使用 pycharm 的设置 External Tools 添加设计工具的转换工具。
pyside6 Designer的设置:

pyside6 Designer:Program:程序是安装的 pyside6-designer.exe
Arguments:参数设置$FilePath$,文件全路径
工作目录:设置$FileDir$ ,文件目录。
同样对UIC转换工具进行设置:

pyside6 UIC:Program:程序是安装的 pyside6-uic.exe
Arguments:参数设置$FilePath$ -o $FileDir$\$FileNameWithoutExtension$.py
工作目录:设置$FileDir$ ,文件目录。
UIC工具是将图形界面文件转成py文件。
命令行为 uic.exe 文件.ui -o 输出文件全路径.py 。以上设置为同名同目录输出py文件。
设置完成后就可以通过右键菜单打开图形界面设计器。

二、图形界面设计布局
界面很简单,拖拉拽几个按钮,两个单行文本,一个tree Widget, 一个list widget 。主要说明 的是如何布局。

从图中可以看到,使用了三个横向布局,表单采用一个纵向布局。布局比例可以使用layoutStretch 这个属性去调整。

每个组件一个数字,为占用整体布局的比例。
这里有个参数 QTreeWidget 的一个属性需要设置隐藏一下:

该属性置为不可见,意思树状视图中 不显示标题栏
三、图形界面运行
界面保存后,使用UIC转成py文件代码 ,如下,由于是机器自动生成的,可读性不是太好,不建议在此文件中直接进行修改。
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'mainui.ui'
##
## Created by: Qt User Interface Compiler version 6.4.0
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QHBoxLayout, QHeaderView, QLabel,
QLineEdit, QListWidget, QListWidgetItem, QPushButton,
QSizePolicy, QSpacerItem, QTreeWidget, QTreeWidgetItem,
QVBoxLayout, QWidget)
class Ui_myinfo(object):
def setupUi(self, myinfo):
if not myinfo.objectName():
myinfo.setObjectName(u"myinfo")
myinfo.resize(1011, 622)
myinfo.setStyleSheet(u"*{\n"
"font: \"Microsoft YaHei UI\";\n"
"font-size:16pt;\n"
"color:rgb(0, 170, 255);\n"
"}\n"
"")
self.verticalLayout = QVBoxLayout(myinfo)
self.verticalLayout.setObjectName(u"verticalLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.label = QLabel(myinfo)
self.label.setObjectName(u"label")
self.horizontalLayout.addWidget(self.label)
self.txtInput = QLineEdit(myinfo)
self.txtInput.setObjectName(u"txtInput")
self.horizontalLayout.addWidget(self.txtInput)
self.cmdSubmit = QPushButton(myinfo)
self.cmdSubmit.setObjectName(u"cmdSubmit")
self.horizontalLayout.addWidget(self.cmdSubmit)
self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(self.horizontalSpacer_3)
self.cmdfile = QPushButton(myinfo)
self.cmdfile.setObjectName(u"cmdfile")
self.horizontalLayout.addWidget(self.cmdfile)
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(self.horizontalSpacer_2)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 6)
self.horizontalLayout.setStretch(2, 1)
self.horizontalLayout.setStretch(3, 1)
self.horizontalLayout.setStretch(4, 1)
self.horizontalLayout.setStretch(5, 1)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.tvInfo = QTreeWidget(myinfo)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"name");
self.tvInfo.setHeaderItem(__qtreewidgetitem)
self.tvInfo.setObjectName(u"tvInfo")
self.tvInfo.setLineWidth(4)
self.horizontalLayout_2.addWidget(self.tvInfo)
self.lstDetail = QListWidget(myinfo)
self.lstDetail.setObjectName(u"lstDetail")
self.horizontalLayout_2.addWidget(self.lstDetail)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.txtSearch = QLineEdit(myinfo)
self.txtSearch.setObjectName(u"txtSearch")
self.horizontalLayout_3.addWidget(self.txtSearch)
self.cmdSearch = QPushButton(myinfo)
self.cmdSearch.setObjectName(u"cmdSearch")
sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.cmdSearch.sizePolicy().hasHeightForWidth())
self.cmdSearch.setSizePolicy(sizePolicy)
self.cmdSearch.setCursor(QCursor(Qt.ArrowCursor))
self.horizontalLayout_3.addWidget(self.cmdSearch)
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer)
self.cmdExit = QPushButton(myinfo)
self.cmdExit.setObjectName(u"cmdExit")
sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
sizePolicy1.setHorizontalStretch(1)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.cmdExit.sizePolicy().hasHeightForWidth())
self.cmdExit.setSizePolicy(sizePolicy1)
self.horizontalLayout_3.addWidget(self.cmdExit)
self.horizontalLayout_3.setStretch(0, 6)
self.horizontalLayout_3.setStretch(1, 2)
self.horizontalLayout_3.setStretch(3, 2)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.retranslateUi(myinfo)
QMetaObject.connectSlotsByName(myinfo)
# setupUi
def retranslateUi(self, myinfo):
myinfo.setWindowTitle(QCoreApplication.translate("myinfo", u"Form", None))
self.label.setText(QCoreApplication.translate("myinfo", u"\u6a21\u5757\u540d\u79f0\uff1a", None))
#if QT_CONFIG(tooltip)
self.txtInput.setToolTip(QCoreApplication.translate("myinfo", u"\u8bf7\u8f93\u5165\u6a21\u5757\u540d\u79f0\uff1a", None))
#endif // QT_CONFIG(tooltip)
self.cmdSubmit.setText(QCoreApplication.translate("myinfo", u"\u786e\u5b9a", None))
self.cmdfile.setText(QCoreApplication.translate("myinfo", u"\u5bfc\u51fa", None))
self.cmdSearch.setText(QCoreApplication.translate("myinfo", u"\u641c\u7d22", None))
self.cmdExit.setText(QCoreApplication.translate("myinfo", u"\u9000 \u51fa", None))
# retranslateUi
比较好的办法是此文件不动,另外生成一个类文件继承该图形界面类,这样图形界面变化后重新生成代码也无影响。
标准代码如下:
from PySide6.QtWidgets import QApplication
import sys
from myui import Ui_Form
#导入图形文件类
#新建类自 窗口组件和自已设计的界面继承
class View(QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = View()
window.show()
sys.exit(app.exec())
这样,我们的图形界面就 运行起来了
四、设置信息响应
QT中的事件响应为信号与槽的模式。signal 与slot ,具体来说信号和消息差不多,槽就是处理消息的程序方式。比如说鼠标单击消息就可是一个信号,处理单击事件的函数程序就是一个槽,这两个要进行关联起来后才能正常处理消息。
1、图形界面信号与槽编辑
在图形界面上通过F4打开信号槽编辑模式

鼠标放上可以直接拖拉进行信号与槽的连接,下图将按钮的点击事件信息连接到文本框的清空文本框的槽上。关联后,点击按钮,文本框将被清空。

2、使用标准函数名称关联信号与槽
pycharm 中需要勾选如下选项后,可使用标准化的命名方式自动关联信息与槽。
如鼠标单击事件的标准命名为: on_按钮名称_clicked ,在以下选项勾选的情况下,以这个名称来命名的函数可自动处理鼠标单击事件

3、自定义信号与槽的连接
可通过以下语句连接信息与槽。
cmdOk.clicked.connect(on_tv_clicked)
cmdOk.clicked 就是一个信号,单击信号 ,on_cmdOk_clicked 为一个事件处理函数。
定义事件处理函数需要使用关键字 @Slot() ,括号中可以使用参数,由于python 通过C++对接,因此需要明确变量的类型。如 @Slot(str,int)
@Slot()
def exit(self):
self.close()
@Slot()
def on_tv_clicked(self):
print('按钮')
pass
使用明确的connect 语句连接信息与槽,对函数的命名没有要求。
4、一个好的习惯
由于一个项目中可能会有很多个信息与槽的连接,因此使用专门的函数处理信息与槽的连接。增加一个信号,增加一条连接语句,清晰明了。
class View(QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
self.bind()
def bind(self):
self.cmdSubmit.clicked.connect(self.on_cmd_clicked)
self.tvInfo.doubleClicked.connect(self.on_db_clicked)
self.tvInfo.clicked.connect(self.on_tv_clicked)
self.cmdExit.clicked.connect(self.exit)
self.cmdfile.clicked.connect(self.savetofile)
self.cmdSearch.clicked.connect(self.search)
五、模块信息获取实现
模块信息使用Importlib.import_module(modname) 通过字符串导入相应的模块,并返回导入的模块变量。 通过 inspect.getmembers(modname or classname) 得到其成员及成员的类型,根据类型分别保存到不同的字典列表中:
info={'module':['mod1','mod2'],'class':['cls1','cls2']
def getinfo(self):
self.initinfo()
if inspect.ismodule(self.mod):
for c, cls in inspect.getmembers(self.mod):
# printif(c, cls)
if c == '__all__':
self.info['module'].extend(cls)
else:
if inspect.ismodule(cls):
key = 'module'
else:
if inspect.isclass(cls):
key = 'class'
else:
if inspect.isfunction(cls):
key = 'function'
else:
key = self.__gettype__(cls)
if key not in DataType.DTTYPE:
key = DataType.DT_OTHERS
self.info[key].append(c)
self.info['module'] = list(set(self.info['module']))
self.info['module'].sort()
类信息的获取差不多,均是先使用 importtlib 动态导入模块,模块名.类名 组合成类的全名,通过 inspect.getmembers(类类型),注意此处为类类型。getmembers 返回两个参数,一个是类名称,一个是类类型。
这样设计一个类,实现模块的动态导入和信息的获取。
六、QTreeWidget组件展示
1、自字典列表读取并展示
self.tvInfo.clear()
info = Modinfo(self.txtInput.text()).getinfo()
self.tvInfo.addTopLevelItem(QTreeWidgetItem([name]))
items = []
root = self.tvInfo.topLevelItem(0)
for key, values in info.items():
item = QTreeWidgetItem([key])
root.addChild(item)
for value in values:
child = QTreeWidgetItem([value])
item.addChild(child)
#info 数据格式
#info={'module':['mod1','mod2'],'class':['cls1','cls2']
形成如下的列表

2、双击事件处理
要求双击时能够根据当前的节点数据类型继续下控,如是模块或类,则取得相应的成员列表并展示。

上代码:
@Slot()
def on_db_clicked(self):
curitem = self.tvInfo.currentItem()
fpath = self.getFullPath(curitem)
# 如果是类或是模块,则生成信息增加到列表中
if curitem.parent() and (curitem.text(0) not in DataType.DTTYPE) and (
curitem.parent().text(0) in DataType.DTDBTYPE):
if self.tvInfo.currentItem().childCount() > 0: return
if self.tvInfo.currentItem().text(0) == '__class__': return
info = self.getinfo(curitem)
if info == '': return
for key, values in info.items():
item = QTreeWidgetItem([key])
curitem.addChild(item)
for value in values:
child = QTreeWidgetItem([value])
item.addChild(child)
3、遍历搜索
搜索遍历QTreeWidget 使用迭代器 QTreeWidgetItemIterator()
@Slot()
def search(self):
self.lstDetail.clear()
if self.txtSearch.text == '':
return
it = QTreeWidgetItemIterator(self.tvInfo)
searchstr = self.txtSearch.text()
while it:
item = it.value()
if searchstr.lower() in item.text(0).lower():
self.lstDetail.addItem(self.FullPath(item))
next(it)
4、导出保存文件
打开保存文件对话框: QFileDialog.getSaveFileName()
通过一个迭代递归函数取得行列表。其中一个难点是如何得到每项的缩进。通过使用每个节点的全路径的数量获得每个节点的层级,根据层级采用不同的缩进方式写入文件。
def printitem(self,item:QTreeWidgetItem):
indent=len(self.getFullPath(item).split('.'))
self.lstLines.append(' '*(indent-1)+item.text(0)+'\n')
for i in range(item.childCount()):
self.printitem(item.child(i))
@Slot()
def savetofile(self):
filename, filter = QFileDialog.getSaveFileName(self, '保存文件', os.getcwd(), filter='文本文件(*.txt)')
if filename:
with open(filename, 'w') as f:
item = self.tvInfo.topLevelItem(0)
# f.writelines()
self.lstLines.clear()
self.printitem(item)
f.writelines(self.lstLines)
f.close()
七、完整源代码
import sys
from modinfo.mainui import Ui_myinfo
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import importlib
import inspect
import os
ISDEBUG = True
def printif(*args, sep=' ', end='\n', file=None):
if ISDEBUG:
print(*args, sep, end, file)
class DataType:
DT_MODULE = 'module'
DT_CLASS = 'class'
DT_FUNC = 'function'
DT_OTHERS = 'others'
DT_CLASS_METHOD = 'method'
DT_CLASS_STATIC_METHOD = 'staticmethod'
DT_CLASS_PROP = 'property'
DT_CLASS_SLOT = 'slot'
DT_CLASS_FUNC = 'function'
DT_CLASS_ATTR = 'attribute'
DT_CLASS_MEMBER = 'member'
DT_CLASS_BIN_METHOD = 'built-in method'
DT_CLASS_BIN_FUNC = 'built-in function'
DTTYPE = [DT_MODULE, DT_CLASS, DT_CLASS_FUNC, DT_CLASS_METHOD, DT_CLASS_STATIC_METHOD, DT_CLASS_PROP,
DT_CLASS_BIN_METHOD, DT_CLASS_BIN_FUNC, DT_CLASS_SLOT, DT_CLASS_ATTR, DT_CLASS_MEMBER, DT_OTHERS]
DTDBTYPE = [DT_MODULE, DT_CLASS]
DT_BIN_TYPE = [DT_CLASS_BIN_METHOD, DT_CLASS_BIN_FUNC]
DT_METHOD_FUNC = [DT_CLASS_METHOD, DT_CLASS_FUNC]
class Modinfo():
def __init__(self, name='', clsname=''):
# if name.isspace():
self.clsname = clsname
self.modname = name
# print(self.modname, self.clsname)
self.initinfo()
try:
self.mod = importlib.import_module(name)
except Exception as r:
QMessageBox(QMessageBox.Information, '信息', '加载模块错误:' + str(r)).exec()
self.mod = None
# self.getinfo()
def initinfo(self):
self.info = {}
for k in DataType.DTTYPE:
self.info[k] = []
def delEmpty(self):
info1 = self.info.copy()
for k in DataType.DTTYPE:
if len(info1[k]) == 0:
info1.pop(k)
return info1
def getNameType(self):
if inspect.ismodule(self.mod):
for c, cls in inspect.getmembers(self.mod):
if c == self.clsname:
return c, cls
def getClassInfo(self):
self.initinfo()
name, clss = self.getNameType()
if inspect.isclass(clss):
for c, cls in inspect.getmembers(clss):
key = self.__gettype__(cls)
# printif(c, key,cls)
if key not in DataType.DTTYPE:
print(key, cls)
key = DataType.DT_OTHERS
self.info[key].append(c)
return self.delEmpty()
def __gettype__(self, cls):
lstcls = str(cls).split(' ')
if len(lstcls) > 1 and lstcls[1] in DataType.DT_METHOD_FUNC:
key = lstcls[0].strip('<') + ' ' + lstcls[1]
#print(key, cls)
else:
key = str(cls).split(' ')[0].strip('<')
return key
def getinfo(self):
self.initinfo()
if inspect.ismodule(self.mod):
for c, cls in inspect.getmembers(self.mod):
# printif(c, cls)
if c == '__all__':
self.info['module'].extend(cls)
else:
if inspect.ismodule(cls):
key = 'module'
else:
if inspect.isclass(cls):
key = 'class'
else:
if inspect.isfunction(cls):
key = 'function'
else:
key = self.__gettype__(cls)
if key not in DataType.DTTYPE:
key = DataType.DT_OTHERS
self.info[key].append(c)
self.info['module'] = list(set(self.info['module']))
self.info['module'].sort()
return self.delEmpty()
class PathInfo:
SEP = '.'
def __init__(self, path=''):
self.clname = ''
self.modname = ''
self.FullName = ''
self.FullPath = ''
self.othname = ''
self.othtype = ''
self.lstpath = []
self.lstname = []
if path and (not path.isspace()):
self.setpath(path)
@staticmethod
def deltype(lst):
tl = []
for c in lst:
if c not in DataType.DTTYPE:
tl.append(c)
return tl
def setpath(self, path):
self.FullPath = path
self.lstpath = self.FullPath.split(self.SEP)
self.lstname = PathInfo.deltype(self.lstpath)
self.FullName = self.SEP.join(self.lstname)
tm = self.lstpath.copy()
tm.reverse()
if DataType.DT_MODULE in tm:
mod = tm[tm.index(DataType.DT_MODULE) - 1:]
mod.reverse()
mod = PathInfo.deltype(mod)
else:
mod=[]
if DataType.DT_CLASS in tm:
cls = tm[tm.index(DataType.DT_CLASS) - 1:tm.index(DataType.DT_MODULE) - 1]
cls.reverse()
cls = PathInfo.deltype(cls)
#print(cls)
else:
cls=[]
othname = tm[0]
self.modname = self.SEP.join(mod)
self.clname = self.SEP.join(cls)
self.othname = othname
if len(tm)==1 :
self.othtype = DataType.DT_MODULE
else:
self.othtype=tm[1]
class View(QWidget, Ui_myinfo):
def __init__(self):
super().__init__()
self.setupUi(self)
self.txtInput.setText('PySide6')
self.txtSearch.setText('File')
self.lstLines=[]
self.tvInfo.setHeaderHidden(True)
self.setWindowTitle('获取模块信息')
# item = QTreeWidgetItem(['root'])
# self.tvInfo.addTopLevelItem(item)
# self.viewinfo(info)
self.bind()
def bind(self):
self.cmdSubmit.clicked.connect(self.on_cmd_clicked)
self.tvInfo.doubleClicked.connect(self.on_db_clicked)
self.tvInfo.clicked.connect(self.on_tv_clicked)
self.cmdExit.clicked.connect(self.exit)
self.cmdfile.clicked.connect(self.savetofile)
self.cmdSearch.clicked.connect(self.search)
def printitem(self,item:QTreeWidgetItem):
indent=len(self.getFullPath(item).split('.'))
self.lstLines.append(' '*(indent-1)+item.text(0)+'\n')
for i in range(item.childCount()):
self.printitem(item.child(i))
@Slot()
def savetofile(self):
filename, filter = QFileDialog.getSaveFileName(self, '保存文件', os.getcwd(), filter='文本文件(*.txt)')
if filename:
with open(filename, 'w') as f:
item = self.tvInfo.topLevelItem(0)
# f.writelines()
self.lstLines.clear()
self.printitem(item)
f.writelines(self.lstLines)
f.close()
@Slot()
def search(self):
self.lstDetail.clear()
if self.txtSearch.text == '':
return
it = QTreeWidgetItemIterator(self.tvInfo)
searchstr = self.txtSearch.text()
# print(it)
while it:
item = it.value()
# print(item.text(0))
# time.sleep(30)
if searchstr.lower() in item.text(0).lower():
self.lstDetail.addItem(self.FullPath(item))
next(it)
@Slot()
def exit(self):
self.close()
@Slot()
def on_tv_clicked(self):
# self.getinfo(self.tvInfo.currentItem())
pass
@Slot()
def on_cmd_clicked(self):
self.viewinfo()
# 当双击模块名称时,在当前模块下追加模块相关信息
def getFullPath(self, item: QTreeWidgetItem, column_no=0):
texts = []
while item:
texts.append(item.text(column_no))
item = item.parent()
texts.reverse()
return '.'.join(texts)
def getFullName(self, item: QTreeWidgetItem, column_no=0):
if item.text(0) in DataType.DTTYPE:
return '', ''
if item.parent().text(column_no) == DataType.DT_MODULE:
clsname = ''
modname = item.text(column_no)
else:
clsname = item.text(column_no)
modname = ''
texts = []
item = item.parent()
while item is not None:
if item.text(0) in DataType.DTTYPE:
item = item.parent()
continue
texts.append(item.text(0))
item = item.parent()
texts.reverse()
if not (modname == ''):
# print(texts)
texts.append(modname)
return '.'.join(texts), clsname
def getinfo(self, item: QTreeWidgetItem):
# print(item.text(0))
# print(item.parent)
modname, clsname = self.getFullName(item)
if item.parent().text(0) == DataType.DT_MODULE:
# print('module')
return Modinfo(modname, clsname).getinfo()
else:
if item.parent().text(0) == DataType.DT_CLASS:
return Modinfo(modname, clsname).getClassInfo()
@Slot()
def on_db_clicked(self):
curitem = self.tvInfo.currentItem()
fpath = self.getFullPath(curitem)
# 如果是类或是模块,则生成信息增加到列表中
if curitem.parent() and (curitem.text(0) not in DataType.DTTYPE) and (
curitem.parent().text(0) in DataType.DTDBTYPE):
if self.tvInfo.currentItem().childCount() > 0: return
if self.tvInfo.currentItem().text(0) == '__class__': return
info = self.getinfo(curitem)
if info == '': return
for key, values in info.items():
item = QTreeWidgetItem([key])
curitem.addChild(item)
for value in values:
child = QTreeWidgetItem([value])
item.addChild(child)
self.display(fpath)
# 在列表显示详细信息
def display(self, fpath):
pathinfo = PathInfo(fpath)
if pathinfo.othname in DataType.DTTYPE:
return
self.lstDetail.clear()
self.lstDetail.addItem('当前名称:' + pathinfo.othname)
self.lstDetail.addItem('全路径:' + pathinfo.FullPath)
self.lstDetail.addItem('全名称:' + pathinfo.FullName)
self.lstDetail.addItem('类型:' + pathinfo.othtype)
self.lstDetail.addItem('类型详细:')
self.lstDetail.addItem('所在模块:' + pathinfo.modname)
self.lstDetail.addItem('所在类:' + pathinfo.clname)
self.lstDetail.addItem('子结点:')
# 显示模块信息列表
def viewinfo(self):
name = self.txtInput.text()
# print(name)
if name == '':
QMessageBox(QMessageBox.Information, '信息', '请输入模块名称:').exec()
self.txtInput.setFocus()
return
self.tvInfo.clear()
info = Modinfo(self.txtInput.text()).getinfo()
self.tvInfo.addTopLevelItem(QTreeWidgetItem([name]))
items = []
root = self.tvInfo.topLevelItem(0)
# print(root, type(root))
for key, values in info.items():
item = QTreeWidgetItem([key])
root.addChild(item)
for value in values:
child = QTreeWidgetItem([value])
item.addChild(child)
# items.append(item)
# print(items[0].text(1))
# self.tvInfo.insertTopLevelItem(0,root)
# self.tvInfo.insertTopLevelItems(0, items)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = View()
window.show()
sys.exit(app.exec())
本文介绍了使用PySide6和Qt Designer创建图形界面,并通过inspect获取模块信息展示在QTreeWidget中的过程。详细讲述了设置图形设计工具、界面布局、运行界面、设置信号与槽,以及如何动态导入模块并展示其内容。最后给出了完整源代码。
14





