屏幕变化监听
This commit is contained in:
parent
2a54e678ae
commit
7c396a9a40
7 changed files with 328 additions and 1 deletions
|
@ -23,6 +23,7 @@
|
||||||
- [判断信号是否连接](#20判断信号是否连接)
|
- [判断信号是否连接](#20判断信号是否连接)
|
||||||
- [调用虚拟键盘](#21调用虚拟键盘)
|
- [调用虚拟键盘](#21调用虚拟键盘)
|
||||||
- [动态忙碌光标](#22动态忙碌光标)
|
- [动态忙碌光标](#22动态忙碌光标)
|
||||||
|
- [屏幕变动监听](#23屏幕变动监听)
|
||||||
|
|
||||||
## 1、重启窗口Widget
|
## 1、重启窗口Widget
|
||||||
[运行 RestartWindow.py](RestartWindow.py)
|
[运行 RestartWindow.py](RestartWindow.py)
|
||||||
|
@ -223,4 +224,11 @@ PyQt 结合 Opencv 进行人脸检测;
|
||||||
|
|
||||||
通过定时器不停的修改光标图片来实现动态效果
|
通过定时器不停的修改光标图片来实现动态效果
|
||||||
|
|
||||||
![GifCursor](ScreenShot/GifCursor.gif)
|
![GifCursor](ScreenShot/GifCursor.gif)
|
||||||
|
|
||||||
|
## 23、屏幕变动监听
|
||||||
|
[运行 ScreenNotify.py](ScreenNotify.py)
|
||||||
|
|
||||||
|
通过定时器减少不同的变化信号,尽量保证只调用一次槽函数来获取信息
|
||||||
|
|
||||||
|
![ScreenNotify](ScreenShot/ScreenNotify.png)
|
58
Demo/ScreenNotify.py
Normal file
58
Demo/ScreenNotify.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Created on 2021/4/13
|
||||||
|
@author: Irony
|
||||||
|
@site: https://github.com/PyQt5
|
||||||
|
@email: 892768447@qq.com
|
||||||
|
@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_())
|
BIN
Demo/ScreenShot/ScreenNotify.png
Normal file
BIN
Demo/ScreenShot/ScreenNotify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
105
QtRemoteObjects/SyncUi/ClipboardMaster.py
Normal file
105
QtRemoteObjects/SyncUi/ClipboardMaster.py
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Created on 2020/7/31
|
||||||
|
@author: Irony
|
||||||
|
@site: https://pyqt.site https://github.com/PyQt5
|
||||||
|
@email: 892768447@qq.com
|
||||||
|
@file: ClipboardMaster
|
||||||
|
@description:
|
||||||
|
"""
|
||||||
|
from PyQt5.QtCore import QUrl, pyqtSlot, pyqtSignal, QLoggingCategory, QVariant, QMimeData
|
||||||
|
from PyQt5.QtRemoteObjects import QRemoteObjectHost
|
||||||
|
from PyQt5.QtWidgets import QTextBrowser
|
||||||
|
|
||||||
|
__Author__ = 'Irony'
|
||||||
|
__Copyright__ = 'Copyright (c) 2019 Irony'
|
||||||
|
__Version__ = 1.0
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class WindowMaster(QTextBrowser):
|
||||||
|
SignalUpdateMimeData = pyqtSignal(
|
||||||
|
bool, QVariant, # color
|
||||||
|
bool, QVariant, # html
|
||||||
|
bool, QVariant, # image
|
||||||
|
bool, QVariant, # text
|
||||||
|
bool, QVariant, # urls
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(WindowMaster, self).__init__(*args, **kwargs)
|
||||||
|
# 监听剪切板
|
||||||
|
# clipboard = QApplication.clipboard()
|
||||||
|
# clipboard.dataChanged.connect(self.on_data_changed)
|
||||||
|
# 开启节点
|
||||||
|
host = QRemoteObjectHost(QUrl('tcp://0.0.0.0:' + sys.argv[1]), parent=self)
|
||||||
|
host.enableRemoting(self, 'WindowMaster')
|
||||||
|
self.append('开启节点完成')
|
||||||
|
|
||||||
|
def on_data_changed(self):
|
||||||
|
# 服务端剪贴板变化后发送到客户端
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.blockSignals(True)
|
||||||
|
mime_data = clipboard.mimeData()
|
||||||
|
self.SignalUpdateMimeData.emit(
|
||||||
|
mime_data.hasColor(), mime_data.colorData(),
|
||||||
|
mime_data.hasHtml(), mime_data.html(),
|
||||||
|
mime_data.hasImage(), mime_data.imageData(),
|
||||||
|
mime_data.hasText(), mime_data.text(),
|
||||||
|
mime_data.hasUrls(), mime_data.urls(),
|
||||||
|
)
|
||||||
|
clipboard.blockSignals(False)
|
||||||
|
|
||||||
|
@pyqtSlot(
|
||||||
|
bool, QVariant, # color
|
||||||
|
bool, QVariant, # html
|
||||||
|
bool, QVariant, # image
|
||||||
|
bool, QVariant, # text
|
||||||
|
bool, QVariant, # urls
|
||||||
|
bool, QVariant # files
|
||||||
|
)
|
||||||
|
def updateMimeData(self,
|
||||||
|
hasColor, color,
|
||||||
|
hasHtml, html,
|
||||||
|
hasImage, image,
|
||||||
|
hasText, text,
|
||||||
|
hasUrls, urls,
|
||||||
|
hasFiles, files,
|
||||||
|
):
|
||||||
|
# 客户端剪切板同步到服务端
|
||||||
|
self.append('收到客户端发送的剪贴板')
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.blockSignals(True)
|
||||||
|
data = QMimeData()
|
||||||
|
if hasColor:
|
||||||
|
data.setColorData(color)
|
||||||
|
if hasHtml:
|
||||||
|
data.setHtml(html)
|
||||||
|
if hasImage:
|
||||||
|
data.setImageData(image)
|
||||||
|
if hasText:
|
||||||
|
data.setText(text)
|
||||||
|
# if hasUrls:
|
||||||
|
# data.setUrls(urls)
|
||||||
|
if hasFiles:
|
||||||
|
data.setData('')
|
||||||
|
clipboard.setMimeData(data)
|
||||||
|
clipboard.blockSignals(False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import cgitb
|
||||||
|
|
||||||
|
cgitb.enable(1, None, 5, '')
|
||||||
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
|
QLoggingCategory.setFilterRules('qt.remoteobjects.debug=true\n'
|
||||||
|
'qt.remoteobjects.warning=true')
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
w = WindowMaster()
|
||||||
|
w.show()
|
||||||
|
sys.exit(app.exec_())
|
107
QtRemoteObjects/SyncUi/ClipboardSlave.py
Normal file
107
QtRemoteObjects/SyncUi/ClipboardSlave.py
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Created on 2020/7/31
|
||||||
|
@author: Irony
|
||||||
|
@site: https://pyqt.site https://github.com/PyQt5
|
||||||
|
@email: 892768447@qq.com
|
||||||
|
@file: ClipboardSlave
|
||||||
|
@description:
|
||||||
|
"""
|
||||||
|
from PyQt5.QtCore import QUrl, pyqtSignal, QVariant, QMimeData
|
||||||
|
from PyQt5.QtRemoteObjects import QRemoteObjectNode, QRemoteObjectReplica
|
||||||
|
from PyQt5.QtWidgets import QTextBrowser
|
||||||
|
|
||||||
|
__Author__ = 'Irony'
|
||||||
|
__Copyright__ = 'Copyright (c) 2019 Irony'
|
||||||
|
__Version__ = 1.0
|
||||||
|
|
||||||
|
|
||||||
|
class WindowSlave(QTextBrowser):
|
||||||
|
SignalUpdateMimeData = pyqtSignal(
|
||||||
|
bool, QVariant, # color
|
||||||
|
bool, QVariant, # html
|
||||||
|
bool, QVariant, # image
|
||||||
|
bool, QVariant, # text
|
||||||
|
bool, QVariant, # urls
|
||||||
|
bool, QVariant, # files
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(WindowSlave, self).__init__(*args, **kwargs)
|
||||||
|
# 监听剪切板
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.dataChanged.connect(self.on_data_changed)
|
||||||
|
# 加入Master节点
|
||||||
|
node = QRemoteObjectNode(parent=self)
|
||||||
|
node.connectToNode(QUrl('tcp://{}:{}'.format(sys.argv[1], sys.argv[2])))
|
||||||
|
# 获取WindowMaster对象
|
||||||
|
self.windowMaster = node.acquireDynamic('WindowMaster')
|
||||||
|
# 初始化成功后才能去绑定信号等
|
||||||
|
self.windowMaster.initialized.connect(self.onInitialized)
|
||||||
|
# 状态改变 https://doc.qt.io/qt-5/qremoteobjectreplica.html#State-enum
|
||||||
|
self.windowMaster.stateChanged.connect(self.onStateChanged)
|
||||||
|
|
||||||
|
def onStateChanged(self, newState, oldState):
|
||||||
|
if newState == QRemoteObjectReplica.Suspect:
|
||||||
|
self.append('连接丢失')
|
||||||
|
|
||||||
|
def onInitialized(self):
|
||||||
|
self.SignalUpdateMimeData.connect(self.windowMaster.updateMimeData)
|
||||||
|
# self.windowMaster.SignalUpdateMimeData.connect(self.updateMimeData)
|
||||||
|
self.append('绑定信号槽完成')
|
||||||
|
|
||||||
|
def on_data_changed(self):
|
||||||
|
# 客户端剪贴板变化后发送到远程
|
||||||
|
print('on_data_changed')
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.blockSignals(True)
|
||||||
|
mime_data = clipboard.mimeData()
|
||||||
|
files = mime_data.data('text/uri-list')
|
||||||
|
self.SignalUpdateMimeData.emit(
|
||||||
|
mime_data.hasColor(), mime_data.colorData(),
|
||||||
|
mime_data.hasHtml(), mime_data.html(),
|
||||||
|
mime_data.hasImage(), mime_data.imageData(),
|
||||||
|
mime_data.hasText(), mime_data.text(),
|
||||||
|
mime_data.hasUrls(), mime_data.urls(),
|
||||||
|
True if files else False, files,
|
||||||
|
)
|
||||||
|
clipboard.blockSignals(False)
|
||||||
|
|
||||||
|
def updateMimeData(self,
|
||||||
|
hasColor, color,
|
||||||
|
hasHtml, html,
|
||||||
|
hasImage, image,
|
||||||
|
hasText, text,
|
||||||
|
hasUrls, urls
|
||||||
|
):
|
||||||
|
# 远程的剪贴板同步到客户端
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.blockSignals(True)
|
||||||
|
data = QMimeData()
|
||||||
|
if hasColor:
|
||||||
|
data.setColorData(color)
|
||||||
|
if hasHtml:
|
||||||
|
data.setHtml(html)
|
||||||
|
if hasImage:
|
||||||
|
data.setImageData(image)
|
||||||
|
if hasText:
|
||||||
|
data.setText(text)
|
||||||
|
if hasUrls:
|
||||||
|
data.setUrls(urls)
|
||||||
|
clipboard.setMimeData(data)
|
||||||
|
clipboard.blockSignals(False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
import cgitb
|
||||||
|
|
||||||
|
cgitb.enable(1, None, 5, '')
|
||||||
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
w = WindowSlave()
|
||||||
|
w.show()
|
||||||
|
sys.exit(app.exec_())
|
|
@ -253,6 +253,7 @@ https://pyqt.site 论坛是专门针对PyQt5学习和提升开设的网站,分
|
||||||
- [判断信号是否连接](Demo/IsSignalConnected.py)
|
- [判断信号是否连接](Demo/IsSignalConnected.py)
|
||||||
- [调用虚拟键盘](Demo/CallVirtualKeyboard.py)
|
- [调用虚拟键盘](Demo/CallVirtualKeyboard.py)
|
||||||
- [动态忙碌光标](Demo/GifCursor.py)
|
- [动态忙碌光标](Demo/GifCursor.py)
|
||||||
|
- [屏幕变动监听](Demo/ScreenNotify.py)
|
||||||
|
|
||||||
# QQ群
|
# QQ群
|
||||||
|
|
||||||
|
|
48
Test/ColumnView.py
Normal file
48
Test/ColumnView.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Created on 2020/9/14
|
||||||
|
@author: Irony
|
||||||
|
@site: https://pyqt.site https://github.com/PyQt5
|
||||||
|
@email: 892768447@qq.com
|
||||||
|
@file: ColumnView
|
||||||
|
@description:
|
||||||
|
"""
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import QComboBox, QFileSystemModel, QHBoxLayout, QSpacerItem, QSizePolicy
|
||||||
|
|
||||||
|
__Author__ = 'Irony'
|
||||||
|
__Copyright__ = 'Copyright (c) 2020'
|
||||||
|
__Version__ = 'Version 1.0'
|
||||||
|
|
||||||
|
|
||||||
|
class PathComboBox(QComboBox):
|
||||||
|
|
||||||
|
def __init__(self, *args, is_item=False, **kwargs):
|
||||||
|
super(PathComboBox, self).__init__(*args, **kwargs)
|
||||||
|
self.is_item = is_item
|
||||||
|
if not self.is_item:
|
||||||
|
self.setEditable(True)
|
||||||
|
layout = QHBoxLayout(self)
|
||||||
|
layout.setSpacing(0)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 23)
|
||||||
|
layout.addItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
|
||||||
|
else:
|
||||||
|
self.f_model = QFileSystemModel(self)
|
||||||
|
self.f_model.setRootPath('')
|
||||||
|
self.setModel(self.f_model)
|
||||||
|
|
||||||
|
def addWidget(self, widget):
|
||||||
|
self.layout().insertWidget(self.layout().count()-1, widget)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
w = PathComboBox()
|
||||||
|
w.show()
|
||||||
|
w.addWidget(PathComboBox(w, is_item=True))
|
||||||
|
sys.exit(app.exec_())
|
Loading…
Reference in a new issue