Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing multi select bind key in QGraphicsScene

I'm subclassing QGraphicsScene in PyQT and want to use Shift key (modifier) for multi-select items instead of control key.

I can do so by subclassing it and making my own mousePressedEvent, but then when I do that, the graphicsItem in the scene acting weird when I start dragging them.

All I need is to change the control key to shift key for multi select. I would appreciate if anyone could help.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class GraphicsScene(QGraphicsScene):
    def __init__(self, parent=None, ns=""):
        super(GraphicsScene, self).__init__(parent)
        self.parent = parent
        self.prevItem = []
        self.ns = ns
        self.setBackgroundBrush(QBrush(QColor(50,50,50) , Qt.SolidPattern))


    def mouseReleaseEvent(self, event):
        if event.button() == 2: #Right mouse click
            #Set previous selections selected
            for item in self.prevItem:
                item.setSelected(1)

            item = self.itemAt(event.lastScenePos ().x(), event.lastScenePos ().y())
            if item:
                item.setSelected(1)

        if event.button() == 1: # Left mouse click
            #Get selected item
            items = self.selectedItems()

            #Shift click
            if event.modifiers() & Qt.ShiftModifier: 
                #Set previous items selected
                for item in self.prevItem:
                    item.setSelected(1)

                for item in items:
                    self.prevItem.append(item)

                item = self.itemAt(event.scenePos ().x(), event.scenePos ().y())
                if item == None:
                    self.clearSelection()

            else:
                self.prevItem = []
                for item in items:
                    self.prevItem.append(item)

        super(GraphicsScene, self).mouseReleaseEvent(event)

    def mousePressEvent(self, event):
        if event.modifiers() & Qt.ShiftModifier:
            item = self.itemAt(event.scenePos ().x(), event.scenePos ().y())
            if item:
                item.setSelected(1)

        super(GraphicsScene, self).mousePressEvent(event)

class MainClass(QMainWindow):
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__(parent)        

        self.setGeometry(50,50,400,600)

        widget = QWidget()
        self.setCentralWidget(widget)
        layout = QGridLayout()
        layout.setMargin(3)

        widget.setLayout(layout)

        view = QGraphicsView()
        view.setMouseTracking(1)
        view.setDragMode(QGraphicsView.RubberBandDrag)
        view.setRenderHint(QPainter.Antialiasing)
        view.setRenderHint(QPainter.TextAntialiasing)
        view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) 
        view.setAlignment(Qt.AlignJustify)


        scene = GraphicsScene(self)
        scene.setSceneRect(0,0, 300, 500)


        view.setScene(scene)
        layout.addWidget(view)

        elipseOne = QGraphicsEllipseItem (30,30,30,30, parent=None, scene=scene)
        elipseOne.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)

        elipseTwo = QGraphicsEllipseItem (60,60,30,30, parent=None, scene=scene)
        elipseTwo.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)

win = MainClass()
win.show()
like image 680
user2237951 Avatar asked Nov 12 '22 08:11

user2237951


1 Answers

Modified your mousePress and mouseRelease events hope it's helpful

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
from collections import deque

class GraphicsScene(QGraphicsScene):
    def __init__(self, parent=None, ns=""):
        super(GraphicsScene, self).__init__(parent)
        self.parent = parent
        self._selectedItemVec = deque()
        self.ns = ns
        self.setBackgroundBrush(QBrush(QColor(50,50,50) , Qt.SolidPattern))

    def mouseReleaseEvent(self, event):
        item = self.itemAt(event.scenePos ().x(), event.scenePos ().y())
        if item:
            item.setSelected(1)
        else:
            if len(self._selectedItemVec):
                self._selectedItemVec.popleft()
                return QGraphicsScene.mouseReleaseEvent(self, event)
        if event.modifiers() & Qt.ShiftModifier:
            for item in self._selectedItemVec:
                item.setSelected(1)
        else:
            self._selectedItemVec.popleft()

    def mousePressEvent(self, event):

        item = self.itemAt(event.scenePos ().x(), event.scenePos ().y())
        if item:
            item.setSelected(1)
            self._selectedItemVec.append(item)
        else:
            return QGraphicsScene.mousePressEvent(self, event)


class MainClass(QMainWindow):
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__(parent)        

        self.setGeometry(50,50,400,600)

        widget = QWidget()
        self.setCentralWidget(widget)
        layout = QGridLayout()
        layout.setMargin(3)

        widget.setLayout(layout)

        view = QGraphicsView()
        view.setMouseTracking(1)
        view.setDragMode(QGraphicsView.RubberBandDrag)
        view.setRenderHint(QPainter.Antialiasing)
        view.setRenderHint(QPainter.TextAntialiasing)
        view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) 
        view.setAlignment(Qt.AlignJustify)


        scene = GraphicsScene(self)
        scene.setSceneRect(0,0, 300, 500)


        view.setScene(scene)
        layout.addWidget(view)

        elipseOne = QGraphicsEllipseItem (30,30,30,30, parent=None, scene=scene)
        elipseOne.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)

        elipseTwo = QGraphicsEllipseItem (60,60,30,30, parent=None, scene=scene)
        elipseTwo.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)
if __name__ == '__main__':

    app = QApplication(sys.argv)
    win = MainClass()
    win.show()
    sys.exit(app.exec_())
like image 176
smitkpatel Avatar answered Dec 28 '22 07:12

smitkpatel