get the size of QGraphicsScene - qt

I want to do the following:
create a QGraphicsView
connect it to QGraphicsScene
Get the size of the QGraphicsScene
create a QGraphicsRectItem with this size
My problem is how to get the size of the scene
In all the examples I saw that they put constants in setSceneRect()
The following is my code
class CharIdentifierInput(QDialog, Ui_CharIdentifierInput):
"""description of class"""
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setupUi(self)
self.setFixedSize(self.width(), self.height())
self.leftMouseButtonPressed = False
self.createGui()
def createGui(self):
self.graphicsScene = QGraphicsScene()
self.graphicsView.setScene(self.graphicsScene)
# I want to replace this line with a line that sets to the actual scene size
self.graphicsScene.setSceneRect(0,0,368,235)
mainItem = MyQtCharIdentifierMain(self.graphicsScene.sceneRect())
self.graphicsScene.addItem(mainItem)
mainItem.setPos(0,0)

Getters of the dimensions of the sceneRect are
QGraphicsScene.sceneRect(), QGraphicsScene.width() and QGraphicsScene.height()
if the sceneRect changes, QGraphicsScene.sceneRectChanged -signal is emitted, sendig the new sceneRect as parameter.
If QGraphicsView.setSceneRect() is not set, QGraphicsView.sceneRect() will
return the same value as QGraphicsScene.sceneRect() and it changes with QGraphicsScene.sceneRect(), see documentation QGraphicsView and documentation QGraphicsScene

Related

How to print current pixel of an QImage?

