Update the Opacity of QGraphicsItem - python

I want to update the opacity of some QGraphicsItem after the mouse clicking. As suggested from other solution, the QGraphicScene manually update the GraphicsItem after the mouser press event. I have tried different setOpacity() and update() in QGraphicsScene and QGraphicsItem. But none works and do not know what is wrong.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
CUBE_POS = {
"a":( 8.281, 18.890),
"b":( 8.668, 23.692),
"c":( 21.493, 23.423),
"d":( 21.24, 15.955),
}
class CubeItem(QGraphicsItem):
def __init__(self, x, y, parent=None):
super(CubeItem,self).__init__(parent)
self.x = x
self.y = y
self.polygon = QPolygonF([
QPointF(self.x-10, self.y-10), QPointF(self.x-10, self.y+10),
QPointF(self.x+10, self.y+10), QPointF(self.x+10, self.y-10),
])
self._painter = QPainter()
##Estimate the drawing area
def boundingRect(self):
return QRectF(self.x-10, self.y-10, 20, 20)
##Real Shape of drawing area
def shape(self):
path = QPainterPath()
path.addRect(self.x-10, self.y-10, 20, 20)
return path
##paint function called by graphicview
def paint(self, painter, option, widget):
painter.setBrush(Qt.red)
painter.setOpacity(0.2)
painter.drawRect(self.x-10, self.y-10, 20, 20)
self._painter = painter
def activate(self):
try:
#self._painter.setOpacity(1.0)
self.setOpacity(1.0)
self.update()
except ValueError as e:
print(e)
class TagScene(QGraphicsScene):
def __init__(self, parent=None):
super(TagScene, self).__init__(parent)
self.cubes_items_ref = {}
self.addCubes()
def addCubes(self):
for cube in CUBE_POS:
newCube = CubeItem(CUBE_POS[cube][0]*15,
CUBE_POS[cube][1]*15)
self.addItem(newCube)
self.cubes_items_ref[cube] = newCube
def mousePressEvent(self, event):
print("mouse pressed")
#for cube in self.cubes_items_ref:
# self.cubes_items_ref[cube].setOpacity(1.0)
# #self.cubes_items_ref[cube].activate()
#self.update(QRectF(0,0,500,500))
for cube in self.items():
cube.setOpacity(1.0)
self.update(QRectF(0,0,500,500))
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
layout = QHBoxLayout()
self.scene = TagScene()
self.view = QGraphicsView(self.scene)
self.scene.setSceneRect(QRectF(0,0,500,500))
layout.addWidget(self.view)
self.widget = QWidget()
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())

The problem is that when you overwrite the paint method of the QGraphicsItem you are setting a constant opacity
def paint(self, painter, option, widget):
painter.setBrush(Qt.red)
painter.setOpacity(0.2) # <-- this line is the problem
painter.drawRect(self.x-10, self.y-10, 20, 20)
self._painter = painter
And you will not use the opacity that the QPainter already passes paint() method.
If you want to set an initial opacity you must do it in the constructor.On the other hand the setOpacity() method already calls update() so it is not necessary to make an explicit call.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
CUBE_POS = {
"a": (8.281, 18.890),
"b": (8.668, 23.692),
"c": (21.493, 23.423),
"d": (21.24, 15.955),
}
class CubeItem(QtWidgets.QGraphicsItem):
def __init__(self, x, y, parent=None):
super(CubeItem, self).__init__(parent)
self.x = x
self.y = y
self.polygon = QtGui.QPolygonF(
[
QtCore.QPointF(self.x - 10, self.y - 10),
QtCore.QPointF(self.x - 10, self.y + 10),
QtCore.QPointF(self.x + 10, self.y + 10),
QtCore.QPointF(self.x + 10, self.y - 10),
]
)
self.setOpacity(0.2) # initial opacity
##Estimate the drawing area
def boundingRect(self):
return QtCore.QRectF(self.x - 10, self.y - 10, 20, 20)
##Real Shape of drawing area
def shape(self):
path = QtGui.QPainterPath()
path.addRect(self.boundingRect())
return path
##paint function called by graphicview
def paint(self, painter, option, widget):
painter.setBrush(QtCore.Qt.red)
painter.drawRect(self.x - 10, self.y - 10, 20, 20)
class TagScene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super(TagScene, self).__init__(parent)
self.cubes_items_ref = {}
self.addCubes()
def addCubes(self):
for cube in CUBE_POS:
newCube = CubeItem(CUBE_POS[cube][0] * 15, CUBE_POS[cube][1] * 15)
self.addItem(newCube)
self.cubes_items_ref[cube] = newCube
def mousePressEvent(self, event):
for cube in self.items():
cube.setOpacity(1.0) # update opacity
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
layout = QtWidgets.QHBoxLayout()
self.scene = TagScene()
self.view = QtWidgets.QGraphicsView(self.scene)
self.scene.setSceneRect(QtCore.QRectF(0, 0, 500, 500))
layout.addWidget(self.view)
self.widget = QtWidgets.QWidget()
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())

