Initial commit

This commit is contained in:
Jcen 2024-10-04 12:37:45 +08:00
parent 3a26c132fb
commit f6c8fac77f
10 changed files with 916 additions and 0 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

8
.idea/PyQt_Lesson.iml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13 (project (3)) (2)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (project (3)) (2)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/PyQt_Lesson.iml" filepath="$PROJECT_DIR$/.idea/PyQt_Lesson.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

362
lesson1/动态layout.py Normal file
View File

@ -0,0 +1,362 @@
# -*- coding: utf-8 -*-
import os
import sys
from PyQt5.QtCore import pyqtSlot, Qt
# from PyQt5.QtGui import Q
from PyQt5.QtWidgets import QHBoxLayout, QDockWidget, QMainWindow, QListWidget, QTextEdit, QPushButton, QApplication, \
QWidget, QToolBar, QAction, QVBoxLayout, QMenu, QLineEdit, QLabel
from PyQt5.QtCore import Qt, QSettings
from PyQt5.QtCore import QByteArray
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.dock_widgets = {} # 存储QDockWidget的字典
self.object = []
self.initUI()
def initUI(self):
self.setWindowTitle("DockWidget Example")
self.setGeometry(100, 100, 800, 600)
self.setDockNestingEnabled(True)
# 加载布局
self.loadLayout()
def add(self, text):
# 创建三个QDockWidget
dock1 = QDockWidget(text, self)
# 设置QDockWidget的特性
dock1.setFeatures(
QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable)
# 创建QTextEdit作为QDockWidget的内容
text_edit = QWidget()
text_edit1 = QLabel()
text_edit1.setText('sdfdsfdsafdsfdsa')
text_edit11 = QVBoxLayout()
text_edit11.addWidget(text_edit1)
text_edit.setLayout(text_edit11)
# 将QTextEdit添加到QDockWidget中
dock1.setWidget(text_edit1)
# 将QDockWidget添加到主窗口中
self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
if self.object:
# 设置QDockWidget的叠加摆放
self.tabifyDockWidget(self.object[-1], dock1)
else:
self.object.append(dock1)
print(self.object)
self.dock_widgets[text] = dock1
def save_layout(self):
try:
p = 'layout1.ini'
with open(p, 'wb') as f:
s = self.saveState()
f.write(s)
# 创建QSettings对象用于保存布局设置
settings = QSettings("layout.ini", QSettings.IniFormat)
# 保存当前的布局设置
settings.setValue("mainWindow/geometry", self.saveGeometry())
settings.setValue("mainWindow/state", self.saveState())
# 保存QDockWidget的信息
settings.beginGroup("dockWidgets")
for name, dock in self.dock_widgets.items():
settings.setValue(name + "/geometry", dock.saveGeometry())
settings.endGroup()
except Exception as e:
print("保存布局时出错:", e)
def createDockWidget(self, name):
# 创建一个QDockWidget
dock = QDockWidget(name, self)
dock.setObjectName(name)
# 设置QDockWidget的特性
dock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable)
# 创建QTextEdit作为QDockWidget的内容
text_edit = QTextEdit()
dock.setWidget(text_edit)
# 将QDockWidget添加到字典中
self.dock_widgets[name] = dock
def loadLayout(self):
# 创建QSettings对象用于加载布局设置
settings = QSettings("layout.ini", QSettings.IniFormat)
# 加载之前保存的布局设置
self.restoreGeometry(settings.value("mainWindow/geometry", self.saveGeometry()))
self.restoreState(settings.value("mainWindow/state", self.saveState()))
# 加载QDockWidget的信息
settings.beginGroup("dockWidgets")
dock_names = settings.childGroups()
for s, name in enumerate(dock_names):
self.createDockWidget(name)
dock = self.dock_widgets[name]
dock.restoreGeometry(settings.value(name + "/geometry", dock.saveGeometry()))
self.addDockWidget(Qt.LeftDockWidgetArea, dock) # 将QDockWidget添加到主窗口中
self.restoreState(self.saveState())
settings.endGroup()
p = 'layout1.ini'
if os.path.exists(p):
with open(p, 'rb') as f:
s = f.read()
self.restoreState(s)
class widget(QWidget):
def __init__(self):
super(widget, self).__init__()
self.L = QHBoxLayout()
self.setLayout(self.L)
self.A = MainWindow()
self.P = QPushButton('add')
self.Ps = QPushButton('save')
self.Lo = QPushButton('lo')
self.name = QLineEdit()
self.L.addWidget(self.name)
self.L.addWidget(self.A)
self.L.addWidget(self.P)
self.L.addWidget(self.Ps)
self.L.addWidget(self.Lo)
self.P.clicked.connect(self.add)
self.Ps.clicked.connect(self.adds)
self.Lo.clicked.connect(self.addss)
def add(self):
self.A.add(self.name.text())
def adds(self):
self.A.save_layout()
def addss(self):
self.A.sss()
if __name__ == "__main__":
import sys
import qtmodern.styles
app = QApplication(sys.argv)
qtmodern.styles.dark(app)
mainWindow = widget()
mainWindow.show()
sys.exit(app.exec_())
from .import_qt import *
import os
from .MyDockWidget import MyDockWidget
from .util.form_class_registration import FormCalss
from util.func import quantity_recursion
import re
class InitUI(QMainWindow):
def __init__(self, parent=None):
super(InitUI, self).__init__(parent)
self.dock_widgets = {} # 存储QDockWidget的字典
self.initUI()
# self.setStyleSheet_func()
# 创建一个动作,用于保存布局设置
save_layout_action = QAction("Save Layout", self)
save_layout_action.triggered.connect(self.save_layout)
# 创建一个动作,用于加载布局设置
load_layout_action = QAction("Load Layout", self)
load_layout_action.triggered.connect(self.load_layout)
# 创建一个动作,用于加载布局设置
create_action = QAction("create", self)
create_action.triggered.connect(self.create_action_func)
# 将动作添加到菜单栏
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(save_layout_action)
file_menu.addAction(load_layout_action)
file_menu.addAction(create_action)
# 将动作添加到菜单栏
self.tool_menu = self.menuBar().addMenu("tool")
self.init_tool()
def init_tool(self):
import functools
for i in FormCalss.FormDict:
create_action = QAction(i, self)
self.tool_menu.addAction(create_action)
create_action.triggered.connect(functools.partial(self.create_action_func, i))
def create_action_func(self, name):
widget = {'type': name, 'text': ''}
try:
FormCalss.form_class_dict[widget['type']]
except:
FormCalss.form_class_dict[widget['type']] = []
if FormCalss.form_class_dict[widget['type']] != []:
widgetList = FormCalss.form_class_dict[widget['type']]
widgetNameList = [i.objectName() for i in widgetList]
widget['text'] = quantity_recursion(1, widgetNameList)
else:
widget = {'type': name, 'text': '%s1' % name}
widgets = FormCalss.FormDict[widget['type']]()
widgets.setObjectName(widget['text'])
self.addTest(widgets, text=widget['text'])
FormCalss.add_form_class(widgets, widget['type'])
print(FormCalss.form_class_dict)
def addTest(self, widget, text):
# 创建三个QDockWidget
result = re.sub(r'\d+', '', text)
dock1 = MyDockWidget(text, self, type=result)
# 将QTextEdit添加到QDockWidget中
dock1.setWidget(widget)
# 将QDockWidget添加到主窗口中
self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
self.dock_widgets[text] = dock1
def setStyleSheet_func(self):
StyleSheet = """
background-color: rgb(50, 50, 50);
"""
self.setStyleSheet(StyleSheet)
def initUI(self):
self.setWindowTitle("DockWidget Example")
self.setGeometry(100, 100, 800, 600)
self.setDockNestingEnabled(True)
# 加载布局
self.load_layout()
# def add(self, text):
# # 创建三个QDockWidget
# dock1 = QDockWidget(text, self)
# # 设置QDockWidget的特性
# dock1.setFeatures(
# QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable)
# # 创建QTextEdit作为QDockWidget的内容
# text_edit = QWidget()
# text_edit1 = QLabel()
# text_edit1.setText('sdfdsfdsafdsfdsa')
# text_edit11 = QVBoxLayout()
# text_edit11.addWidget(text_edit1)
# text_edit.setLayout(text_edit11)
# # 将QTextEdit添加到QDockWidget中
# dock1.setWidget(text_edit1)
#
# # 将QDockWidget添加到主窗口中
# self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
#
# if self.object:
# # 设置QDockWidget的叠加摆放
# self.tabifyDockWidget(self.object[-1], dock1)
# else:
# self.object.append(dock1)
# self.dock_widgets[text] = dock1
def save_layout(self):
try:
try:
os.remove('layout1.ini')
except:
try:
os.remove('layout.ini')
except Exception as e:
print(e, 'save')
pass
p = 'layout1.ini'
with open(p, 'wb') as f:
s = self.saveState()
f.write(s)
# 创建QSettings对象用于保存布局设置
settings = QSettings("layout.ini", QSettings.IniFormat)
# 保存当前的布局设置
settings.setValue("mainWindow/geometry", self.saveGeometry())
settings.setValue("mainWindow/state", self.saveState())
# 保存QDockWidget的信息
settings.beginGroup("dockWidgets")
for name, dock in self.dock_widgets.items():
settings.setValue(name + "/geometry", dock.saveGeometry())
settings.endGroup()
except Exception as e:
print("保存布局时出错:", e)
self.w = QWidget()
self.w.setWindowFlags(Qt.WindowStaysOnTopHint)
reply = QMessageBox.question(self.w, '信息', '保存预设成功', QMessageBox.Cancel)
if reply == QMessageBox.Cancel:
return
def createDockWidget(self, name):
result = re.sub(r'\d+', '', name)
widget_object = FormCalss.FormDict[result]()
widget_object.setObjectName(name)
# 创建一个QDockWidget
dock = MyDockWidget(name, self, type=result)
# 创建QTextEdit作为QDockWidget的内容
dock.setWidget(widget_object)
widget = {'type': result, 'text': ''}
try:
FormCalss.form_class_dict[widget['type']]
except:
FormCalss.form_class_dict[widget['type']] = []
if FormCalss.form_class_dict[widget['type']] != []:
widgetList = FormCalss.form_class_dict[widget['type']]
widgetNameList = [i.objectName() for i in widgetList]
widget['text'] = quantity_recursion(1, widgetNameList)
else:
widget = {'type': result, 'text': '%s1' % result}
FormCalss.add_form_class(widget_object, widget['type'])
print(FormCalss.form_class_dict)
# 将QDockWidget添加到字典中
self.dock_widgets[name] = dock
def load_layout(self):
# 创建QSettings对象用于加载布局设置
settings = QSettings("layout.ini", QSettings.IniFormat)
# 加载之前保存的布局设置
self.restoreGeometry(settings.value("mainWindow/geometry", self.saveGeometry()))
self.restoreState(settings.value("mainWindow/state", self.saveState()))
# 加载QDockWidget的信息
settings.beginGroup("dockWidgets")
dock_names = settings.childGroups()
for s, name in enumerate(dock_names):
self.createDockWidget(name)
dock = self.dock_widgets[name]
dock.restoreGeometry(settings.value(name + "/geometry", dock.saveGeometry()))
self.addDockWidget(Qt.LeftDockWidgetArea, dock) # 将QDockWidget添加到主窗口中
self.restoreState(self.saveState())
settings.endGroup()
p = 'layout1.ini'
if os.path.exists(p):
with open(p, 'rb') as f:
s = f.read()
self.restoreState(s)
for i in self.findChildren(QDockWidget):
if i.isHidden():
settings = QSettings("layout.ini", QSettings.IniFormat)
settings.remove("dockWidgets/" + i.objectName() + "/geometry")

