Felix
Felix

Reputation: 3591

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

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?

Upvotes: 5

Views: 2309

Answers (2)

Kaaf
Kaaf

Reputation: 380

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);
}

Upvotes: 5

goug
goug

Reputation: 2444

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.

Upvotes: 4

Related Questions