Related

custom QGraphicsItem unwanted behaviour after overriding mouse event

I am trying to model a chess board and i want the pawn GraphicsItem object to be dropped in the center of the case GraphicsItem object .
i only implemented a mouseRelease event for the pawn object, it checks the list of items in the position, if a case is present i drop the pawn at the case position .
now when trying it in the window it works fine for the first move, but after that when i try to move the pawn it goes back to its original position i can still move it but its not under the mouse cursor
here is the code:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout,
QGraphicsView, QGraphicsScene, QGraphicsItem)
from PyQt5.QtGui import QPen, QBrush, QTransform
from PyQt5.QtCore import Qt, QRectF, QPointF
class Pawn(QGraphicsItem):
def __init__(self, parent = None):
super().__init__(parent)
self.setFlag(QGraphicsItem.ItemIsMovable)
self.setPos(0, 0)
self.setZValue(1)
self.originalPos = self.scenePos()
def paint(self, painter, options, widget):
painter.setBrush(Qt.white)
painter.drawEllipse(0, 0, 30, 30)
def boundingRect(self):
return QRectF(0, 0, 30, 30)
def mouseReleaseEvent(self, event):
dropPos = self.mapToScene(event.pos())
dropCase = None
for item in self.scene().items(dropPos.x(), dropPos.y(), 0.0001, 0.0001,
Qt.IntersectsItemShape,
Qt.AscendingOrder):
if isinstance(item, Case):
dropCase = item
if dropCase:
newP = dropCase.scenePos()
self.setPos(newP)
self.originalPos = newP
else:
self.setPos(self.originalPos)
class Case(QGraphicsItem):
def __init__(self, parent = None):
super().__init__(parent)
self.setPos(100, 0)
self.setZValue(0)
def paint(self, painter, options, widget):
painter.setPen(Qt.black)
painter.setBrush(Qt.black)
painter.drawRect(0, 0, 40, 40)
def boundingRect(self):
return QRectF(0, 0, 40, 40)
def getCenter(self):
x, y = self.scenePos().x() + 10, self.scenePos().y() + 10
return QPointF(x, y)
class MainWin(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
scene = QGraphicsScene()
view = QGraphicsView(scene, self)
view.setGeometry(0, 0, 290, 290)
case = Case()
pawn = Pawn()
scene.addItem(case)
scene.addItem(pawn)
self.setWindowTitle('doodling')
self.setGeometry(200, 200, 300, 300)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWin()
sys.exit(app.exec_())
I did not implement the mouseMoveEvent as i confused it with hover behaviour.
this code works as intended
from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout,
QGraphicsView, QGraphicsScene, QGraphicsItem)
from PyQt5.QtGui import QPen, QBrush, QTransform
from PyQt5.QtCore import Qt, QRectF, QPointF
class Pawn(QGraphicsItem):
def __init__(self, parent = None):
super().__init__(parent)
self.setFlag(QGraphicsItem.ItemIsMovable)
self.setPos(0, 0)
self.setZValue(1)
self.originalPos = self.scenePos()
def paint(self, painter, options, widget):
painter.setBrush(Qt.white)
painter.drawEllipse(0, 0, 30, 30)
def boundingRect(self):
return QRectF(0, 0, 30, 30)
def mouseMoveEvent(self, event):
movePos = self.mapToScene(event.pos())
self.setPos(movePos.x(), movePos.y())
def mouseReleaseEvent(self, event):
dropPos = self.mapToScene(event.pos())
dropCase = None
for item in self.scene().items(dropPos.x(), dropPos.y(), 0.0001, 0.0001,
Qt.IntersectsItemShape,
Qt.AscendingOrder):
if isinstance(item, Case):
dropCase = item
if dropCase:
newP = dropCase.scenePos()
self.setPos(newP)
self.originalPos = newP
else:
self.setPos(self.originalPos)
class Case(QGraphicsItem):
def __init__(self, x_coord, y_coord, parent = None):
super().__init__(parent)
self.setPos(x_coord, y_coord)
self.setZValue(0)
def paint(self, painter, options, widget):
painter.setPen(Qt.black)
painter.setBrush(Qt.black)
painter.drawRect(0, 0, 40, 40)
def boundingRect(self):
return QRectF(0, 0, 40, 40)
def getCenter(self):
x, y = self.scenePos().x() + 10, self.scenePos().y() + 10
return QPointF(x, y)
class MainWin(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
scene = QGraphicsScene()
view = QGraphicsView(scene, self)
view.setGeometry(0, 0, 290, 290)
case1 = Case(-100, 0)
case2 = Case(100, 0)
pawn = Pawn()
scene.addItem(case1)
scene.addItem(case2)
scene.addItem(pawn)
self.setWindowTitle('doodling')
self.setGeometry(200, 200, 300, 300)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWin()
sys.exit(app.exec_())

Graphics in PyQtGraph not updating after zoom

I have the following PyQtGraph program, which makes a red square "move" when moving a slider:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QSlider
from pyqtgraph import (
mkBrush,
mkPen,
GraphicsObject,
QtGui,
PlotWidget,
)
class SquareItem(GraphicsObject):
def __init__(self):
super().__init__()
self.position_picture = QtGui.QPicture()
def paint(self, p, *args):
p.drawPicture(0, 0, self.position_picture)
def boundingRect(self):
return QtCore.QRectF(-5, -5, 20, 10)
def update_position(self, x):
self.position_picture = QtGui.QPicture()
painter = QtGui.QPainter(self.position_picture)
painter.scale(1, -1)
painter.setBrush(mkBrush('r'))
painter.setPen(mkPen(None))
painter.drawRect(QtCore.QRectF(x, 0, 1, 1))
painter.end()
self.informViewBoundsChanged()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('Micromouse maze simulator')
self.resize(600, 600)
frame = QtWidgets.QFrame()
layout = QtWidgets.QVBoxLayout(frame)
self.graphics = PlotWidget()
self.graphics.setAspectLocked()
self.item = SquareItem()
self.graphics.addItem(self.item)
self.slider = QSlider(QtCore.Qt.Horizontal)
self.slider.setSingleStep(1)
self.slider.setPageStep(10)
self.slider.setRange(0, 10)
self.slider.setTickPosition(QSlider.TicksAbove)
self.slider.valueChanged.connect(self.slider_value_changed)
self.slider.setValue(1)
layout.addWidget(self.graphics)
layout.addWidget(self.slider)
self.setCentralWidget(frame)
def slider_value_changed(self, value):
self.item.update_position(value)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
Everything seems to work fine, but if I zoom in/out and then move the slider again the square position is no longer updated (i.e.: the square is not re-drawn).
How can I fix that?
Updates
I am using a square to simplify the problem. In reality, I do not only change position, but I can also draw different shapes, so using setPos() is not really an option.
You should not update the painting if you want to change position, you should only use setPos(). the paint() function takes boundingRect() as a reference so when moving the graph you are moving it in that coordinate system instead of the coordinate system of PlotWidget.
class SquareItem(GraphicsObject):
def paint(self, p, *args):
p.setBrush(mkBrush('r'))
p.setPen(mkPen(None))
p.drawRect(self.boundingRect())
def boundingRect(self):
return QtCore.QRectF(0, 0, 1, 1)
def update_position(self, x):
self.setPos(x, 0)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('Micromouse maze simulator')
self.resize(600, 600)
frame = QtWidgets.QFrame()
layout = QtWidgets.QVBoxLayout(frame)
self.graphics = PlotWidget()
self.graphics.setAspectLocked()
self.item = SquareItem()
self.graphics.addItem(self.item)
self.graphics.setRange(rect=QtCore.QRectF(-10, -10, 20, 20))
self.slider = QSlider(QtCore.Qt.Horizontal)
self.slider.setSingleStep(1)
self.slider.setPageStep(10)
self.slider.setRange(0, 10)
self.slider.setTickPosition(QSlider.TicksAbove)
self.slider.valueChanged.connect(self.slider_value_changed)
self.slider.setValue(1)
layout.addWidget(self.graphics)
layout.addWidget(self.slider)
self.setCentralWidget(frame)
def slider_value_changed(self, value):
self.item.update_position(value)
If you are not going to use signals it is advisable to use objects that inherit from QGraphicsItem instead of QGraphicsObject, for example you could use QGraphicsRectItem:
import sys
from PyQt5 import QtCore, QtWidgets
from pyqtgraph import (
mkBrush,
mkPen,
GraphicsObject,
QtGui,
PlotWidget,
)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('Micromouse maze simulator')
self.resize(600, 600)
frame = QtWidgets.QFrame()
layout = QtWidgets.QVBoxLayout(frame)
self.graphics = PlotWidget()
self.graphics.setAspectLocked()
self.item = QtWidgets.QGraphicsRectItem(0, 0, 1, 1)
self.item.setBrush(mkBrush('r'))
self.item.setPen(mkPen(None))
self.graphics.addItem(self.item)
self.graphics.setRange(rect=QtCore.QRectF(-10, -10, 20, 20))
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.slider.setSingleStep(1)
self.slider.setPageStep(10)
self.slider.setRange(0, 10)
self.slider.setTickPosition(QtWidgets.QSlider.TicksAbove)
self.slider.valueChanged.connect(self.slider_value_changed)
self.slider.setValue(1)
layout.addWidget(self.graphics)
layout.addWidget(self.slider)
self.setCentralWidget(frame)
def slider_value_changed(self, value):
self.item.setPos(value, 0)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
update:
If you want to redraw you should call update():
import sys
from PyQt5 import QtCore, QtWidgets
from pyqtgraph import (
mkBrush,
mkPen,
GraphicsObject,
QtGui,
PlotWidget,
)
class SquareItem(GraphicsObject):
colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k', 'w', 'FF0', 'AA0', '0AA']
def __init__(self):
super().__init__()
self.mColor = SquareItem.colors[0]
def paint(self, p, *args):
p.setBrush(mkBrush(self.mColor))
p.setPen(mkPen(None))
p.drawRect(self.boundingRect())
def boundingRect(self):
return QtCore.QRectF(0, 0, 1, 1)
def update_draw(self, x):
self.mColor = SquareItem.colors[x]
self.update()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('Micromouse maze simulator')
self.resize(600, 600)
frame = QtWidgets.QFrame()
layout = QtWidgets.QVBoxLayout(frame)
self.graphics = PlotWidget()
self.graphics.setAspectLocked()
self.item = SquareItem()
self.graphics.addItem(self.item)
self.graphics.setRange(rect=QtCore.QRectF(-10, -10, 20, 20))
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.slider.setSingleStep(1)
self.slider.setPageStep(10)
self.slider.setRange(0, 10)
self.slider.setTickPosition(QtWidgets.QSlider.TicksAbove)
self.slider.valueChanged.connect(self.item.update_draw)
self.slider.setValue(1)
layout.addWidget(self.graphics)
layout.addWidget(self.slider)
self.setCentralWidget(frame)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())

