Why QGraphicsPixmapItem do not have setParent() - pointers

QGraphicsPixmapItem does not like other qt object which inherited from QObject. It can not be destroyed when its parent destroy. Is the only way to use it is delete the pointer by myself?
......
QGraphicsPixmapItem * backGround = new QGraphicsPixmapItem(QPixmap::fromImage(this->mat2QImage(img)), NULL);
this->scene->addItem(backGround);
ui.imgDisplay->setScene(scene);
ui.imgDisplay->show();
......
// delete by myself
delete backGround;
// why can not I set the parent of the QGraphicsPixmapItem to QGraphicsScene
// when QGraphicsScene destroy, QGraphicsPixmapItem under QGraphicsScene automatically destroy.

QGraphicsPixmapItem inherits from QGraphicsItem, not QObject.
A QgraphicsItem is deleted when the scene is deleted. It will also delete all its children. So, you don't have delete yourself the items.
If you want a graphics item based on QObject, you should take a look to QGraphicsObject.

Related

How to save the QPixmap of a label which consist of one more label above it which has a Qpixmap

I have inherited the QLabel to create my own class of QLabel, The code is below:
class myLabel : public QLabel
{
Q_OBJECT
public:
explicit myLabel(QWidget *parent=nullptr): QLabel(parent){ setFrameShape(QFrame::Box);}
QLabel insideLabel;
};
As you can see, My class has one QLabel member inside.
Now, What I have done is that I created the object of my class and assign a image to it using setPixmap() and also assign a image to my QLabel member inside my class. The code is below:
QFile file("file.png");
ui->setupUi(this);
//Creatig instance of my QLabel class and setting one image to it.
myLabel *label=new myLabel(this);
label->setPixmap(QPixmap("someImagePath"));
//Assining image to my class QLabel member.
label->insideLabel.setPixmap(QPixmap("someImagePath"));
//saving file.
label->pixmap()->save("imageName","png",-1);
So when I save the image it only save the image of my QLabel class object QPixmap instead of saving both of my label image as the insideLabel is present above the my label class object as it is it's member. How can i save both images of my labels as one image.
Your code is not trying to save a QLabel, you are trying to save the pixmap property of a QLabel, those are two very different things.
A QLabel is a widget that can be rendered on a paint device. You should read the documentation about the QWidget subsystem:
Qt Widgets module
I see some problems with your code, the inside widget has no parent, and in your case I think that is a problem, but explaining that is beyond your question.
If what you want is to render the widget into an image file, you could do something like this:
QPixmap pixmap(Widget->size());
Widget->render(&pixmap);
pixmap.save("widget_render_file.png");
If you want to compose an image you can directly draw on a painter attached to a pixmap like this:
QPixmap pixmap(100,100);
QPainter painter(pixmap);
painter.setPen (...);
painter.drawPixmap (...);
painter.end();
pixmap.save(...);
You should also check documentation on QPainter and QPixmap, there's a lot of useful drawing/painting functions.
I just saved the needed portion of my Widget window as image, below is my code
label=new myLabel(this);
label->setGeometry(50,50,300,300);
label->setPixmap(QPixmap("/home/vinay/Pictures/exp.png").scaled(label->width(),label->height()));
label->insideLabel=new QLabel(this);
label->insideLabel->setGeometry(50,50,50,50);
label->insideLabel->setPixmap(QPixmap("/home/vinay/Pictures/exp2.png"));
label->insideLabel->setFrameShape(QFrame::Box);
label->insideLabel->setLineWidth(3);
//Assining image to my class QLabel member.
//saving file.
label->pixmap()->save("imageName","png",-1);
//ui->myWidget->grab().save("image.png");
QRect r(50,50,300,300);
Widget::grab(r).save("image.png");

Adding a QWidget to a QGraphicsScene

