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:
Within Qt, is a graphic item selected when moved and unselected when released?
How might a graphic item remain selected after mouse release? For example, should I create a Boolean variable in "Line" called self.selected?
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?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With