forked from PyQt5/PyQt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/PyQt5/PyQt
- Loading branch information
Showing
9 changed files
with
694 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
Created on 2021/4/13 | ||
@author: Irony | ||
@site: https://github.com/PyQt5 | ||
@email: [email protected] | ||
@file: ScreenNotify | ||
@description: 屏幕、分辨率、DPI变化通知 | ||
""" | ||
import sys | ||
|
||
from PyQt5.QtCore import QTimer, QRect | ||
from PyQt5.QtWidgets import QApplication, QPlainTextEdit, qApp | ||
|
||
|
||
class Window(QPlainTextEdit): | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(Window, self).__init__(*args, **kwargs) | ||
self.appendPlainText('修改分辨率后查看') | ||
# 记录最后一次的值(减少槽调用) | ||
self.m_rect = QRect() | ||
# 使用定时器来延迟触发最后一次变化 | ||
self.m_timer = QTimer(self, timeout=self.onSolutionChanged) | ||
self.m_timer.setSingleShot(True) # **重要** 保证多次信号尽量少的调用函数 | ||
|
||
# 主要是多屏幕->无屏幕->有屏幕 | ||
qApp.primaryScreenChanged.connect(lambda _: self.m_timer.start(1000)) | ||
# 其它信号最终基本上都会调用该信号 | ||
qApp.primaryScreen().virtualGeometryChanged.connect(lambda _: self.m_timer.start(1000)) | ||
# DPI变化 | ||
qApp.primaryScreen().logicalDotsPerInchChanged.connect(lambda _: self.m_timer.start(1000)) | ||
|
||
def onSolutionChanged(self): | ||
# 获取主屏幕 | ||
screen = qApp.primaryScreen() | ||
if self.m_rect == screen.availableVirtualGeometry(): | ||
return | ||
self.m_rect = screen.availableVirtualGeometry() | ||
# 所有屏幕可用大小 | ||
self.appendPlainText('\navailableVirtualGeometry: {0}'.format(str(screen.availableVirtualGeometry()))) | ||
# 获取所有屏幕 | ||
screens = qApp.screens() | ||
for screen in screens: | ||
self.appendPlainText( | ||
'screen: {0}, geometry({1}), availableGeometry({2}), logicalDotsPerInch({3}), ' | ||
'physicalDotsPerInch({4}), refreshRate({5})'.format( | ||
screen.name(), screen.geometry(), screen.availableGeometry(), screen.logicalDotsPerInch(), | ||
screen.physicalDotsPerInch(), screen.refreshRate())) | ||
|
||
|
||
if __name__ == '__main__': | ||
app = QApplication(sys.argv) | ||
w = Window() | ||
w.show() | ||
sys.exit(app.exec_()) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
Created on 2021/4/15 | ||
@author: Irony | ||
@site: https://github.com/PyQt5 | ||
@email: [email protected] | ||
@file: ImageView | ||
@description: | ||
""" | ||
import os | ||
|
||
from PyQt5.QtCore import QPointF, Qt, QRectF, QSizeF | ||
from PyQt5.QtGui import QStandardItem, QStandardItemModel, QPainter, QColor, QImage, QPixmap | ||
from PyQt5.QtWidgets import QListView, QGraphicsView, QGraphicsPixmapItem, QGraphicsScene | ||
|
||
ScrollPixel = 40 | ||
|
||
|
||
class BigImageView(QGraphicsView): | ||
"""图片查看控件""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
image = kwargs.pop('image', None) | ||
background = kwargs.pop('background', None) | ||
super(BigImageView, self).__init__(*args, **kwargs) | ||
self.setCursor(Qt.OpenHandCursor) | ||
self.setBackground(background) | ||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) | ||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) | ||
self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | | ||
QPainter.SmoothPixmapTransform) | ||
self.setCacheMode(self.CacheBackground) | ||
self.setViewportUpdateMode(self.SmartViewportUpdate) | ||
self._item = QGraphicsPixmapItem() # 放置图像 | ||
self._item.setFlags(QGraphicsPixmapItem.ItemIsFocusable | | ||
QGraphicsPixmapItem.ItemIsMovable) | ||
self._scene = QGraphicsScene(self) # 场景 | ||
self.setScene(self._scene) | ||
self._scene.addItem(self._item) | ||
rect = QApplication.instance().desktop().availableGeometry() | ||
self.resize(int(rect.width() * 2 / 3), int(rect.height() * 2 / 3)) | ||
|
||
self.pixmap = None | ||
self._delta = 0.1 # 缩放 | ||
self.setPixmap(image) | ||
|
||
def setBackground(self, color): | ||
"""设置背景颜色 | ||
:param color: 背景颜色 | ||
:type color: QColor or str or GlobalColor | ||
""" | ||
if isinstance(color, QColor): | ||
self.setBackgroundBrush(color) | ||
elif isinstance(color, (str, Qt.GlobalColor)): | ||
color = QColor(color) | ||
if color.isValid(): | ||
self.setBackgroundBrush(color) | ||
|
||
def setPixmap(self, pixmap, fitIn=True): | ||
"""加载图片 | ||
:param pixmap: 图片或者图片路径 | ||
:param fitIn: 是否适应 | ||
:type pixmap: QPixmap or QImage or str | ||
:type fitIn: bool | ||
""" | ||
if isinstance(pixmap, QPixmap): | ||
self.pixmap = pixmap | ||
elif isinstance(pixmap, QImage): | ||
self.pixmap = QPixmap.fromImage(pixmap) | ||
elif isinstance(pixmap, str) and os.path.isfile(pixmap): | ||
self.pixmap = QPixmap(pixmap) | ||
else: | ||
return | ||
self._item.setPixmap(self.pixmap) | ||
self._item.update() | ||
self.setSceneDims() | ||
if fitIn: | ||
self.fitInView(QRectF(self._item.pos(), QSizeF( | ||
self.pixmap.size())), Qt.KeepAspectRatio) | ||
self.update() | ||
|
||
def setSceneDims(self): | ||
if not self.pixmap: | ||
return | ||
self.setSceneRect(QRectF(QPointF(0, 0), QPointF(self.pixmap.width(), self.pixmap.height()))) | ||
|
||
def fitInView(self, rect, flags=Qt.IgnoreAspectRatio): | ||
"""剧中适应 | ||
:param rect: 矩形范围 | ||
:param flags: | ||
:return: | ||
""" | ||
if not self.scene() or rect.isNull(): | ||
return | ||
unity = self.transform().mapRect(QRectF(0, 0, 1, 1)) | ||
self.scale(1 / unity.width(), 1 / unity.height()) | ||
viewRect = self.viewport().rect() | ||
sceneRect = self.transform().mapRect(rect) | ||
x_ratio = viewRect.width() / sceneRect.width() | ||
y_ratio = viewRect.height() / sceneRect.height() | ||
if flags == Qt.KeepAspectRatio: | ||
x_ratio = y_ratio = min(x_ratio, y_ratio) | ||
elif flags == Qt.KeepAspectRatioByExpanding: | ||
x_ratio = y_ratio = max(x_ratio, y_ratio) | ||
self.scale(x_ratio, y_ratio) | ||
self.centerOn(rect.center()) | ||
|
||
def wheelEvent(self, event): | ||
if event.angleDelta().y() > 0: | ||
self.zoomIn() | ||
else: | ||
self.zoomOut() | ||
|
||
def zoomIn(self): | ||
"""放大""" | ||
self.zoom(1 + self._delta) | ||
|
||
def zoomOut(self): | ||
"""缩小""" | ||
self.zoom(1 - self._delta) | ||
|
||
def zoom(self, factor): | ||
"""缩放 | ||
:param factor: 缩放的比例因子 | ||
""" | ||
_factor = self.transform().scale( | ||
factor, factor).mapRect(QRectF(0, 0, 1, 1)).width() | ||
if _factor < 0.07 or _factor > 100: | ||
# 防止过大过小 | ||
return | ||
self.scale(factor, factor) | ||
|
||
|
||
class ImageView(QListView): | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(ImageView, self).__init__(*args, **kwargs) | ||
self.setFrameShape(self.NoFrame) | ||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) | ||
self.setEditTriggers(self.NoEditTriggers) | ||
self.setDropIndicatorShown(True) | ||
self.setDragDropMode(self.DragDrop) | ||
self.setDefaultDropAction(Qt.IgnoreAction) | ||
self.setSelectionMode(self.ExtendedSelection) | ||
self.setVerticalScrollMode(self.ScrollPerPixel) | ||
self.setHorizontalScrollMode(self.ScrollPerPixel) | ||
self.setFlow(self.LeftToRight) | ||
self.setWrapping(True) | ||
self.setResizeMode(self.Adjust) | ||
self.setSpacing(6) | ||
self.setViewMode(self.IconMode) | ||
self.setWordWrap(True) | ||
self.setSelectionRectVisible(True) | ||
self.setContextMenuPolicy(Qt.CustomContextMenu) | ||
# 解决拖动到顶部或者底部自动滚动 | ||
self.setAutoScrollMargin(150) | ||
self.verticalScrollBar().setSingleStep(ScrollPixel) | ||
# 设置model | ||
self.dmodel = QStandardItemModel(self) | ||
self.setModel(self.dmodel) | ||
|
||
# 大图控件 | ||
self.bigView = BigImageView(background='#323232') | ||
|
||
def addItem(self, image): | ||
if isinstance(image, str): | ||
image = QPixmap(image) | ||
# 添加一个item | ||
item = QStandardItem() | ||
# 记录原始图片 | ||
item.setData(image, Qt.UserRole + 1) # 用于双击的时候取出来 | ||
# 缩放成小图并显示 | ||
item.setData(image.scaled(60, 60, Qt.IgnoreAspectRatio, Qt.SmoothTransformation), Qt.DecorationRole) | ||
# 添加item到界面中 | ||
self.dmodel.appendRow(item) | ||
|
||
def count(self): | ||
return self.dmodel.rowCount() | ||
|
||
def setCurrentRow(self, row): | ||
self.setCurrentIndex(self.dmodel.index(row, 0)) | ||
|
||
def currentRow(self): | ||
return self.currentIndex().row() | ||
|
||
def updateGeometries(self): | ||
# 一次滑动20px | ||
super(ImageView, self).updateGeometries() | ||
self.verticalScrollBar().setSingleStep(ScrollPixel) | ||
|
||
def closeEvent(self, event): | ||
# 关闭预览窗口 | ||
self.bigView.close() | ||
super(ImageView, self).closeEvent(event) | ||
|
||
def wheelEvent(self, event): | ||
# 修复滑动bug | ||
if self.flow() == QListView.LeftToRight: | ||
bar = self.horizontalScrollBar() | ||
value = ScrollPixel if event.angleDelta().y() < 0 else (0 - ScrollPixel) | ||
bar.setSliderPosition(bar.value() + value) | ||
else: | ||
super(ImageView, self).wheelEvent(event) | ||
|
||
def mouseDoubleClickEvent(self, event): | ||
# 列表双击,如果有item则进入item处理流程,否则调用打开图片功能 | ||
index = self.indexAt(event.pos()) | ||
if index and index.isValid(): | ||
item = self.dmodel.itemFromIndex(index) | ||
if item: | ||
# 取出原图用来新窗口显示 | ||
image = item.data(Qt.UserRole + 1) | ||
self.bigView.setPixmap(image) | ||
self.bigView.show() | ||
return | ||
super(ImageView, self).mouseDoubleClickEvent(event) | ||
|
||
|
||
if __name__ == '__main__': | ||
import sys | ||
import cgitb | ||
|
||
cgitb.enable(format='text') | ||
from PyQt5.QtWidgets import QApplication | ||
|
||
app = QApplication(sys.argv) | ||
w = ImageView() | ||
w.show() | ||
|
||
# 添加模拟图片 | ||
for i in range(3): | ||
for name in os.listdir('ScreenShot'): | ||
w.addItem(os.path.join('ScreenShot', name)) | ||
sys.exit(app.exec_()) |
Oops, something went wrong.