PyQt5: How to use signal+slot to transfer parameters for paintEvent?

For this question, I am referring to the code from https://gist.github.com/zhanglongqi/78d7b5cd24f7d0c42f5d116d967923e7
The code above shows how to draw an overlay onto current widget, which works fine. But I want to transfer parameters into the overlay class, and use these variables to trigger the paintEvent there in the overlay class.
I modified the code as follows...
# -*- coding:utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class overlay(QWidget):
def __init__(self, parent=None):
super(overlay, self).__init__(parent)
palette = QPalette(self.palette())
palette.setColor(palette.Background, Qt.transparent)
self.setPalette(palette)
#pyqtSlot(int)
def getValue(self, a): # variable is received.
self.a = a
print(self.a)
self.update()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(event.rect(), QBrush(QColor(255, 255, 255, 127)))
painter.drawLine(self.width() / 8, self.height() / 8, 7 * self.width() / 8, 7 * self.height() / 8)
painter.drawLine(self.width() / 8, 7 * self.height() / 8, 7 * self.width() / 8, self.height() / 8)
painter.drawLine(self.a , self.a+50, self.a +10, self.a + 100) #Here I want to draw the line using parameter.
painter.setPen(QPen(Qt.NoPen))
class windowOverlay(QWidget):
signal = pyqtSignal(int)
def __init__(self, parent=None):
super(windowOverlay, self).__init__(parent)
self.editor = QTextEdit()
self.editor.setPlainText("OVERLAY" * 100)
self.button = QPushButton("Toggle Overlay")
self.verticalLayout = QVBoxLayout(self)
self.verticalLayout.addWidget(self.editor)
self.verticalLayout.addWidget(self.button)
self.overlay = overlay(self.editor)
self.overlay.hide()
self.button.clicked.connect(self.switch_and_send_signal)
def switch_and_send_signal(self):
if self.overlay.isVisible():
self.overlay.setVisible(False)
else:
self.overlay.setVisible(True)
self.obj = overlay()
a = 100
self.signal.connect(self.obj.getValue)
self.signal.emit(a)
self.signal.disconnect(self.obj.getValue)
def resizeEvent(self, event):
self.overlay.resize(event.size())
event.accept()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = windowOverlay()
main.show()
sys.exit(app.exec_())
The Problem:
It seems the parameter is transferred, but the paintEvent is not updated. The parameter does not arrive the paintEvent. What am I doing wrong?
Thanks for the help!
The problem is caused because you are creating an overlay object that is not connected, what you must do is use the same object as I show below:
class windowOverlay(QWidget):
signal = pyqtSignal(int)
def __init__(self, parent=None):
super(windowOverlay, self).__init__(parent)
self.editor = QTextEdit()
self.editor.setPlainText("OVERLAY" * 100)
self.button = QPushButton("Toggle Overlay")
self.verticalLayout = QVBoxLayout(self)
self.verticalLayout.addWidget(self.editor)
self.verticalLayout.addWidget(self.button)
self.overlay = overlay(self.editor)
self.overlay.hide()
self.signal.connect(self.overlay.getValue)
self.button.clicked.connect(self.switch_and_send_signal)
def switch_and_send_signal(self):
self.overlay.setVisible(not self.overlay.isVisible())
a = 100
self.signal.emit(a)
def resizeEvent(self, event):
self.overlay.resize(event.size())
event.accept()

