同步iron

This commit is contained in:
625781186 2018-08-09 18:35:29 +08:00
commit 14bc681ee0
15 changed files with 910 additions and 73 deletions

View file

@ -11,15 +11,21 @@ encoding//PyQtChart\u7EC3\u4E60/test/LineChart\u81EA\u5B9A\u4E49xy\u8F74.py=utf-
encoding//PyQtChart\u7EC3\u4E60/test/ToolTip.py=utf-8
encoding//PyQtChart\u7EC3\u4E60/test/ToolTip2.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/ImageView.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/QGraphicsItem/Item\u62D6\u62FD\u6539\u53D8\u5927\u5C0F.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/QGraphicsItem/Item\u79FB\u52A8.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/QGraphicsItem/\u8C03\u6574.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/\u4E16\u754C\u5730\u56FE/WorldMap.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/\u6DFB\u52A0QWidget.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImagePs.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImageThread.py=utf-8
encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImageView.py=utf-8
encoding//QListView/\u663E\u793A\u81EA\u5B9A\u4E49Widget.py=utf-8
encoding//QListView/\u663E\u793A\u81EA\u5B9A\u4E49Widget\u5E76\u6392\u5E8F.py=utf-8
encoding//QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/qrctest1.py=utf-8
encoding//QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/qrctest2.py=utf-8
encoding//QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/res_rc.py=utf-8
encoding//QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/textread.py=utf-8
encoding//tmp/ListView.py=utf-8
encoding//tmp/LocalClient.py=utf-8
encoding//tmp/Material/Effect/LineEffect.py=utf-8
encoding//tmp/Material/Utils/Colors.py=utf-8
@ -29,6 +35,7 @@ encoding//tmp/Material/test/TestLineEdit.py=utf-8
encoding//tmp/QtServer.py=utf-8
encoding//tmp/error.py=utf-8
encoding//tmp/json\u751F\u6210\u6811\u5F62\u7ED3\u6784.py=utf-8
encoding//tmp/\u52A0\u8F7Dui\u63CF\u7ED8\u8FB9\u754C.py=utf-8
encoding//tmp/\u622A\u56FE\u753B\u77E9\u5F62/DrawRectangle.py=utf-8
encoding//tmp/\u7B80\u5355\u63D2\u4EF6/Widget.py=utf-8
encoding//tmp/\u8BFB\u53D6\u526A\u5207\u677F\u56FE\u7247.py=utf-8
@ -55,6 +62,7 @@ encoding//\u6570\u636E\u5E93\u67E5\u8BE2\u663E\u793A\u8868\u683C/main.py=utf-8
encoding//\u6570\u636E\u5E93\u67E5\u8BE2\u663E\u793A\u8868\u683C/mainui.py=utf-8
encoding//\u65E0\u8FB9\u6846\u81EA\u5B9A\u4E49\u6807\u9898\u680F\u7A97\u53E3/FramelessWindow.py=utf-8
encoding//\u65E0\u8FB9\u6846\u81EA\u5B9A\u4E49\u6807\u9898\u680F\u7A97\u53E3/Test.py=utf-8
encoding//\u65E0\u8FB9\u6846\u81EA\u5B9A\u4E49\u6807\u9898\u680F\u7A97\u53E3/win\u65E0\u8FB9\u6846\u8C03\u6574\u5927\u5C0F.py=utf-8
encoding//\u68A6\u5E7B\u6811/DreamTree.py=utf-8
encoding//\u6C14\u6CE1\u63D0\u793A/BubbleTips.py=utf-8
encoding//\u6D4F\u89C8\u5668\u83B7\u53D6Cookie/WebEngineView.py=utf-8

View file

