代码拉取完成,页面将自动刷新
同步操作将从 终點起點/PySide6-UI-Demo 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
import sys
import os
import datetime
import traceback
import six
from six import exec_
import builtins
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
from CodeEditor import CodeEditor
currentdir = os.path.split(os.path.abspath(sys.argv[0]))[0]
class ModuleDictWrapper(object):
"""Emulates a module with a dynamically compiled __dict__"""
def __init__(self, dict):
self.dict = dict
def __getattr__(self, name):
if name in self.dict:
return self.dict[name]
else:
raise AttributeError
class DemoError(object):
"""Wraps and stores information about the current exception"""
def __init__(self, exc_info):
import copy
excType, excValue = exc_info[:2]
# traceback list entries: (filename, line number, function name, text)
self.traceback = traceback.extract_tb(exc_info[2])
# --Based on traceback.py::format_exception_only()--
if isinstance(excType, type):
self.exception_type = excType.__name__
else:
self.exception_type = excType
# If it's a syntax error, extra information needs
# to be added to the traceback
if excType is SyntaxError:
try:
msg, (filename, lineno, self.offset, line) = excValue
except:
pass
else:
if not filename:
filename = "<string>"
line = line.strip()
self.traceback.append( (filename, lineno, "", line) )
excValue = msg
try:
self.exception_details = str(excValue)
except:
self.exception_details = "<unprintable %s object>" & type(excValue).__name__
del exc_info
def __str__(self):
ret = "Type %s \n \
Traceback: %s \n \
Details : %s" % ( str(self.exception_type), str(self.traceback), self.exception_details )
return ret
class DemoModules(object):
"""
Dynamically manages the original/modified versions of a demo module
"""
def __init__(self, demoName):
self.name = demoName
self.fileName = f"{currentdir}/{demoName}.py"
# (dict , source , filename , description , error information )
self.modules = [dict(), "" , "" , "<original>" , None]
self.modules[0]['__file__'] = self.fileName
# load original module
self.LoadFromFile(self.fileName)
def LoadFromFile(self, filename):
self.modules[2] = filename
with open(filename, "rt") as file_:
self.LoadFromSource(file_.read())
def LoadFromSource(self, source):
self.modules[1] = source
self.LoadDict()
def LoadDict(self):
if self.name != __name__:
source = self.modules[1]
description = self.modules[2]
if six.PY2:
description = description.encode(sys.getfilesystemencoding())
try:
code = compile(source, description, "exec")
exec_(code, self.modules[0])
except:
self.modules[4] = DemoError(sys.exc_info())
self.modules[0] = None
else:
self.modules[4] = None
def GetActive(self):
dict = self.modules[0]
if dict is None:
return None
else:
return ModuleDictWrapper(dict)
def GetSource(self):
return self.modules[1]
def GetFilename(self):
return self.modules[2]
def GetErrorInfo(self):
return self.modules[4]
def Delete(self):
self.modules[0] = None
self.modules[1] = ""
self.modules[2] = ""
self.modules[3] = ""
self.modules[4] = None
class MainWindow(QMainWindow):
__title__ = 'PySide6 Demos'
__treeData__ = [('Layouts',['HBoxLayout', 'VBoxLayout', 'GridLayout', 'FormLayout','StackedLayout']),
('Buttons',['PushButton', 'CheckBox', 'RadioButton', 'ToolButton', 'CommandLikButton',]),
('Input Widgets',['ComboBox','FontComboBox','LineEdit','TextEdit','PlainTextEdit','SpinBox','DobleSpinBox','TimeEdit','DateEdit','DateTimeEdit','Dial','ScrollBar','Slider','KeySequenceEdit']),
('Item Widgets',['ListWidget','TreeWidget','TableWidget']),
('Item Views',['ListView','TreeView','TableView','ColumnView']),
('Models',['StringListModel','StandardItemModel','FileSystemModel','SqlQueryModel','SqlTableModel','SqlRelationalTableModel','SortFilterProxyModel','CustomTableModel']),
('Containers',['GroupBox','ScrollArea','ToolBox','TabWidget','StackedWidget','Frame','MDIArea','DockWidget']),
('Display Widgets',['Label','TextBrowser','GraphicsView','CalendarWidget','LCDNumber','ProgressBar','Line','QML']),
('Dialogs',['Dialog','MessageBox','ColorDialog','FontDialog','FileDialog','InputDialog','ProgressDialog']),
('Charts',['BarChart','LineChart','DateTimeAxis']),
('Others',['XML','SQL','TCP','UDP','BrushStyle','Clipboard'])]
dataModel = QStandardItemModel()
def __init__(self):
super(MainWindow,self).__init__()
self.codePage = None
self.demoPage = None
self.setWindowIcon(QIcon(f"{currentdir}/resources/pyside_icon.ico"))
self.setWindowTitle(self.__title__)
splitter = QSplitter(Qt.Orientation.Horizontal)
splitter.setChildrenCollapsible(False)
leftWidget = QWidget()
leftLayout = QVBoxLayout()
#左侧树
self.treeView = QTreeView()
self.treeView.setStyleSheet('background-color: #ffffff;')
self.treeView.setEditTriggers(QTreeView.EditTrigger.NoEditTriggers)
self.treeView.clicked.connect(self.OnTreeClicked)
self.treeView.setModel(self.dataModel)
self.dataModel.setHorizontalHeaderLabels([self.__title__])
self.searchTxt = QLineEdit()
self.searchTxt.textChanged.connect(self.__initTree__)
leftLayout.addWidget(self.treeView)
leftLayout.addWidget(QLabel('Filter Demos:'))
leftLayout.addWidget(self.searchTxt)
leftWidget.setLayout(leftLayout)
#右上代码及展示
rightTopWidget = QWidget()
rightTopLayout = QVBoxLayout()
self.tabWidget = QTabWidget()
self.codePage = CodeEditor()
self.tabWidget.addTab(self.codePage,"Demo Code")
rightTopLayout.addWidget(self.tabWidget)
rightTopWidget.setLayout(rightTopLayout)
#右下消息
rightBottomWidget = QWidget()
rightBottomLayout = QVBoxLayout()
self.messageTxt = QTextEdit()
self.messageTxt.setStyleSheet('background-color:#ffffff;')
self.messageTxt.setReadOnly(True)
rightBottomLayout.addWidget(QLabel("Demo Message:"))
rightBottomLayout.addWidget(self.messageTxt)
rightBottomWidget.setLayout(rightBottomLayout)
splitterRight = QSplitter(Qt.Orientation.Vertical)
splitterRight.setChildrenCollapsible(False)
splitterRight.addWidget(rightTopWidget)
splitterRight.addWidget(rightBottomWidget)
splitterRight.setStretchFactor(0,8)
splitterRight.setStretchFactor(1,2)
splitter.addWidget(leftWidget)
splitter.addWidget(splitterRight)
splitter.setStretchFactor(0,2)
splitter.setStretchFactor(1,8)
self.setCentralWidget(splitter)
self.__initTree__()
def __initTree__(self):
'''初始化树'''
self.dataModel.removeRows(0,self.dataModel.rowCount())
root = self.dataModel.invisibleRootItem()
keyword = str(self.searchTxt.text())
for category, items in self.__treeData__:
if keyword:
items = [item for item in items if keyword.lower() in item.lower()]
if items:
categoryItem = QStandardItem(category)
root.appendRow(categoryItem)
for child in items:
categoryItem.appendRow(QStandardItem(child))
#self.treeView.expandAll()#展开所有
self.treeView.expand(self.treeView.model().index(0,0))#默认只展开第1个
def __getTabByName__(self,tabName):
'''根据名字获取Tab'''
for i in range(self.tabWidget.count()):
if tabName == self.tabWidget.tabText(i):
return i
return -1
def getAppDir(self):
return currentdir
def OnTreeClicked(self,index):
'''树点击事件,加载代码及示例'''
currentItem = self.dataModel.itemFromIndex(index)
if currentItem.hasChildren() == False:
name = str(currentItem.text())
self.OnShowMessage(f'clicked {name}')
self.OnLoadDemo(name)
def OnShowMessage(self,msg):
'''显示日志'''
self.messageTxt.append(f'{datetime.datetime.now().strftime("%H:%M:%S.%f")} {msg}')
def OnLoadDemo(self,demoName):
'''加载示例及代码'''
tmpIndex = self.tabWidget.currentIndex()
self.codePage.setText('')
self.demoPage = None
if self.tabWidget.count() == 2:
self.tabWidget.removeTab(1)
fileName = f'{currentdir}/{demoName}.py'
if os.path.exists(fileName) == False:
return
self.OnShowMessage(f'Loading demo code {demoName}.py...')
self.codePage.setText( open(fileName,'r').read())
self.demoModules = DemoModules(demoName)
self.OnShowMessage(f'Running demo {demoName}...')
#demo 标签页,每次移除新建
module = self.demoModules.GetActive()
self.demoPage = module.runDemo(self)
self.tabWidget.addTab(self.demoPage,"Demo")
self.tabWidget.setCurrentIndex(tmpIndex)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。