I have a QGraphicsScene for drawing, where I now want to "add" a QWidget to a QGraphicsItem (display on top of the item, which can of course be moved).
How could this be accomplished? Is there any QGraphicsItem, which may function as a Widget container?
You can use QGraphicsScene::addWidget which creates a new QGraphicsProxyWidget for widget, adds it to the scene, and returns a pointer to the proxy :
QGraphicsProxyWidget * item = myScene->addWidget(myWidget);
item->setParentItem(anOtherItem);
item->setPos(100,100);
item->setZValue(1);

Redefine QPainter options when redrawing QGraphicsItem

I want to redefine the QPainter before drawing earch QGraphicsItem in a QGraphics scene.
void GraphicsScene::drawItems( QPainter * painter, int nbItem, QGraphicsItem *[] items, const QStyleOptionGraphicsItem[] options, QWidget * widget = NULL )
Is now obsolete, what's the "new" method ?
Thx
The QGraphicsScene isn't in charge of the painter... it is in charge of the storage and retrieval of the items. The QGraphicsView is in charge of the painter and transformation of the view.
If you want to set render hints to modify the QPainter behavior, you can do that from the view using QGraphicsView::setRenderHint.
If you just want to do a single render to another special QPainter engine, the documentation shows an example for it to a printer here.
Here is link to the docs on QGraphicsView.

How to Add QListView/QListWidget to QGraphicsScene in Qt?

How to Add QListView/QListWidget to QGraphicsScene and add Widgets to ListView
When i Try to add QLisView to QGraphicsScene mouse scroll affects goes from Scene.
I want to add QPushButtons as ListView Items in QgraphicsScene with mouse scroll affect.
Thanks.
What about QGraphicsProxyWidget?
QListView *listView = new QListView;
QGraphicsProxyWidget *proxy = scene.addWidget(listView);
Then (or before that) you can populate the list with anything you want. QPushButton can be added to the list using setIndexWidget(). Also you might rethink the whole idea of having a QListView, and give it a try with QScrollArea and a linear layout containing buttons. That would require a bit more logic to organize items within the scroll area, but it should be more lightweight that QListView with custom widgets.
I second the answer above: ProxyWidget is the answer.
Here is my working code,
Header:
class CenterScreen{
private:
QListWidget* nameListWidget;
QGraphicsProxyWidget* nameProxyWidget;
...
C++ source:
void CenterScreen::addListView()
{
QGraphicsScene* scene = ui.centerGraphicsView->scene();
nameListWidget = new QListWidget();
nameProxyWidget = scene->addWidget(nameListWidget);
...
nameProxyWidget->hide(); // you can control your widget as you like

Creating shader program for QGraphicsItem

I have a QGraphicsScene in which I add a QGraphicsItem. Inside the QGraphicsItem, I render the triangle used in the hello triangle example of OpenGL ES 2.0. The problem is that if I create and compile the shaders anyplace other than the QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) function, they do not get compiled. I know that you should have a GL rendering context active but doesn't that happen when I set my viewport to a GLWidget?? I tried various things like compiling them in the QGraphicsItem constructor or in the QGraphicsScene and setting the QGraphicsItem as a parent (which I learned they are very stupid things to do), but (obviously) nothing works. What seemed most logical to me was to create a initShaders() function inside the QGraphicsItem class and call it after the item is created in my scene, but that didn't work also.
Create a derived class of QGraphicsView. Override the setupViewport(QWidget *viewport) to initialize the shaders. This will allow you to ensure the context is current when compiling the shaders. However, it requires that the items be added to the scene before setViewport() is called on the graphics view.
void MyGraphicsView::setupViewport(QWidget *viewport)
{
QGLWidget *glWidget = qobject_cast<QGLWidget*>(viewport);
if (glWidget) {
glWidget->makeCurrent();
foreach (QGraphicsItem *item, scene()->items())
{
MyGraphicsShaderItem *glItem = qgraphicsitem_cast<MyGraphicsShaderItem*>(item);
if (glItem)
glItem->initShader();
}
glWidget->doneCurrent();
}
}

Resources