Pyqt5 从 QtWebChannel 移动 window
Pyqt5 Move window from QtWebChannel
我正在尝试使 mousePressEvent 和 mouseMoveEvent 事件起作用,以便从 QtWebChannel 移动我的应用程序 window。
我正在使用 self.setWindowFlags (QtCore.Qt.FramelessWindowHint) 删除 window 标志并使用带有 html、css 和 js 的自定义标志。
在 html 中,我有一个 ID 为 "header" 的 div,它具有自定义的 window 标志,我想按住鼠标左键, window 可以像传统的 window 标志一样被拖动。
关闭、最小化和最大化按钮在使用后端单击时已经具有各自的功能,但我在创建允许从 <div id="header"> . . . </ div >
移动 window 的功能时遇到问题。
如何 运行 QtWebChannel 中的 mousePressEvent 和 mouseMoveEvent 事件来移动 window 并模拟传统的 window 标志?
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
from PyQt5.QtCore import QPoint
class Backend(QtCore.QObject):
valueChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._value = ""
@QtCore.pyqtProperty(str)
def value(self):
return self._value
@value.setter
def value(self, v):
self._value = v
self.valueChanged.emit(v)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.webEngineView = QtWebEngineWidgets.QWebEngineView()
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.resize(650, 610)
self.setWindowOpacity(0.99)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.setWindowIcon(icon)
lay = QtWidgets.QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(self.webEngineView)
backend = Backend(self)
backend.valueChanged.connect(self.foo_function)
self.channel = QtWebChannel.QWebChannel()
self.channel.registerObject("backend", backend)
self.webEngineView.page().setWebChannel(self.channel)
path = "http://localhost"
self.webEngineView.setUrl(QtCore.QUrl(path))
@QtCore.pyqtSlot(str)
def foo_function(self, value):
print("JS:", value)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
片段html代码
<div id="header" style="top: 0;" class="header">
<button ondblclick="$('#div_console').fadeIn('fast')" class="ui-btn modales" id="btn_title" value="title" title="Bankus"><i style="color:#007bff" class="fas fa-eye"></i></button>
<span id="title_text">Bankus 1.0</span>
<button title="Cerrar" id="btn_exit" value="exit" onclick="json($(this))" class="ui-btn closee modales"><svg viewBox="0 0 10 10"><polygon points="10.2,0.7 9.5,0 5.1,4.4 0.7,0 0,0.7 4.4,5.1 0,9.5 0.7,10.2 5.1,5.8 9.5,10.2 10.2,9.5 5.8,5.1" /></svg></button>
<button title="Maximizar" id="btn_maxi" value="maxi" onclick="json($(this))" class="ui-btn maximize modales"><svg viewBox="0 0 10 10"><path d="M0,0v10h10V0H0z M9,9H1V1h8V9z" /></svg></button>
<button title="Retaurar" id="btn_maxi" value="norm" onclick="json($(this))" class="ui-btn maximize modales invisi"><svg viewBox="0 0 10.2 10.1"><path d="M2.1,0v2H0v8.1h8.2v-2h2V0H2.1z M7.2,9.2H1.1V3h6.1V9.2z M9.2,7.1h-1V2H3.1V1h6.1V7.1z" /></svg></button>
<button title="Minimizar" id="btn_mini" value="mini" onclick="json($(this))" class="ui-btn minimize modales"><svg x="0px" y="0px" viewBox="0 0 10.2 1"><rect x="0" y="50%" width="10.2" height="1" /></svg></button>
<button title="Captura de pantalla" id="btn_capt" value="capt" onclick="json($(this))" class="ui-btn modales"><svg id="capture" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 64 64"><polygon fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4" points="47 12 42.88 8 21.12 8 17 12 2 12 2 56 62 56 62 12 47 12"/><circle cx="32" cy="34" r="14" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/><path fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="2" d="M10,21h0a1,1,0,0,1-1-1H9a1,1,0,0,1,1-1h0a1,1,0,0,1,1,1h0A1,1,0,0,1,10,21Z"/></svg></button>
</div>
github 上的完整 html 代码:https://github.com/onimac92/bankus/blob/master/index.html
代码最少 html:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
margin: 0;
}
#header {
width: 100%;
height: 30px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="header"></div>
</body>
</html>
您必须检测鼠标事件,将它们发送到 python 并执行 window 移动:
main.py
import json
import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class WindowManager(QtCore.QObject):
def __init__(self, window, parent=None):
super().__init__(parent)
self._window = window
self._drag_position = QtCore.QPoint()
@property
def window(self):
return self._window
@QtCore.pyqtSlot(str)
def mousePressEvent(self, string_event):
event = json.loads(string_event)
if event["which"] == 1:
gp = QtCore.QPoint(event["screenX"], event["screenY"])
self.drag_position = gp - self.window.frameGeometry().topLeft()
@QtCore.pyqtSlot(str)
def mouseMoveEvent(self, string_event):
event = json.loads(string_event)
if event["which"] == 1:
gp = QtCore.QPoint(event["screenX"], event["screenY"])
self.window.move(gp - self.drag_position)
class WebEngineView(QtWebEngineWidgets.QWebEngineView):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowOpacity(0.99)
self.resize(640, 480)
icon = QtGui.QIcon()
icon.addPixmap(
QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off
)
self.setWindowIcon(icon)
self.window_manager = WindowManager(self.window())
self.channel = QtWebChannel.QWebChannel()
self.channel.registerObject("window_manager", self.window_manager)
self.page().setWebChannel(self.channel)
current_dir = os.path.dirname(os.path.realpath(__file__))
self.load(QtCore.QUrl.fromLocalFile(os.path.join(current_dir, "index.html")))
if __name__ == "__main__":
import sys
sys.argv.append("--remote-debugging-port=8000")
app = QtWidgets.QApplication(sys.argv)
w = WebEngineView()
w.show()
sys.exit(app.exec_())
index.html
<!DOCTYPE html>
<html>
<head>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<style type="text/css">
body {
margin: 0;
}
#header {
width: 100%;
height: 30px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="header"></div>
<script type="text/javascript">
function event_to_string(event){
return JSON.stringify({"screenX": event.screenX, "screenY": event.screenY, "which": event.which})
}
var window_manager = null;
if (typeof QWebChannel !== "undefined") {
new QWebChannel(qt.webChannelTransport, function (channel) {
window_manager = channel.objects.window_manager;
var header = document.getElementById("header")
header.addEventListener('mousedown', function(event){
window_manager.mousePressEvent(event_to_string(event))
});
header.addEventListener('mousemove', function(event){
window_manager.mouseMoveEvent(event_to_string(event))
});
});
}
</script>
</body>
我正在尝试使 mousePressEvent 和 mouseMoveEvent 事件起作用,以便从 QtWebChannel 移动我的应用程序 window。
我正在使用 self.setWindowFlags (QtCore.Qt.FramelessWindowHint) 删除 window 标志并使用带有 html、css 和 js 的自定义标志。
在 html 中,我有一个 ID 为 "header" 的 div,它具有自定义的 window 标志,我想按住鼠标左键, window 可以像传统的 window 标志一样被拖动。
关闭、最小化和最大化按钮在使用后端单击时已经具有各自的功能,但我在创建允许从 <div id="header"> . . . </ div >
移动 window 的功能时遇到问题。
如何 运行 QtWebChannel 中的 mousePressEvent 和 mouseMoveEvent 事件来移动 window 并模拟传统的 window 标志?
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
from PyQt5.QtCore import QPoint
class Backend(QtCore.QObject):
valueChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._value = ""
@QtCore.pyqtProperty(str)
def value(self):
return self._value
@value.setter
def value(self, v):
self._value = v
self.valueChanged.emit(v)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.webEngineView = QtWebEngineWidgets.QWebEngineView()
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.resize(650, 610)
self.setWindowOpacity(0.99)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.setWindowIcon(icon)
lay = QtWidgets.QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(self.webEngineView)
backend = Backend(self)
backend.valueChanged.connect(self.foo_function)
self.channel = QtWebChannel.QWebChannel()
self.channel.registerObject("backend", backend)
self.webEngineView.page().setWebChannel(self.channel)
path = "http://localhost"
self.webEngineView.setUrl(QtCore.QUrl(path))
@QtCore.pyqtSlot(str)
def foo_function(self, value):
print("JS:", value)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
片段html代码
<div id="header" style="top: 0;" class="header">
<button ondblclick="$('#div_console').fadeIn('fast')" class="ui-btn modales" id="btn_title" value="title" title="Bankus"><i style="color:#007bff" class="fas fa-eye"></i></button>
<span id="title_text">Bankus 1.0</span>
<button title="Cerrar" id="btn_exit" value="exit" onclick="json($(this))" class="ui-btn closee modales"><svg viewBox="0 0 10 10"><polygon points="10.2,0.7 9.5,0 5.1,4.4 0.7,0 0,0.7 4.4,5.1 0,9.5 0.7,10.2 5.1,5.8 9.5,10.2 10.2,9.5 5.8,5.1" /></svg></button>
<button title="Maximizar" id="btn_maxi" value="maxi" onclick="json($(this))" class="ui-btn maximize modales"><svg viewBox="0 0 10 10"><path d="M0,0v10h10V0H0z M9,9H1V1h8V9z" /></svg></button>
<button title="Retaurar" id="btn_maxi" value="norm" onclick="json($(this))" class="ui-btn maximize modales invisi"><svg viewBox="0 0 10.2 10.1"><path d="M2.1,0v2H0v8.1h8.2v-2h2V0H2.1z M7.2,9.2H1.1V3h6.1V9.2z M9.2,7.1h-1V2H3.1V1h6.1V7.1z" /></svg></button>
<button title="Minimizar" id="btn_mini" value="mini" onclick="json($(this))" class="ui-btn minimize modales"><svg x="0px" y="0px" viewBox="0 0 10.2 1"><rect x="0" y="50%" width="10.2" height="1" /></svg></button>
<button title="Captura de pantalla" id="btn_capt" value="capt" onclick="json($(this))" class="ui-btn modales"><svg id="capture" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 64 64"><polygon fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4" points="47 12 42.88 8 21.12 8 17 12 2 12 2 56 62 56 62 12 47 12"/><circle cx="32" cy="34" r="14" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/><path fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="2" d="M10,21h0a1,1,0,0,1-1-1H9a1,1,0,0,1,1-1h0a1,1,0,0,1,1,1h0A1,1,0,0,1,10,21Z"/></svg></button>
</div>
github 上的完整 html 代码:https://github.com/onimac92/bankus/blob/master/index.html
代码最少 html:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
margin: 0;
}
#header {
width: 100%;
height: 30px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="header"></div>
</body>
</html>
您必须检测鼠标事件,将它们发送到 python 并执行 window 移动:
main.py
import json
import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class WindowManager(QtCore.QObject):
def __init__(self, window, parent=None):
super().__init__(parent)
self._window = window
self._drag_position = QtCore.QPoint()
@property
def window(self):
return self._window
@QtCore.pyqtSlot(str)
def mousePressEvent(self, string_event):
event = json.loads(string_event)
if event["which"] == 1:
gp = QtCore.QPoint(event["screenX"], event["screenY"])
self.drag_position = gp - self.window.frameGeometry().topLeft()
@QtCore.pyqtSlot(str)
def mouseMoveEvent(self, string_event):
event = json.loads(string_event)
if event["which"] == 1:
gp = QtCore.QPoint(event["screenX"], event["screenY"])
self.window.move(gp - self.drag_position)
class WebEngineView(QtWebEngineWidgets.QWebEngineView):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowOpacity(0.99)
self.resize(640, 480)
icon = QtGui.QIcon()
icon.addPixmap(
QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off
)
self.setWindowIcon(icon)
self.window_manager = WindowManager(self.window())
self.channel = QtWebChannel.QWebChannel()
self.channel.registerObject("window_manager", self.window_manager)
self.page().setWebChannel(self.channel)
current_dir = os.path.dirname(os.path.realpath(__file__))
self.load(QtCore.QUrl.fromLocalFile(os.path.join(current_dir, "index.html")))
if __name__ == "__main__":
import sys
sys.argv.append("--remote-debugging-port=8000")
app = QtWidgets.QApplication(sys.argv)
w = WebEngineView()
w.show()
sys.exit(app.exec_())
index.html
<!DOCTYPE html>
<html>
<head>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<style type="text/css">
body {
margin: 0;
}
#header {
width: 100%;
height: 30px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="header"></div>
<script type="text/javascript">
function event_to_string(event){
return JSON.stringify({"screenX": event.screenX, "screenY": event.screenY, "which": event.which})
}
var window_manager = null;
if (typeof QWebChannel !== "undefined") {
new QWebChannel(qt.webChannelTransport, function (channel) {
window_manager = channel.objects.window_manager;
var header = document.getElementById("header")
header.addEventListener('mousedown', function(event){
window_manager.mousePressEvent(event_to_string(event))
});
header.addEventListener('mousemove', function(event){
window_manager.mouseMoveEvent(event_to_string(event))
});
});
}
</script>
</body>