3

I need to create several movable, selectable graphic items. An item stays selected until a different item is selected or until the user clicks an empty part of the scene, deselecting all items. The selected item must look different than the unselected items. Any widget of the main window should be able to query whether a graphic item is selected and--if so--which one.

This code permits items to be selected and moved on the screen. The items turn red when moved:

import sys
from PySide import QtGui, QtCore

class MainWindowUi(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.scene = Scene(0, 0, 300, 300, self)
        self.view = QtGui.QGraphicsView()
        self.setCentralWidget(self.view)
        self.view.setScene(self.scene)
        self.scene.addItem(Line(25,25,25,50))
        self.scene.addItem(Line(30,30,30,70))
        self.scene.addItem(Line(35, 40, 35, 65))

class Scene(QtGui.QGraphicsScene):
    pass

class Line(QtGui.QGraphicsLineItem):
    def __init__(self, *args):
        QtGui.QGraphicsLineItem.__init__(self)
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.setPen(QtGui.QPen(QtCore.Qt.black, 3))

    def mousePressEvent(self, e):
        self.setPen(QtGui.QPen(QtCore.Qt.red, 5))
        QtGui.QGraphicsLineItem.mousePressEvent(self, e)

    def mouseReleaseEvent(self, e):
        self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
        QtGui.QGraphicsLineItem.mouseReleaseEvent(self, e)

if __name__ == '__main__':
    a = QtGui.QApplication(sys.argv)
    m = MainWindowUi()
    m.show()
    sys.exit(a.exec_())

Here are my questions:

  1. Within Qt, is a graphic item selected when moved and unselected when released?

  2. How might a graphic item remain selected after mouse release? For example, should I create a Boolean variable in "Line" called self.selected?

  3. How can the application query which graphic item is selected and differentiate between them? For example, should each item in the class "Line" be assigned a unique ID or does Qt already do that?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Graph.One
  • 45
  • 1
  • 4

2 Answers2

2

Within Qt, is a graphic item selected when moved and unselected when released?

An item is selected when an item is clicked, and deselected when you choose another item or when you click on an empty area.

How might a graphic item remain selected after mouse release? For example, should I create a Boolean variable in "Line" called self.selected?

From the previous answer the element remains selected, in addition there is already the function selected() that returns True or False and if the item is selected or not.

How can the application query which graphic item is selected and differentiate between them? For example, should each item in the class "Line" be assigned a unique ID or does Qt already do that?

QGraphicsScene has the selectedItems() method that returns the selected items. Qt does not provide an ID or something similar, to perform that task we can use the setData() and data() method, the first one saves some information through a key and the other recovers it with the same key.

To detect the changes in the items you must overwrite the itemChange() method, this gives us the type of change and the value for this change. In your case you should verify that the change must be of the ItemSelectedChange type and the value True if it is selected or False if it is deselected.

def itemChange(self, change, value):
    if change == QtGui.QGraphicsItem.ItemSelectedChange:
        if value:
            self.setPen(QtGui.QPen(QtCore.Qt.red, 3))
        else:
            self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
    return QtGui.QGraphicsLineItem.itemChange(self, change, value)

Example:

class MainWindowUi(QtGui.QMainWindow):
    def __init__(self, *args, **kwargs):
        QtGui.QMainWindow.__init__(self, *args, **kwargs)
        self.scene = Scene(0, 0, 300, 300, self)
        self.view = QtGui.QGraphicsView(self)
        self.setCentralWidget(self.view)
        self.view.setScene(self.scene)
        self.scene.addItem(Line(25, 25, 25, 50))
        self.scene.addItem(Line(30, 30, 30, 70))
        self.scene.addItem(Line(35, 40, 35, 65))
        self.scene.selectionChanged.connect(self.onSelectionChanged)

    def onSelectionChanged(self):
        message = "Items selecteds: "
        for item in self.scene.selectedItems():
            message += " " + item.data(Scene.NameItem)
        self.statusBar().showMessage(message)


class Scene(QtGui.QGraphicsScene):
    NameItem = 1

    def __init__(self, *args, **kwargs):
        QtGui.QGraphicsScene.__init__(self, *args, **kwargs)
        self.counterItems = 0

    def addItem(self, item):
        item.setData(Scene.NameItem, "item {}".format(self.counterItems))
        self.counterItems += 1
        QtGui.QGraphicsScene.addItem(self, item)


class Line(QtGui.QGraphicsLineItem):
    def __init__(self, *args, **kwargs):
        QtGui.QGraphicsLineItem.__init__(self, *args, **kwargs)
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.setPen(QtGui.QPen(QtCore.Qt.black, 3))

    def itemChange(self, change, value):
        if change == QtGui.QGraphicsItem.ItemSelectedChange:
            if value:
                self.setPen(QtGui.QPen(QtCore.Qt.red, 3))
            else:
                self.setPen(QtGui.QPen(QtCore.Qt.black, 3))
        return QtGui.QGraphicsLineItem.itemChange(self, change, value)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
0

Within Qt, is a graphic item selected when moved and unselected when released?

No, by default a qgraphics item get selected on mouse click, and it stays selected even when the mouse get released.

How might a graphic item remain selected after mouse release? For example, should I create a Boolean variable in "Line" called self.selected?

A qgraphics item knows whether it is selected, you can ask to it querying its isSelected() method.

How can the application query which graphic item is selected and differentiate between them? For example, should each item in the class "Line" be assigned a unique ID or does Qt already do that?

From the application point of view, it can gets all the selected items calling the QGraphicsScene::selectedItems() method.

You might read the graphics api documentation that describe how to use it.