@ -0,0 +1,170 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2018年7月26日
@author: Irony
@site: https://github.com/892768447
@email: 892768447@qq.com
@file: QGraphicsView练习.QGraphicsItem.Item移动
@description:
"""
from PyQt5.QtCore import Qt, QLineF, QRectF
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsView, QGraphicsScene,\
QStyle
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = "Copyright (c) 2018 Irony"
__Version__ = "Version 1.0"
class MoveableItem(QGraphicsRectItem):
def __init__(self, *args, **kwargs):
super(MoveableItem, self).__init__(*args, **kwargs)
self.setPos(0, 0)
# 可移动,可选择,有焦点,发送大小位置改变事件
self.setFlags(self.ItemIsMovable | self.ItemIsSelectable |
self.ItemIsFocusable | self.ItemSendsGeometryChanges)
# 设置接收悬停事件
self.setAcceptHoverEvents(True)
self.setBrush(QColor(247, 160, 57)) # 设置背景颜色
# 是否在调整大小的状态
self.isResizing = False
self.mousePressPos = None
self.mousePressRect = None
def paint(self, painter, option, widget):
super(MoveableItem, self).paint(painter, option, widget)
# 当鼠标选中后在边缘绘制边框
if option.state & QStyle.State_Selected:
rect = self.boundingRect()
painter.setRenderHint(QPainter.Antialiasing, True) # 抗锯齿
x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height()
if option.state & QStyle.State_HasFocus: # 有焦点
painter.setPen(QPen(Qt.red, 3)) # 设置红色画笔
# 在左上、左下、右上、右下、以及四条边上画小线段
painter.drawLines(
QLineF(x, y, x + 10, y), # 左上顶点向右
QLineF(x, y, x, y + 10), # 左上顶点向下
QLineF(x, y + h, x + 10, y + h), # 左下顶点向右
QLineF(x, y + h, x, y + h - 10), # 左下顶点向上
QLineF(x + w, y, x + w - 10, y), # 右上顶点向左
QLineF(x + w, y, x + w, y + 10), # 右上顶点向下
QLineF(x + w, y + h, x + w - 10, y + h), # 右下顶点向左
QLineF(x + w, y + h, x + w, y + h - 10) # 右下顶点向上
)
def hoverMoveEvent(self, event):
super(MoveableItem, self).hoverMoveEvent(event)
# 鼠标悬停事件,用于检测鼠标位置并改变鼠标形态
cursor = self.isInResizeArea(event.pos())
if self.isResizing or (cursor and self.isSelected()):
# 正在调整中或者鼠标在可调整区域范围内并且是选中
self.setCursor(cursor)
else:
self.setCursor(Qt.ArrowCursor)
def hoverLeaveEvent(self, event):
"""鼠标悬停离开事件恢复鼠标样式"""
super(MoveableItem, self).hoverLeaveEvent(event)
self.setCursor(Qt.ArrowCursor)
def mousePressEvent(self, event):
# 鼠标按下
super(MoveableItem, self).mousePressEvent(event)
if event.button() == Qt.LeftButton and self.isInResizeArea(event.pos()):
self.isResizing = True
self.mousePressPos = event.pos()
self.mousePressRect = self.boundingRect()
def mouseReleaseEvent(self, event):
# 鼠标释放开
super(MoveableItem, self).mouseReleaseEvent(event)
if event.button() == Qt.LeftButton and self.isResizing:
self.isResizing = False
self.mousePressPos = None
self.mousePressRect = None
self.update()
def mouseMoveEvent(self, event):
# 鼠标移动
if self.isResizing and self.mousePressPos:
rect = self.boundingRect()
pos = event.pos() - self.mousePressPos
w = pos.x()
h = pos.y()
x = -4 if w > 0 else 4
y = -4 if h > 0 else 4
print(x, y, -x, -y, pos)
self.setRect(rect.adjusted(x, y, -x, -y))
self.prepareGeometryChange()
else:
super(MoveableItem, self).mouseMoveEvent(event)
def isInResizeArea(self, pos):
# 检测判断鼠标所在位置是否为四个顶点的范围内
rect = self.boundingRect()
x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height()
lx = pos.x() < x + 10
rx = pos.x() > x + w - 10
ty = pos.y() < y + 10
by = pos.y() > y + h - 10
# 左上角和右下角
if (lx and ty) or (rx and by):
return Qt.SizeFDiagCursor
# 右上角和左下角
if (rx and ty) or (lx and by):
return Qt.SizeBDiagCursor
# 上、下
if ty or by:
return Qt.SizeVerCursor
if lx or rx:
return Qt.SizeHorCursor
# 左、右
return 0
class ImageWidget(QGraphicsView):
def __init__(self, *args, **kwargs):
super(ImageWidget, self).__init__(*args, **kwargs)
self.resize(800, 600)
# 设置背景颜色
self.setBackgroundBrush(QColor(31, 31, 47))
# 去掉滚动条
# self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# 设置变换中心为鼠标所在位置
self.setTransformationAnchor(self.AnchorUnderMouse)
# 不保证painter的状态
self.setOptimizationFlags(self.DontSavePainterState)
self.setViewportUpdateMode(self.SmartViewportUpdate)
self.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform)
# 场景
self._scene = QGraphicsScene(0, 0, self.width(), self.height())
self.setScene(self._scene)
self._scene.addItem(MoveableItem(100, 100, 200, 200))
if __name__ == '__main__':
import sys
import cgitb
sys.excepthook = cgitb.Hook(1, None, 5, sys.stderr, 'text')
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = ImageWidget()
w.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,63 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2018年7月26日
@author: Irony
@site: https://github.com/892768447
@email: 892768447@qq.com
@file: QGraphicsView练习.QGraphicsItem.Item移动
@description:
"""
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsView, QGraphicsScene
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = "Copyright (c) 2018 Irony"
__Version__ = "Version 1.0"
class MoveableItem(QGraphicsRectItem):
def __init__(self, *args, **kwargs):
super(MoveableItem, self).__init__(*args, **kwargs)
self.setFlag(self.ItemIsMovable) # 设置为可以动
self.setBrush(QColor(247, 160, 57)) # 设置背景颜色
class ImageWidget(QGraphicsView):
def __init__(self, *args, **kwargs):
super(ImageWidget, self).__init__(*args, **kwargs)
self.resize(800, 600)
# 设置背景颜色
self.setBackgroundBrush(QColor(31, 31, 47))
# 去掉滚动条
# self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# 设置变换中心为鼠标所在位置
self.setTransformationAnchor(self.AnchorUnderMouse)
# 不保证painter的状态
self.setOptimizationFlags(self.DontSavePainterState)
self.setViewportUpdateMode(self.SmartViewportUpdate)
self.setRenderHints(QPainter.Antialiasing |
QPainter.SmoothPixmapTransform)
# 场景
self._scene = QGraphicsScene()
self.setScene(self._scene)
self.setSceneRect(0, 0, self.width(), self.height())
self._scene.addItem(MoveableItem(100, 100, 200, 200))
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = ImageWidget()
w.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,294 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created on 2018年7月26日
# author: Irony
# site: https://github.com/892768447
# email: 892768447@qq.com
# file: QGraphicsView练习.QGraphicsItem.ttt
# description:
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
import sys
from PyQt5.QtCore import Qt, QRectF, QPointF
from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen, QPixmap
from PyQt5.QtWidgets import QGraphicsRectItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
class GraphicsRectItem(QGraphicsRectItem):
handleTopLeft = 1
handleTopMiddle = 2
handleTopRight = 3
handleMiddleLeft = 4
handleMiddleRight = 5
handleBottomLeft = 6
handleBottomMiddle = 7
handleBottomRight = 8
handleSize = +8.0
handleSpace = -4.0
handleCursors = {
handleTopLeft: Qt.SizeFDiagCursor,
handleTopMiddle: Qt.SizeVerCursor,
handleTopRight: Qt.SizeBDiagCursor,
handleMiddleLeft: Qt.SizeHorCursor,
handleMiddleRight: Qt.SizeHorCursor,
handleBottomLeft: Qt.SizeBDiagCursor,
handleBottomMiddle: Qt.SizeVerCursor,
handleBottomRight: Qt.SizeFDiagCursor,
}
def __init__(self, *args):
"""
Initialize the shape.
"""
super().__init__(*args)
self.handles = {}
self.handleSelected = None
self.mousePressPos = None
self.mousePressRect = None
self.setAcceptHoverEvents(True)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.updateHandlesPos()
def handleAt(self, point):
"""
Returns the resize handle below the given point.
"""
for k, v, in self.handles.items():
if v.contains(point):
return k
return None
def hoverMoveEvent(self, moveEvent):
"""
Executed when the mouse moves over the shape (NOT PRESSED).
"""
if self.isSelected():
handle = self.handleAt(moveEvent.pos())
cursor = Qt.ArrowCursor if handle is None else self.handleCursors[handle]
self.setCursor(cursor)
super().hoverMoveEvent(moveEvent)
def hoverLeaveEvent(self, moveEvent):
"""
Executed when the mouse leaves the shape (NOT PRESSED).
"""
self.setCursor(Qt.ArrowCursor)
super().hoverLeaveEvent(moveEvent)
def mousePressEvent(self, mouseEvent):
"""
Executed when the mouse is pressed on the item.
"""
self.handleSelected = self.handleAt(mouseEvent.pos())
if self.handleSelected:
self.mousePressPos = mouseEvent.pos()
self.mousePressRect = self.boundingRect()
super().mousePressEvent(mouseEvent)
def mouseMoveEvent(self, mouseEvent):
"""
Executed when the mouse is being moved over the item while being pressed.
"""
if self.handleSelected is not None:
self.interactiveResize(mouseEvent.pos())
else:
super().mouseMoveEvent(mouseEvent)
def mouseReleaseEvent(self, mouseEvent):
"""
Executed when the mouse is released from the item.
"""
super().mouseReleaseEvent(mouseEvent)
self.handleSelected = None
self.mousePressPos = None
self.mousePressRect = None
self.update()
def boundingRect(self):
"""
Returns the bounding rect of the shape (including the resize handles).
"""
o = self.handleSize + self.handleSpace
return self.rect().adjusted(-o, -o, o, o)
def updateHandlesPos(self):
"""
Update current resize handles according to the shape size and position.
"""
s = self.handleSize
b = self.boundingRect()
self.handles[self.handleTopLeft] = QRectF(b.left(), b.top(), s, s)
self.handles[self.handleTopMiddle] = QRectF(b.center().x() - s / 2, b.top(), s, s)
self.handles[self.handleTopRight] = QRectF(b.right() - s, b.top(), s, s)
self.handles[self.handleMiddleLeft] = QRectF(b.left(), b.center().y() - s / 2, s, s)
self.handles[self.handleMiddleRight] = QRectF(b.right() - s, b.center().y() - s / 2, s, s)
self.handles[self.handleBottomLeft] = QRectF(b.left(), b.bottom() - s, s, s)
self.handles[self.handleBottomMiddle] = QRectF(b.center().x() - s / 2, b.bottom() - s, s, s)
self.handles[self.handleBottomRight] = QRectF(b.right() - s, b.bottom() - s, s, s)
def interactiveResize(self, mousePos):
"""
Perform shape interactive resize.
"""
offset = self.handleSize + self.handleSpace
boundingRect = self.boundingRect()
rect = self.rect()
diff = QPointF(0, 0)
self.prepareGeometryChange()
if self.handleSelected == self.handleTopLeft:
fromX = self.mousePressRect.left()
fromY = self.mousePressRect.top()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setLeft(toX)
boundingRect.setTop(toY)
rect.setLeft(boundingRect.left() + offset)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleTopMiddle:
fromY = self.mousePressRect.top()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setY(toY - fromY)
boundingRect.setTop(toY)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleTopRight:
fromX = self.mousePressRect.right()
fromY = self.mousePressRect.top()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setRight(toX)
boundingRect.setTop(toY)
rect.setRight(boundingRect.right() - offset)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleMiddleLeft:
fromX = self.mousePressRect.left()
toX = fromX + mousePos.x() - self.mousePressPos.x()
diff.setX(toX - fromX)
boundingRect.setLeft(toX)
rect.setLeft(boundingRect.left() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleMiddleRight:
print("MR")
fromX = self.mousePressRect.right()
toX = fromX + mousePos.x() - self.mousePressPos.x()
diff.setX(toX - fromX)
boundingRect.setRight(toX)
rect.setRight(boundingRect.right() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomLeft:
fromX = self.mousePressRect.left()
fromY = self.mousePressRect.bottom()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setLeft(toX)
boundingRect.setBottom(toY)
rect.setLeft(boundingRect.left() + offset)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomMiddle:
fromY = self.mousePressRect.bottom()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setY(toY - fromY)
boundingRect.setBottom(toY)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomRight:
fromX = self.mousePressRect.right()
fromY = self.mousePressRect.bottom()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setRight(toX)
boundingRect.setBottom(toY)
rect.setRight(boundingRect.right() - offset)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
self.updateHandlesPos()
def shape(self):
"""
Returns the shape of this item as a QPainterPath in local coordinates.
"""
path = QPainterPath()
path.addRect(self.rect())
if self.isSelected():
for shape in self.handles.values():
path.addEllipse(shape)
return path
def paint(self, painter, option, widget=None):
"""
Paint the node in the graphic view.
"""
painter.setBrush(QBrush(QColor(255, 0, 0, 100)))
painter.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
painter.drawRect(self.rect())
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(QBrush(QColor(255, 0, 0, 255)))
painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
for handle, rect in self.handles.items():
if self.handleSelected is None or handle == self.handleSelected:
painter.drawEllipse(rect)
def main():
app = QApplication(sys.argv)
grview = QGraphicsView()
scene = QGraphicsScene()
scene.setSceneRect(0, 0, 680, 459)
scene.addPixmap(QPixmap('01.png'))
grview.setScene(scene)
item = GraphicsRectItem(0, 0, 300, 150)
scene.addItem(item)
grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
grview.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

11
QListView/README.md Normal file
View file

@ -0,0 +1,11 @@
# QListView练习
显示自定义widget使用setIndexWidget
排序使用QSortFilterProxyModel
## 截图
![截图](ScreenShot/1.png)
![截图](ScreenShot/2.gif)

BIN
QListView/ScreenShot/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
QListView/ScreenShot/2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

View file

@ -0,0 +1,63 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QListView, QWidget, QHBoxLayout, QLineEdit,\
QPushButton
# Created on 2018年8月4日
# author: Irony
# site: https://github.com/892768447
# email: 892768447@qq.com
# file: QListView.显示自定义Widget
# description:
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
class CustomWidget(QWidget):
def __init__(self, text, *args, **kwargs):
super(CustomWidget, self).__init__(*args, **kwargs)
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(QLineEdit(text, self))
layout.addWidget(QPushButton('x', self))
def sizeHint(self):
# 决定item的高度
return QSize(200, 40)
class ListView(QListView):
def __init__(self, *args, **kwargs):
super(ListView, self).__init__(*args, **kwargs)
# 模型
self._model = QStandardItemModel(self)
self.setModel(self._model)
# 循环生成10个自定义控件
for i in range(10):
item = QStandardItem()
self._model.appendRow(item) # 添加item
# 得到索引
index = self._model.indexFromItem(item)
widget = CustomWidget(str(i))
item.setSizeHint(widget.sizeHint()) # 主要是调整item的高度
# 设置自定义的widget
self.setIndexWidget(index, widget)
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = ListView()
w.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,116 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from random import choice, randint
import string
from time import time
from PyQt5.QtCore import QSortFilterProxyModel, Qt, QSize
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QListView,\
QHBoxLayout, QLineEdit
# Created on 2018年8月4日
# author: Irony
# site: https://github.com/892768447
# email: 892768447@qq.com
# file: QListView.显示自定义Widget并排序
# description:
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
def randomChar(y):
# 返回随机字符串
return ''.join(choice(string.ascii_letters) for _ in range(y))
class CustomWidget(QWidget):
def __init__(self, text, *args, **kwargs):
super(CustomWidget, self).__init__(*args, **kwargs)
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(QLineEdit(text, self))
layout.addWidget(QPushButton('x', self))
def sizeHint(self):
# 决定item的高度
return QSize(200, 40)
class SortFilterProxyModel(QSortFilterProxyModel):
def lessThan(self, source_left, source_right):
if not source_left.isValid() or not source_right.isValid():
return False
# 获取数据
leftData = self.sourceModel().data(source_left)
rightData = self.sourceModel().data(source_right)
if self.sortOrder() == Qt.DescendingOrder:
# 按照时间倒序排序
leftData = leftData.split('-')[-1]
rightData = rightData.split('-')[-1]
return leftData < rightData
# elif self.sortOrder() == Qt.AscendingOrder:
# #按照名字升序排序
# leftData = leftData.split('-')[0]
# rightData = rightData.split('-')[0]
# return leftData < rightData
return super(SortFilterProxyModel, self).lessThan(source_left, source_right)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(800, 600)
layout = QVBoxLayout(self)
# 名字排序
layout.addWidget(QPushButton('以名字升序', self, clicked=self.sortByName))
# 时间倒序
layout.addWidget(QPushButton('以时间倒序', self, clicked=self.sortByTime))
# listview
self.listView = QListView(self)
layout.addWidget(self.listView)
# 数据模型
self.dmodel = QStandardItemModel(self.listView)
# 排序代理模型
self.fmodel = SortFilterProxyModel(self.listView)
self.fmodel.setSourceModel(self.dmodel)
self.listView.setModel(self.fmodel)
# 模拟生成50条数据
for _ in range(50):
name = randomChar(5)
times = time() + randint(0, 30) # 当前时间随机+
value = '{}-{}'.format(name, times) # 内容用-分开
item = QStandardItem(value)
# item.setData(value, Qt.UserRole + 2)
self.dmodel.appendRow(item)
# 索引
index = self.fmodel.mapFromSource(item.index())
# 自定义的widget
widget = CustomWidget(value, self)
item.setSizeHint(widget.sizeHint())
self.listView.setIndexWidget(index, widget)
def sortByTime(self):
# 按照时间倒序排序
self.fmodel.sort(0, Qt.DescendingOrder)
def sortByName(self):
# 按照名字升序排序
self.fmodel.sort(0, Qt.AscendingOrder)
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

View file

@ -47,7 +47,8 @@
- [1.41 消息对话框倒计时关闭](消息对话框倒计时关闭/)
- 1.42 悬浮下拉菜单
- [1. tableWidget形式](partner_625781186/5.hoverMenu)
- [1.43 QSplitter 分割条重写 来添加按钮](分割窗口的分割条重写/)
- [1.43 QListView](QListView/)
- [1.44 QSplitter 分割条重写 来添加按钮](分割窗口的分割条重写/)
### [2.QGraphicsView练习](QGraphicsView练习/)
- [2.1 世界地图](QGraphicsView练习/世界地图)

View file

@ -1,72 +1,88 @@
# 无边框自定义标题栏窗口
### [Python3.4.4 or Python3.5][PyQt5]
原理说明:
- 使用一个QWidgetFramelessWindow作为父窗口, 一个TitleBar作为标题栏, 一个QWidget作为底部容器
- 父窗口FramelessWindow设置为背景透明但是需要绘制一定宽度的透明度很高的矩形边框用来接受鼠标事件变形鼠标样式进行调整窗口大小
- TitleBar的最小化最大化关闭等按钮事件关联到父窗口里
- TitleBar中的鼠标按下移动事件得到坐标也传递到父窗口调用move方法进行窗口移动
使用方法:
```
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)
layout.addWidget(QPushButton('按钮', self))
layout.addWidget(QTextEdit(self))
# 样式
StyleSheet = """
/*标题栏*/
TitleBar {
background-color: rgb(54, 157, 180);
}
/*最小化最大化关闭按钮通用默认背景*/
#buttonMinimum,#buttonMaximum,#buttonClose {
border: none;
background-color: rgb(54, 157, 180);
}
/*悬停*/
#buttonMinimum:hover,#buttonMaximum:hover {
background-color: rgb(48, 141, 162);
}
#buttonClose:hover {
color: white;
background-color: rgb(232, 17, 35);
}
/*鼠标按下不放*/
#buttonMinimum:pressed,#buttonMaximum:pressed {
background-color: rgb(44, 125, 144);
}
#buttonClose:pressed {
color: white;
background-color: rgb(161, 73, 92);
}
"""
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = FramelessWindow()
w.setWindowTitle('测试标题栏')
w.setWindowIcon(QIcon('Qt.ico'))
w.setWidget(MainWindow(w)) # 把自己的窗口添加进来
w.show()
sys.exit(app.exec_())
```
# 截图
![截图](ScreenShot/1.gif)
# 无边框自定义标题栏窗口
### [Python3.4.4 or Python3.5][PyQt5]
原理说明:
- 使用一个QWidgetFramelessWindow作为父窗口, 一个TitleBar作为标题栏, 一个QWidget作为底部容器
- 父窗口FramelessWindow设置为背景透明但是需要绘制一定宽度的透明度很高的矩形边框用来接受鼠标事件变形鼠标样式进行调整窗口大小
- TitleBar的最小化最大化关闭等按钮事件关联到父窗口里
- TitleBar中的鼠标按下移动事件得到坐标也传递到父窗口调用move方法进行窗口移动
使用方法:
```
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)
layout.addWidget(QPushButton('按钮', self))
layout.addWidget(QTextEdit(self))
# 样式
StyleSheet = """
/*标题栏*/
TitleBar {
background-color: rgb(54, 157, 180);
}
/*最小化最大化关闭按钮通用默认背景*/
#buttonMinimum,#buttonMaximum,#buttonClose {
border: none;
background-color: rgb(54, 157, 180);
}
/*悬停*/
#buttonMinimum:hover,#buttonMaximum:hover {
background-color: rgb(48, 141, 162);
}
#buttonClose:hover {
color: white;
background-color: rgb(232, 17, 35);
}
/*鼠标按下不放*/
#buttonMinimum:pressed,#buttonMaximum:pressed {
background-color: rgb(44, 125, 144);
}
#buttonClose:pressed {
color: white;
background-color: rgb(161, 73, 92);
}
"""
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = FramelessWindow()
w.setWindowTitle('测试标题栏')
w.setWindowIcon(QIcon('Qt.ico'))
w.setWidget(MainWindow(w)) # 把自己的窗口添加进来
w.show()
sys.exit(app.exec_())
```
## 截图
![截图](ScreenShot/1.gif)
# 利用windows api
原理说明:
- 使用win32gui设置薄边框
- 重写nativeEvent事件拦截边框的系统边框的显示并返回各个方向
## 截图
![截图](ScreenShot/1.jpg)
![截图](ScreenShot/2.jpg)
![截图](ScreenShot/3.gif)

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View file

@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created on 2018年8月2日
# author: Irony
# site: https://github.com/892768447
# email: 892768447@qq.com
# file: win无边框调整大小
# description:
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
import ctypes.wintypes
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget
import win32api
import win32con
import win32gui
class Window(QWidget):
BorderWidth = 5
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(800, 600)
self.setWindowFlags(Qt.Window
| Qt.FramelessWindowHint
| Qt.WindowSystemMenuHint
| Qt.WindowMinimizeButtonHint
| Qt.WindowMaximizeButtonHint
| Qt.WindowCloseButtonHint)
# 增加薄边框
style = win32gui.GetWindowLong(int(self.winId()), win32con.GWL_STYLE)
win32gui.SetWindowLong(
int(self.winId()), win32con.GWL_STYLE, style | win32con.WS_THICKFRAME)
def nativeEvent(self, eventType, message):
retval, result = super(Window, self).nativeEvent(eventType, message)
if eventType == "windows_generic_MSG":
msg = ctypes.wintypes.MSG.from_address(message.__int__())
if msg.message == win32con.WM_NCCALCSIZE:
# 拦截不显示顶部的系统自带的边框
return True, 0
if msg.message == win32con.WM_NCHITTEST:
# 获取鼠标移动经过时的坐标
x = win32api.LOWORD(msg.lParam) - self.frameGeometry().x()
y = win32api.HIWORD(msg.lParam) - self.frameGeometry().y()
w, h = self.width(), self.height()
lx = x < self.BorderWidth
rx = x > w - self.BorderWidth
ty = y < self.BorderWidth
by = y > h - self.BorderWidth
# 左上角
if (lx and ty):
return True, win32con.HTTOPLEFT
# 右下角
if (rx and by):
return True, win32con.HTBOTTOMRIGHT
# 右上角
if (rx and ty):
return True, win32con.HTTOPRIGHT
# 左下角
if (lx and by):
return True, win32con.HTBOTTOMLEFT
# 上
if ty:
return True, win32con.HTTOP
# 下
if by:
return True, win32con.HTBOTTOM
# 左
if lx:
return True, win32con.HTLEFT
# 右
if rx:
return True, win32con.HTRIGHT
# 标题
return True, win32con.HTCAPTION
return retval, result
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())