Paint ticks on custom QProgressBar in Pyside

I'm trying to paint some ticks in my custom progressbar but I'm not clear on why the line isn't showing up at all?
import sys
import os
sys.path.append('Z:\\pipeline\\site-packages')
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from PySide import QtGui, QtCore
class QProgressBarPro(QtGui.QProgressBar):
progressClicked = QtCore.Signal()
progressChanging = QtCore.Signal()
progressChanged = QtCore.Signal()
def __init__(self, parent=None):
super(QProgressBarPro, self).__init__(parent)
self.default_value = 50.0
self.lmb_pressed = False
self.setFormat('%p')
self.setRange(0.0, 100.0)
self.stepEnabled = True
self.step = 5
self.setToolTip('<strong>Press+Hold+Ctrl</strong> for percise values<br><strong>Right-Click</strong> to reset default value')
def step_round(self, x, base=5):
return int(base * round(float(x)/base))
def set_value_from_cursor(self, xpos):
width = self.frameGeometry().width()
percent = float(xpos) / width
val = self.maximum() * percent
if self.stepEnabled:
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers != QtCore.Qt.ControlModifier:
val = self.step_round(val, self.step)
self.setValue(val)
def mousePressEvent(self, event):
self.progressClicked.emit()
mouse_button = event.button()
if mouse_button == QtCore.Qt.RightButton:
self.setValue(self.default_value)
else:
xpos = event.pos().x()
self.set_value_from_cursor(xpos)
self.lmb_pressed = True
self.progressChanging.emit()
def mouseReleaseEvent(self, event):
self.lmb_pressed = False
self.progressChanged.emit()
def mouseMoveEvent(self, event):
if self.lmb_pressed:
xpos = event.pos().x()
self.set_value_from_cursor(xpos)
self.progressChanging.emit()
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.drawLine(10, 0, 10, 10)
QtGui.QProgressBar.paintEvent(self, event)
# DEMO
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.ui_progress = QProgressBarPro()
self.ui_progress.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.ui_progress.setValue(10)
gdl = QtGui.QVBoxLayout()
gdl.addWidget(self.ui_progress)
self.setLayout(gdl)
self.resize(300, 300)
self.setWindowTitle('Tooltips')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You need to change your paintEvent function.
I wrote a first approach that provides same result as in your image:
def paintEvent(self, event):
QtGui.QProgressBar.paintEvent(self, event)
painter = QtGui.QPainter(self)
brush = QtGui.QBrush(QtCore.Qt.SolidPattern)
# Set gray color
brush.setColor(QtGui.QColor(204,204,204))
painter.setPen(QtGui.QPen(brush, 2, QtCore.Qt.SolidLine,QtCore.Qt.RoundCap))
#print(str(self.width())+","+str(self.height()))
progressbarwidth = self.width()
progressbarheight = self.height()
## Drawing one vertical line each 1/5
painter.drawLine(progressbarwidth*1/5, 0, progressbarwidth*1/5, progressbarheight)
painter.drawLine(progressbarwidth*2/5, 0, progressbarwidth*2/5, progressbarheight)
painter.drawLine(progressbarwidth*3/5, 0, progressbarwidth*3/5, progressbarheight)
painter.drawLine(progressbarwidth*4/5, 0, progressbarwidth*4/5, progressbarheight)
The achieved outcome is shown here.

