QGraphicsView: how to make rubber band selection appear only on left mouse button?
Asked Answered
O

2

5

I want to make a QGraphicsScene and show it in QGraphicsView. I want to scroll the scene by middle mouse button and make rubber band selection by left button. But I don't know how to make the rubber band selection appear only by left mouse button.

Here's my code:

# -*- coding: utf-8 -*-

import os, sys

from PyQt5 import QtWidgets, QtCore, QtGui, QtSvg

class MegaSceneView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(MegaSceneView, self).__init__(parent)
        self._scale_factor = 1.0

        self._scale_by = 1.2
        self.setAcceptDrops(True)

        self.setRenderHint(QtGui.QPainter.Antialiasing)
        self.setMouseTracking(True)
        self.setRubberBandSelectionMode(QtCore.Qt.IntersectsItemShape)
        self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)

        self._prev_mouse_scene_pos = None


    def mousePressEvent(self, event):
        if (event.buttons() & QtCore.Qt.MidButton) != QtCore.Qt.NoButton:
            self._prev_mouse_scene_pos = (event.pos())
        super(MegaSceneView, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        super(MegaSceneView, self).mouseReleaseEvent(event)
        self._prev_mouse_scene_pos = None

    def mouseMoveEvent(self, event):
        super(MegaSceneView, self).mouseMoveEvent(event)

        if (event.buttons() & QtCore.Qt.MidButton) != QtCore.Qt.NoButton:
            cur_mouse_pos = (event.pos())
            if self._prev_mouse_scene_pos is not None:
                delta_x = cur_mouse_pos.x() - self._prev_mouse_scene_pos.x()
                delta_y = cur_mouse_pos.y() - self._prev_mouse_scene_pos.y()

                self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - delta_x)
                self.verticalScrollBar().setValue(self.verticalScrollBar().value() - delta_y)

            self._prev_mouse_scene_pos = (event.pos())

if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)

    mega_view = MegaSceneView()

    mega_scene = QtWidgets.QGraphicsScene(-500, -500, 1000, 1000)
    # mega_scene = QtWidgets.QGraphicsScene()

    rect_item_1 = QtWidgets.QGraphicsRectItem(-30, -20, 60, 40)
    mega_scene.addItem(rect_item_1)

    rect_item_2 = QtWidgets.QGraphicsRectItem(-20, -30, 40, 60)
    mega_scene.addItem(rect_item_2)
    rect_item_2.setPos(300, 200)

    mega_view.setScene(mega_scene)
    mega_view.show()

    sys.exit(app.exec_())

What should I add to make the rubber band appear only by left button?

Ostler answered 9/3, 2017 at 10:30 Comment(0)
G
5

You can set the drag mode in the mousePressEvent and mouseReleaseEvent functions in your view class, so it stays in the RubberBandDrag as default, but switches to NoDrag mode when the middle mouse button is held.

Like so - c++, but the idea is the same in all languages - :

void YourViewClass::mousePressEvent(QMouseEvent* event)    {
    if (event->buttons() == Qt::MiddleButton)
        setDragMode(QGraphicsView::NoDrag);
}

void YourViewClass::mouseReleaseEvent(QMouseEvent* event)    {
    if (event->button() == Qt::MiddleButton)
        setDragMode(QGraphicsView::RubberBandDrag);
}
Grandmotherly answered 18/11, 2020 at 0:17 Comment(0)
V
4

There isn't a built-in way to do this. You will need to subclass the mousePressEvent, mouseMoveEvent, and mouseReleaseEvent for your graphics view and create the visible rubber band yourself. (QRubberBand works well for this.) When the user releases the mouse, you then need to convert the rubber band extents into scene coordinates and call QGraphicsScene::setSelectionArea.

Voluntary answered 9/3, 2017 at 23:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.