View File

@ -0,0 +1,385 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: jyroy
import sys
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt, pyqtSignal, QPoint
from PyQt5.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel,QSpacerItem, QSizePolicy, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit
# from LeftTabWidget import LeftTabWidget
# 样式
StyleSheet = """
/*标题栏*/
TitleBar {
background-color: red;
}
/*最小化最大化关闭按钮通用默认背景*/
#buttonMinimum,#buttonMaximum,#buttonClose {
border: none;
background-color: red;
}
/*悬停*/
#buttonMinimum:hover,#buttonMaximum:hover {
background-color: red;
color: white;
}
#buttonClose:hover {
color: white;
}
/*鼠标按下不放*/
#buttonMinimum:pressed,#buttonMaximum:pressed {
background-color: Firebrick;
}
#buttonClose:pressed {
color: white;
background-color: Firebrick;
}
"""
class TitleBar(QWidget):
# 窗口最小化信号
windowMinimumed = pyqtSignal()
# 窗口最大化信号
windowMaximumed = pyqtSignal()
# 窗口还原信号
windowNormaled = pyqtSignal()
# 窗口关闭信号
windowClosed = pyqtSignal()
# 窗口移动
windowMoved = pyqtSignal(QPoint)
def __init__(self, *args, **kwargs):
super(TitleBar, self).__init__(*args, **kwargs)
# 支持qss设置背景
self.setAttribute(Qt.WA_StyledBackground, True)
self.mPos = None
self.iconSize = 20 # 图标的默认大小
# 设置默认背景颜色,否则由于受到父窗口的影响导致透明
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(palette.Window, QColor(240, 240, 240))
self.setPalette(palette)
# 布局
layout = QHBoxLayout(self, spacing=0)
layout.setContentsMargins(0, 0, 0, 0)
# 窗口图标
self.iconLabel = QLabel(self)
# self.iconLabel.setScaledContents(True)
layout.addWidget(self.iconLabel)
# 窗口标题
self.titleLabel = QLabel(self)
self.titleLabel.setMargin(2)
layout.addWidget(self.titleLabel)
# 中间伸缩条
layout.addSpacerItem(QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
# 利用Webdings字体来显示图标
font = self.font() or QFont()
font.setFamily('Webdings')
# 最小化按钮
self.buttonMinimum = QPushButton(
'0', self, clicked=self.windowMinimumed.emit, font=font, objectName='buttonMinimum')
layout.addWidget(self.buttonMinimum)
# 最大化/还原按钮
self.buttonMaximum = QPushButton(
'1', self, clicked=self.showMaximized, font=font, objectName='buttonMaximum')
layout.addWidget(self.buttonMaximum)
# 关闭按钮
self.buttonClose = QPushButton(
'r', self, clicked=self.windowClosed.emit, font=font, objectName='buttonClose')
layout.addWidget(self.buttonClose)
# 初始高度
self.setHeight()
def showMaximized(self):
if self.buttonMaximum.text() == '1':
# 最大化
self.buttonMaximum.setText('2')
self.windowMaximumed.emit()
else: # 还原
self.buttonMaximum.setText('1')
self.windowNormaled.emit()
def setHeight(self, height=38):
"""设置标题栏高度"""
self.setMinimumHeight(height)
self.setMaximumHeight(height)
# 设置右边按钮的大小
self.buttonMinimum.setMinimumSize(height, height)
self.buttonMinimum.setMaximumSize(height, height)
self.buttonMaximum.setMinimumSize(height, height)
self.buttonMaximum.setMaximumSize(height, height)
self.buttonClose.setMinimumSize(height, height)
self.buttonClose.setMaximumSize(height, height)
def setTitle(self, title):
"""设置标题"""
self.titleLabel.setText(title)
def setIcon(self, icon):
"""设置图标"""
self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize))
def setIconSize(self, size):
"""设置图标大小"""
self.iconSize = size
def enterEvent(self, event):
self.setCursor(Qt.ArrowCursor)
super(TitleBar, self).enterEvent(event)
def mouseDoubleClickEvent(self, event):
super(TitleBar, self).mouseDoubleClickEvent(event)
self.showMaximized()
def mousePressEvent(self, event):
"""鼠标点击事件"""
if event.button() == Qt.LeftButton:
self.mPos = event.pos()
event.accept()
def mouseReleaseEvent(self, event):
'''鼠标弹起事件'''
self.mPos = None
event.accept()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton and self.mPos:
self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos))
event.accept()
# 枚举左上右下以及四个定点
Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(8)
class FramelessWindow(QWidget):
# 四周边距
Margins = 5
def __init__(self, *args, **kwargs):
super(FramelessWindow, self).__init__(*args, **kwargs)
self._pressed = False
self.Direction = None
# 背景透明
self.setAttribute(Qt.WA_TranslucentBackground, True)
# 无边框
self.setWindowFlags(Qt.FramelessWindowHint) # 隐藏边框
# 鼠标跟踪
self.setMouseTracking(True)
# 布局
layout = QVBoxLayout(self, spacing=0)
# 预留边界用于实现无边框窗口调整大小
layout.setContentsMargins(
self.Margins, self.Margins, self.Margins, self.Margins)
# 标题栏
self.titleBar = TitleBar(self)
layout.addWidget(self.titleBar)
# 信号槽
self.titleBar.windowMinimumed.connect(self.showMinimized)
self.titleBar.windowMaximumed.connect(self.showMaximized)
self.titleBar.windowNormaled.connect(self.showNormal)
self.titleBar.windowClosed.connect(self.close)
self.titleBar.windowMoved.connect(self.move)
self.windowTitleChanged.connect(self.titleBar.setTitle)
self.windowIconChanged.connect(self.titleBar.setIcon)
def setTitleBarHeight(self, height=38):
"""设置标题栏高度"""
self.titleBar.setHeight(height)
def setIconSize(self, size):
"""设置图标的大小"""
self.titleBar.setIconSize(size)
def setWidget(self, widget):
"""设置自己的控件"""
if hasattr(self, '_widget'):
return
self._widget = widget
# 设置默认背景颜色,否则由于受到父窗口的影响导致透明
self._widget.setAutoFillBackground(True)
palette = self._widget.palette()
palette.setColor(palette.Window, QColor(240, 240, 240))
self._widget.setPalette(palette)
self._widget.installEventFilter(self)
self.layout().addWidget(self._widget)
def move(self, pos):
if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen:
# 最大化或者全屏则不允许移动
return
super(FramelessWindow, self).move(pos)
def showMaximized(self):
"""最大化,要去除上下左右边界,如果不去除则边框地方会有空隙"""
super(FramelessWindow, self).showMaximized()
self.layout().setContentsMargins(0, 0, 0, 0)
def showNormal(self):
"""还原,要保留上下左右边界,否则没有边框无法调整"""
super(FramelessWindow, self).showNormal()
self.layout().setContentsMargins(
self.Margins, self.Margins, self.Margins, self.Margins)
def eventFilter(self, obj, event):
"""事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式"""
if isinstance(event, QEnterEvent):
self.setCursor(Qt.ArrowCursor)
return super(FramelessWindow, self).eventFilter(obj, event)
def paintEvent(self, event):
"""由于是全透明背景窗口,重绘事件中绘制透明度为1的难以发现的边框,用于调整窗口大小"""
super(FramelessWindow, self).paintEvent(event)
painter = QPainter(self)
painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.Margins))
painter.drawRect(self.rect())
def mousePressEvent(self, event):
"""鼠标点击事件"""
super(FramelessWindow, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
self._mpos = event.pos()
self._pressed = True
def mouseReleaseEvent(self, event):
'''鼠标弹起事件'''
super(FramelessWindow, self).mouseReleaseEvent(event)
self._pressed = False
self.Direction = None
def mouseMoveEvent(self, event):
"""鼠标移动事件"""
super(FramelessWindow, self).mouseMoveEvent(event)
pos = event.pos()
xPos, yPos = pos.x(), pos.y()
wm, hm = self.width() - self.Margins, self.height() - self.Margins
if self.isMaximized() or self.isFullScreen():
self.Direction = None
self.setCursor(Qt.ArrowCursor)
return
if event.buttons() == Qt.LeftButton and self._pressed:
self._resizeWidget(pos)
return
if xPos <= self.Margins and yPos <= self.Margins:
# 左上角
self.Direction = LeftTop
self.setCursor(Qt.SizeFDiagCursor)
elif wm <= xPos <= self.width() and hm <= yPos <= self.height():
# 右下角
self.Direction = RightBottom
self.setCursor(Qt.SizeFDiagCursor)
elif wm <= xPos and yPos <= self.Margins:
# 右上角
self.Direction = RightTop
self.setCursor(Qt.SizeBDiagCursor)
elif xPos <= self.Margins and hm <= yPos:
# 左下角
self.Direction = LeftBottom
self.setCursor(Qt.SizeBDiagCursor)
elif 0 <= xPos <= self.Margins and self.Margins <= yPos <= hm:
# 左边
self.Direction = Left
self.setCursor(Qt.SizeHorCursor)
elif wm <= xPos <= self.width() and self.Margins <= yPos <= hm:
# 右边
self.Direction = Right
self.setCursor(Qt.SizeHorCursor)
elif self.Margins <= xPos <= wm and 0 <= yPos <= self.Margins:
# 上面
self.Direction = Top
self.setCursor(Qt.SizeVerCursor)
elif self.Margins <= xPos <= wm and hm <= yPos <= self.height():
# 下面
self.Direction = Bottom
self.setCursor(Qt.SizeVerCursor)
def _resizeWidget(self, pos):
"""调整窗口大小"""
if self.Direction == None:
return
mpos = pos - self._mpos
xPos, yPos = mpos.x(), mpos.y()
geometry = self.geometry()
x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height()
if self.Direction == LeftTop: # 左上角
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
elif self.Direction == RightBottom: # 右下角
if w + xPos > self.minimumWidth():
w += xPos
self._mpos = pos
if h + yPos > self.minimumHeight():
h += yPos
self._mpos = pos
elif self.Direction == RightTop: # 右上角
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
if w + xPos > self.minimumWidth():
w += xPos
self._mpos.setX(pos.x())
elif self.Direction == LeftBottom: # 左下角
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
if h + yPos > self.minimumHeight():
h += yPos
self._mpos.setY(pos.y())
elif self.Direction == Left: # 左边
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
else:
return
elif self.Direction == Right: # 右边
if w + xPos > self.minimumWidth():
w += xPos
self._mpos = pos
else:
return
elif self.Direction == Top: # 上面
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
else:
return
elif self.Direction == Bottom: # 下面
if h + yPos > self.minimumHeight():
h += yPos
self._mpos = pos
else:
return
self.setGeometry(x, y, w, h)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self, spacing=0)
layout.setContentsMargins(0, 0, 0, 0)
# self.left_tag = LeftTabWidget()
# layout.addWidget(self.left_tag)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
mainWnd = FramelessWindow()
mainWnd.setWindowTitle('测试标题栏')
mainWnd.setWindowIcon(QIcon('Qt.ico'))
mainWnd.resize(QSize(1250,780))
mainWnd.setWidget(MainWindow(mainWnd)) # 把自己的窗口添加进来
mainWnd.show()
sys.exit(app.exec_())