Why is my QGraphicsItem not selectable?

I copied some code snippets and made my own version of it. The initial snippet (which I don't have anymore) allowed to move and also select a QgraphicsItem. My modified version allows movement, but not selecting. What am I doing wrong?
#!d:/python27/python -u
import sys
from PyQt4 import QtGui, QtCore
class GraphicsItem(QtGui.QGraphicsItem):
#
# QtGui.QGraphicsItem always needs to override its two public abstract methods
# paint, boundingRect
#
def __init__(self, rect=None, parent=None):
super(GraphicsItem, self).__init__(parent)
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.pen = QtGui.QPen(QtCore.Qt.SolidLine)
self.pen.setColor(QtCore.Qt.blue)
self.pen.setWidth(8)
self.brush = QtGui.QBrush(QtCore.Qt.red)
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
def mouseMoveEvent(self, event):
# move object
QtGui.QGraphicsItem.mouseMoveEvent(self, event)
def boundingRect(self):
return self.rect
def paint(self, painter, option, widget):
painter.setBrush(self.brush)
painter.setPen(self.pen)
painter.drawEllipse(self.rect)
class MyMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
width = 1000
height = 800
scene = QtGui.QGraphicsScene(-width/2, -height/2, width, height)
graphicsItem = GraphicsItem((-100, -100, 200, 200))
scene.addItem(graphicsItem)
view = QtGui.QGraphicsView()
# set QGraphicsView attributes
view.setRenderHints(QtGui.QPainter.Antialiasing |
QtGui.QPainter.HighQualityAntialiasing)
view.setViewportUpdateMode(QtGui.QGraphicsView.FullViewportUpdate)
view.setScene(scene)
self.setCentralWidget(view)
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_Escape:
sys.exit(QtGui.qApp.quit())
else:
super(GraphicsView, self).keyPressEvent(event)
def main():
app = QtGui.QApplication(sys.argv)
form = MyMainWindow()
form.setGeometry(700, 100, 1050, 850)
form.show()
app.exec_()
if __name__ == '__main__':
main()
You miss this method in class GraphicsItem:
def mousePressEvent(self, event):
# select object
QtGui.QGraphicsItem.mousePressEvent(self, event)
print (self) # show the selected item

Categories