同时跟踪多个小部件中的鼠标移动

问题描述 投票:1回答:1

当鼠标习惯于calculation (of values for progress bars)时,我想跟踪draw in one of the two QGraphicsView的鼠标移动。使用下面的代码,您可以在QGraphicsView 中绘制,以获取鼠标在QGraphicsView上的移动坐标,但不能一次绘制两个坐标。如何做到这一点?


main.py

gridLayout

mainwindow.ui

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()
python pyqt pyqt5
1个回答
2
投票

问题是,除了您的重写mouseMoveEvent的策略外,mousePressEvent不一定从父窗口小部件传播到子窗口小部件(行为取决于每种类型的窗口小部件,例如QLabel如果它传播鼠标事件)。如果您想听其他小部件的事件,则方法是有限的。

考虑到上述情况,一种可能的解决方案是使用eventFilter侦听任何小部件的事件,另一个改进是使用全局位置而不是局部位置,以便当鼠标从QGraphicsView更改时不受以下影响。本地坐标系。

<?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>

更新:

class MouseListener(QObject):
    posChanged = pyqtSignal(QPoint)

    def __init__(self, widget):
        super().__init__(widget)
        self._widget = widget
        self._widget.setMouseTracking(True)
        self._widget.installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj is self._widget and event.type() == QEvent.MouseMove:
            self.posChanged.emit(event.globalPos())
        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)

    @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
© www.soinside.com 2019 - 2024. All rights reserved.