119
lesson1/流式布局.py Normal file
View File

@ -0,0 +1,119 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, QWidget)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
flowLayout = FlowLayout()
flowLayout.addWidget(QPushButton("Short"))
flowLayout.addWidget(QPushButton("Longer"))
flowLayout.addWidget(QPushButton("Different text"))
flowLayout.addWidget(QPushButton("More text"))
flowLayout.addWidget(QPushButton("Even longer button text"))
self.setLayout(flowLayout)
self.setWindowTitle("Flow Layout")
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=0, spacing=-1):
super(FlowLayout, self).__init__(parent)
if parent is not None:
self.setContentsMargins(margin, margin, margin, margin)
self.setSpacing(spacing)
self.itemList = []
def __del__(self):
item = self.takeAt(0)
while item:
item = self.takeAt(0)
def addItem(self, item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self, index):
if index >= 0 and index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self, index):
if index >= 0 and index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self.doLayout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
margin, _, _, _ = self.getContentsMargins()
size += QSize(2 * margin, 2 * margin)
return size
def doLayout(self, rect, testOnly):
x = rect.x()
y = rect.y()
lineHeight = 0
for item in self.itemList:
wid = item.widget()
spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
QSizePolicy.PushButton, Qt.Horizontal)
spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
QSizePolicy.PushButton, Qt.Vertical)
nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > rect.right() and lineHeight > 0:
x = rect.x()
y = y + lineHeight + spaceY
nextX = x + item.sizeHint().width() + spaceX
lineHeight = 0
if not testOnly:
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
x = nextX
lineHeight = max(lineHeight, item.sizeHint().height())
return y + lineHeight - rect.y()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
mainWin = Window()
mainWin.show()
sys.exit(app.exec_())

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
code = '''def my_function(self):
print("Hello, World!")
'''
exec(code, globals())
class_obj = globals()['my_function']
# print(class_obj())
# 创建临时实例方法
self.temp_method = types.MethodType(class_obj, self)
#
# # 调用临时实例方法
self.temp_method()