【发布时间】:2019-12-01 16:05:40
【问题描述】:
我想在鼠标用于draw in one of the two QGraphicsView 时跟踪calculation (of values for progress bars) 的鼠标移动。使用下面的代码,您可以在QGraphicsView 或中绘制鼠标在gridLayout 上移动的坐标,但不能同时进行两者。如何做到这一点?
main.py
>import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QCursor, QPainterPath, QPen
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPathItem
from PyQt5.uic import loadUi
app = None
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
loadUi("mainwindow.ui", self)
self.showMaximized()
self.setMouseTracking(True)
self.centralWidget().setAttribute(Qt.WA_MouseTracking)
self._old_x = QCursor.pos().x()
self._old_y = QCursor.pos().y()
self.verticalLayout_top.addWidget(GraphicsView())
self.verticalLayout_bottom.addWidget(GraphicsView())
@staticmethod
def _update_bar(progress_bar, delta):
current_value = progress_bar.value()
new_value = current_value + delta
progress_bar.setValue(new_value)
def mouseMoveEvent(self, event):
new_x = event.x()
new_y = event.y()
if new_x > self._old_x:
self._update_bar(self.progressBar_x_plus, new_x - self._old_x)
if new_x < self._old_x:
self._update_bar(self.progressBar_x_minus, self._old_x - new_x)
if new_y > self._old_y:
self._update_bar(self.progressBar_y_plus, new_y - self._old_y)
if new_y < self._old_y:
self._update_bar(self.progressBar_y_minus, self._old_y - new_y)
self._old_x = new_x
self._old_y = new_y
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.start = None
self.end = None
self.setScene(QGraphicsScene())
self.path = QPainterPath()
self.item = GraphicsPathItem()
self.scene().addItem(self.item)
self.contents_rect = self.contentsRect()
self.setSceneRect(0, 0, self.contents_rect.width(), self.contents_rect.height())
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def mousePressEvent(self, event):
self.start = self.mapToScene(event.pos())
self.path.moveTo(self.start)
def mouseMoveEvent(self, event):
self.end = self.mapToScene(event.pos())
self.path.lineTo(self.end)
self.start = self.end
self.item.setPath(self.path)
class GraphicsPathItem(QGraphicsPathItem):
def __init__(self):
super().__init__()
pen = QPen()
pen.setColor(Qt.black)
pen.setWidth(5)
self.setPen(pen)
def main():
global app
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
主窗口.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1003</width>
<height>703</height>
</rect>
</property>
<property name="windowTitle">
<string>Mouse Pointer</string>
</property>
<property name="locale">
<locale language="English" country="UnitedKingdom"/>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_top"/>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_x_plus">
<property name="text">
<string>X+</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QProgressBar" name="progressBar_x_plus">
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_x_minus">
<property name="text">
<string>X-</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QProgressBar" name="progressBar_x_minus">
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_y_plus">
<property name="text">
<string>Y+</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QProgressBar" name="progressBar_y_plus">
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_y_minus">
<property name="text">
<string>Y-</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QProgressBar" name="progressBar_y_minus">
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_bottom"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1003</width>
<height>24</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
更新 1:尝试在整个窗口上跟踪鼠标移动:
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
loadUi("mainwindow.ui", self)
self.showMaximized()
self.global_pos = QCursor.pos()
for lay in (self.verticalLayout_top, self.verticalLayout_bottom):
view = GraphicsView()
listener = MouseListener(view.viewport())
listener.posChanged.connect(self.on_pos_changed)
lay.addWidget(view)
window_listener = MouseListener(self)
window_listener.posChanged.connect(self.on_pos_changed)
更新 2
import sys
from PyQt5.QtCore import Qt, QObject, pyqtSignal, QPoint, QEvent
from PyQt5.QtGui import QCursor, QPainterPath, QPen
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPathItem, QWidget
from PyQt5.uic import loadUi
app = None
class MouseListener(QObject):
posChanged = pyqtSignal(QPoint)
def __init__(self, widget):
super().__init__(widget)
self._widget = widget
self._childrens = []
self._setup_widget(self._widget)
for w in self._widget.findChildren(QWidget):
self._setup_widget(w)
self._childrens.append(w)
def _setup_widget(self, w):
w.installEventFilter(self)
w.setMouseTracking(True)
def eventFilter(self, obj, event):
# if obj in [self._widget] + self._childrens and event.type() == QEvent.MouseMove:
if event.type() == QEvent.MouseMove:
self.posChanged.emit(event.globalPos())
if event.type() == QEvent.ChildAdded:
obj = event.child()
if obj.isWidgetType():
self._setup_widget(obj)
self._childrens.append(obj)
if event.type() == QEvent.ChildRemoved:
c = event.child()
if c in self._childrens:
c.removeEventFilter(self)
self._childrens.remove(c)
return super().eventFilter(obj, event)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
loadUi("mainwindow.ui", self)
self.showMaximized()
self.global_pos = QCursor.pos()
for lay in (self.verticalLayout_top, self.verticalLayout_bottom):
view = GraphicsView()
listener = MouseListener(view.viewport())
listener.posChanged.connect(self.on_pos_changed)
lay.addWidget(view)
# window_listener = MouseListener(self)
# window_listener.posChanged.connect(self.on_pos_changed)
@staticmethod
def _update_bar(progress_bar, delta):
current_value = progress_bar.value()
new_value = current_value + delta
progress_bar.setValue(new_value)
def on_pos_changed(self, pos):
new_x = pos.x()
new_y = pos.y()
old_x = self.global_pos.x()
old_y = self.global_pos.y()
if new_x > old_x:
self._update_bar(self.progressBar_x_plus, new_x - old_x)
if new_x < old_x:
self._update_bar(self.progressBar_x_minus, old_x - new_x)
if new_y > old_y:
self._update_bar(self.progressBar_y_plus, new_y - old_y)
if new_y < old_y:
self._update_bar(self.progressBar_y_minus, old_y - new_y)
self.global_pos = pos
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.start = None
self.end = None
self.setScene(QGraphicsScene())
self.path = QPainterPath()
self.item = GraphicsPathItem()
self.scene().addItem(self.item)
self.contents_rect = self.contentsRect()
self.setSceneRect(0, 0, self.contents_rect.width(), self.contents_rect.height())
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def mousePressEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.start = self.mapToScene(event.pos())
self.path.moveTo(self.start)
# super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.end = self.mapToScene(event.pos())
self.path.lineTo(self.end)
self.start = self.end
self.item.setPath(self.path)
# super().mouseMoveEvent(event)
class GraphicsPathItem(QGraphicsPathItem):
def __init__(self):
super().__init__()
pen = QPen()
pen.setColor(Qt.black)
pen.setWidth(5)
self.setPen(pen)
def main():
global app
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
【问题讨论】: