Doug
Doug

Reputation: 805

Qt: QWidget with a child on QGraphicsView/QGraphicsScene not working

I'm looking to create a view with a base image in the background and draggable widgets over the top.

The setup I have is like so:

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    ui->graphicsView->scene()->addWidget(new BackgroundWidget(nullptr));
}

This works fine. So does:

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    BackgroundWidget * bgWidget = new BackgroundWidget(nullptr);
    new ForegroundWidget(bgWidget);
    ui->graphicsView->scene()->addWidget(bgWidget);
}

However, I want to add foreground widgets dynamically, and it doesn't work. What I've noticed is that the following doesn't add the foreground widget at all:

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    BackgroundWidget * bgWidget = new BackgroundWidget(nullptr);
    ui->graphicsView->scene()->addWidget(bgWidget);
    new ForegroundWidget(bgWidget);
}

And this adds the foreground widget, but doesn't allow for semi-transparency with the background (which is needed for the project):

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    BackgroundWidget * bgWidget = new BackgroundWidget(nullptr);
    ui->graphicsView->scene()->addWidget(bgWidget);
    ui->graphicsView->scene()->addWidget(new ForegroundWidget(nullptr));
}

Any ideas as to why adding a child widget after adding the background widget isn't working? If so, any ideas how to fix it?

Thanks.

EDIT: Corrected some silly typing errors in the code blocks.

Image of the problem

The image is a reduced version of the issue; the widgets are both set to be semi-transparency (alpha at 100 out of 255), yet one widget seems to be above the other. I get this if I add the 'foreground' widget in any way. Below is what I was expecting to get:

Ok version

As I say, if I add them before attaching to the scene, it works fine, but I need to be able to add to the scene at run time.

Upvotes: 1

Views: 2047

Answers (1)

svlasov
svlasov

Reputation: 10455

You have several memory leak problems in your code.

Depending on BackgroundWidget and ForegroundWidget implementation, you either want

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    BackgroundWidget * bgWidget = new BackgroundWidget(nullptr);
    ForegroundWidget * fgWidget = new ForegroundWidget(bgWidget);
    ui->graphicsView->scene()->addWidget(fgWidget);
}

or

MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
    ui->graphicsView->setScene(new QGraphicsScene(nullptr));
    BackgroundWidget * bgWidget = new BackgroundWidget(nullptr);
    ForegroundWidget * fgWidget = new ForegroundWidget(nullptr);
    ui->graphicsView->scene()->addWidget(bgWidget);
    ui->graphicsView->scene()->addWidget(fgWidget);
}

Complete example:

#include <QtGui>

class MainWindow : public QMainWindow
{
public:
    MainWindow(QWidget *parent = 0) : QMainWindow(parent) {
        QGraphicsView *graphicsView = new QGraphicsView;
        setCentralWidget(graphicsView);

        QGraphicsScene *scene = new QGraphicsScene;
        graphicsView->setScene(scene);

        QWidget *fgWidget = new QWidget;
        fgWidget->setStyleSheet("background: rgba(255, 0, 0, 100)");
        fgWidget->setMinimumSize(100, 100);
        fgWidget->setMaximumSize(100, 100);

        QWidget *bgWidget = new QWidget;
        bgWidget->setStyleSheet("background: rgba(0, 0, 255, 100);");
        bgWidget->setMinimumSize(100, 100);
        bgWidget->setMaximumSize(100, 100);
        bgWidget->move(50, 50);

        scene->addWidget(fgWidget);
        scene->addWidget(bgWidget);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

enter image description here

If you want fgWidget to be parent of bgWidget:

    QWidget *bgWidget = new QWidget(fgWidget);
    ....
    scene->addWidget(fgWidget);
    //scene->addWidget(bgWidget); // don't add it to the scene

enter image description here

Upvotes: 2

Related Questions