I have an RGB888 format qImage defined as follows:
int sizeX = 300; int sizeY = 300;
QImage img = QImage(sizeX, sizeY, QImage::Format_RGB888);
I wish to print current pixel of img one by one. So, I followed the example here:`
for(int i=0; i<sizeX; i++){
for(int j=0; j<sizeY; j++){
img.setPixel(i, j, qRgb(rand()%256, rand()%256, rand()%256));
}
}
QGraphicsScene *graphic = new QGraphicsScene(this);
graphic->addPixmap(QPixmap::fromImage(img));
ui->graphicsView->setScene(graphic);
But it prints the whole QImage. I want to print one by one.
Thanks. Best regards.
As JarMan commented, you are looking for "animation".
Drawing pixel by pixel, and updating the UI for every pixel, may use animation solution as described in the following post.
In Qt5 we have to execute QtWidgets.QApplication.processEvents() for forcing Qt to redraw.
Note:
I implemented the code in Python (with PyQt5), the syntax is different from C++, but the concept is the same.
Initialization stage:
The main class is inherited from QGraphicsView class.
Create QGraphicsScene object:
graphic = QGraphicsScene(0, 0, sizeX, sizeY)
Create QPixmap object from image:
pixmap = QPixmap.fromImage(img)
add addPixmap to the graphic object, and keep the returned reference:
pixmap_item = graphic.addPixmap(pixmap)
Execute setScene(graphic)
Animation:
In the animation loop, we have to execute setPixmap on every iteration for updating the entire image.
(The is a way for drawing pixel by pixel, but it's a deviation from your question).
Simplified code for updating the image (executed each iteration):
img.setPixel(i, j, qRgb(randrange(256), randrange(256), randrange(256)));
pixmap = QPixmap.fromImage(img)
pixmap_item.setPixmap(pixmap)
QtWidgets.QApplication.processEvents()
Complete Python code sample:
import sys
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QApplication
from PyQt5 import QtWidgets
from PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, qRgb
from random import randrange
import time
class Example(QGraphicsView):
def __init__(self):
super().__init__()
self.mPixmap = QPixmap()
self.sizeX = 300
self.sizeY = 300
self.img = QImage(self.sizeX, self.sizeY, QImage.Format_RGB888)
self.img.fill(QColor(60, 60, 60)) # Fill image with gray color
self.initUI()
def initUI(self):
self.graphic = QGraphicsScene(0, 0, self.sizeX, self.sizeY)
self.pixmap = QPixmap.fromImage(self.img)
self.pixmap_item = self.graphic.addPixmap(self.pixmap)
self.setScene(self.graphic)
self.show()
def doAnimation(self):
for i in range(self.sizeX):
for j in range(self.sizeY):
self.img.setPixel(i, j, qRgb(randrange(256), randrange(256), randrange(256)));
pixmap = QPixmap.fromImage(self.img)
self.pixmap_item.setPixmap(pixmap)
QtWidgets.QApplication.processEvents()
time.sleep(0.001) # Sleep 1msec (In Python it's slow enough without the sleep...)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = Example()
example.doAnimation()
app.exec_()
I hope it's not too much Python for you...
Sample output:

QGraphicsScene set item scene position

I have a QGraphicsScene that contains a hierarchy of QGraphicsItems.
Method item.scenePos() returns the scene coordinates of the item.
I'm looking for something like setScenePos() in order to change positions of the items by giving them scene coordinates.
How can I achieve this ?
As the docs says:
QPointF QGraphicsItem::scenePos() const
Returns the item's position in scene coordinates. This is equivalent to calling mapToScene(0, 0).
to get what you want you can do the inverse
# setScenePos(QPointF point)
point = QPointF(xx, yy)
point_item = item.mapFromScene(point)
item.setPos(point_item)

QGraphicsRectItem.boundingRect() not updated during move

I'm trying to get the boundingRect() of a subclass of a QGraphicsRectItem while it is being moved by the user. However, as the rectangle is moved in the scene, the rect returned by boundingRect() always returns the original value for the bounding rectangle. The example below demonstrates the issue. The value of boundinRect() is printed for every mouse move while the RectItem is moved around the scene. Why isn't boundingRect() returning the new bounding rectangle? What am I doing wrong?
from sys import argv
from PyQt4.Qt import QApplication
from PyQt4.QtCore import QPointF, QRectF, Qt
from PyQt4.QtGui import (
QGraphicsItem,
QGraphicsRectItem,
QGraphicsScene,
QGraphicsView,
)
class RectItem(QGraphicsRectItem):
def __init__(self, parent):
super(RectItem, self).__init__(parent)
self.setFlag(QGraphicsItem.ItemIsMovable, enabled=True)
self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=True)
def mouseMoveEvent(self, event):
super(RectItem, self).mouseMoveEvent(event)
print self.boundingRect()
class ViewItem(QGraphicsRectItem):
def __init__(self, x, y, width, height, parent=None, scene=None):
super(ViewItem, self).__init__(parent, scene)
self.setRect(QRectF(x, y, width, height))
self.create_child_item(100, 100)
def create_child_item(self, x, y):
self.child_item = RectItem(self)
self.child_item.setRect(x, y, 200, 100)
self.child_item.setSelected(True)
class View(QGraphicsView):
def __init__(self, parent=None):
super(View, self).__init__(parent)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setInteractive(True)
self.graphics_scene = QGraphicsScene(self)
self.setScene(self.graphics_scene)
self.setAlignment(Qt.AlignTop)
self.add_view_item()
def add_view_item(self):
self.view_item = ViewItem(0.0, 0.0, 1024.0, 768.0)
self.graphics_scene.addItem(self.view_item)
if __name__ == '__main__':
app = QApplication(argv)
view = View()
view.setGeometry(100, 100, 1024, 768)
view.setWindowTitle('View Test')
view.show()
app.exec_()
QGraphicsItem's boundingRect() is always in its own coordinate. Moving a item doesn't change its bounding rect relative to itself.
If you need the bounding box of the item relative to the scene, use sceneBoundingRect()

Qt/PyQt: How do I manually draw a caret?

I know a position within a QWidget where I would like to draw a caret.
Calling paint redraws the entire widget, and I only want to redraw that one 'box' containing the caret/character. Is there a way to tell it not to erase the entire widget?
How do I create a timer that will cause it to blink (even when the program is doing something else)?
I am looking to do it manually, not through QTextLayout.
QWidget has a repaint() method to repaint only a certain portion of the widget
QWidget.repaint (self, int x, int y, int w, int h)
QWidget.repaint (self, QRect)
QWidget.repaint (self, QRegion)
You can create a QTimer that will fire at intervals:
timer = QtCore.QTimer()
timer.timeout.connect(doBlinkMethod)
timer.start(1000) # every second
def doBlinkMethod():
print "blah"
You could also implement your widgets own built in timer to just act on itself internally:
http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qobject.html#startTimer

Qt Qbrush issue

What is the difference in the following code,
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush((QColor(60,20,20)));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
gives black color background
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush();
brush->setColor(QColor(60,20,20));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
it gives nothing.
As the Qt doc says :
QBrush::QBrush ()
Constructs a default black brush with the style Qt::NoBrush (i.e. this brush will not fill shapes).
In your second example, you have to set the style of the QBrush object by setStyle(), for example with Qt::SolidPattern.
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush();
brush->setStyle(Qt::SolidPattern); // Fix your problem !
brush->setColor(QColor(60,20,20));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
Hope it helps !
An alternate approach that achieves the same result is to put the color in the brush constructor, and that applies a default style of solid:
QBrush *brush = new QBrush (QColor (60, 20, 20));
The constructors that take a color have an optional parameter for the style, which defaults to Qt::SolidPattern. Both approaches produce the same result, but this one uses two fewer lines of code.

Resources