Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QFileDialog won't show up when QGraphicsScene::update() is called
Forum Updated to NodeBB v4.3 + New Features

QFileDialog won't show up when QGraphicsScene::update() is called

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 4 Posters 596 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    tomas.soltys
    wrote on last edited by
    #1

    Hi,

    I have stumbled upon an unexpected behavior.
    I have QGraphicsScene and at some point I would like to save some data to a file. At that point QFileDialog::getSaveFileName(this) is called, but dialog itself won't show up. Parent window is grayed out, but no dialog is visible. By hitting Esc "invisible" dialog closes and parent window is available again. This behavior seems to be triggered by calling QGraphicsScene::update().

    Initial state
    1 - Initial state.png
    Button clicked
    2 - Button clicked.png

    MainWindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QGraphicsScene>
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    protected:
        QGraphicsScene *scene;
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow() {}
    
    private slots:
        void onSceneChanged(const QList<QRectF> &region);
        void onButtonClicked();
    };
    #endif // MAINWINDOW_H
    

    MainWindow.cpp

    #include "mainwindow.h"
    
    #include <QVBoxLayout>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    #include <QPushButton>
    #include <QFileDialog>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        QWidget *widget = new QWidget;
        this->setCentralWidget(widget);
    
        QVBoxLayout *layout = new QVBoxLayout;
        widget->setLayout(layout);
    
        QGraphicsView *view = new QGraphicsView(scene = new QGraphicsScene);
        layout->addWidget(view);
    
        scene->setSceneRect(0.0,0.0,100.0,100.0);
    
        QObject::connect(scene,&QGraphicsScene::changed,this,&MainWindow::onSceneChanged);
    
        QPushButton *button = new QPushButton("Open file dialog");
        layout->addWidget(button);
    
        QObject::connect(button,&QPushButton::clicked,this,&MainWindow::onButtonClicked);
    }
    
    void MainWindow::onSceneChanged(const QList<QRectF> &region)
    {
        foreach (const QRectF &oneRegion, region)
        {
            // Call to update will prevent QFileDialog to show up
            scene->update(oneRegion);
        }
    }
    
    void MainWindow::onButtonClicked()
    {
        QString fileName = QFileDialog::getSaveFileName(this);
        qDebug() << fileName;
    }
    

    When line containing scene->update(oneRegion); is commented out, dialog shows up as it suppose to.

    My configuration is Qt 6.8.2, Ubuntu 22.04, x86_64, x11

    Thanks for help in advance,
    Tomas

    Pl45m4P 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Why are you calling update on scene when said scene is emitting the changed signal ?

      That's the wrong thing to do.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • T tomas.soltys

        Hi,

        I have stumbled upon an unexpected behavior.
        I have QGraphicsScene and at some point I would like to save some data to a file. At that point QFileDialog::getSaveFileName(this) is called, but dialog itself won't show up. Parent window is grayed out, but no dialog is visible. By hitting Esc "invisible" dialog closes and parent window is available again. This behavior seems to be triggered by calling QGraphicsScene::update().

        Initial state
        1 - Initial state.png
        Button clicked
        2 - Button clicked.png

        MainWindow.h

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include <QGraphicsScene>
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        protected:
            QGraphicsScene *scene;
        
        public:
            MainWindow(QWidget *parent = nullptr);
            ~MainWindow() {}
        
        private slots:
            void onSceneChanged(const QList<QRectF> &region);
            void onButtonClicked();
        };
        #endif // MAINWINDOW_H
        

        MainWindow.cpp

        #include "mainwindow.h"
        
        #include <QVBoxLayout>
        #include <QGraphicsScene>
        #include <QGraphicsView>
        #include <QPushButton>
        #include <QFileDialog>
        
        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
        {
            QWidget *widget = new QWidget;
            this->setCentralWidget(widget);
        
            QVBoxLayout *layout = new QVBoxLayout;
            widget->setLayout(layout);
        
            QGraphicsView *view = new QGraphicsView(scene = new QGraphicsScene);
            layout->addWidget(view);
        
            scene->setSceneRect(0.0,0.0,100.0,100.0);
        
            QObject::connect(scene,&QGraphicsScene::changed,this,&MainWindow::onSceneChanged);
        
            QPushButton *button = new QPushButton("Open file dialog");
            layout->addWidget(button);
        
            QObject::connect(button,&QPushButton::clicked,this,&MainWindow::onButtonClicked);
        }
        
        void MainWindow::onSceneChanged(const QList<QRectF> &region)
        {
            foreach (const QRectF &oneRegion, region)
            {
                // Call to update will prevent QFileDialog to show up
                scene->update(oneRegion);
            }
        }
        
        void MainWindow::onButtonClicked()
        {
            QString fileName = QFileDialog::getSaveFileName(this);
            qDebug() << fileName;
        }
        

        When line containing scene->update(oneRegion); is commented out, dialog shows up as it suppose to.

        My configuration is Qt 6.8.2, Ubuntu 22.04, x86_64, x11

        Thanks for help in advance,
        Tomas

        Pl45m4P Offline
        Pl45m4P Offline
        Pl45m4
        wrote on last edited by Pl45m4
        #3

        @tomas-soltys

        As @SGaist said, connecting the QGraphicsScene::changed signal to a function which updates the scene again creates a dead lock / infinite loop because updating the region will also cause the scene to emit the signal again... and again... and again.
        So you dialog can't be rendered properly because the event loop is busy with updating the scene forever.
        It's the same thing why you should never call repaint() in some widget's paintEvent()... same result.
        repaint() schedules the repainting of the widget through its paintEvent()... which then would start everything over again, because the repaint() is there.


        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        1 Reply Last reply
        0
        • T Offline
          T Offline
          tomas.soltys
          wrote on last edited by
          #4

          Thanks @SGaist and @Pl45m4 for the hint which eventually lead me to the solution.
          The example I provided was just a demonstration that there is an issue when scene update is called too many times and it happens only with QFileDialog and only on X11. In my real code I was not calling update directly but through QAbstractGraphicsShapeItem::prepareGeometryChange(). Once I reworked my code to call it less frequently dialog shows up.

          What is so special with QFileDialog that it couldn't be rendered but other dialogs like QMessageBox could?

          JonBJ 1 Reply Last reply
          0
          • T tomas.soltys

            Thanks @SGaist and @Pl45m4 for the hint which eventually lead me to the solution.
            The example I provided was just a demonstration that there is an issue when scene update is called too many times and it happens only with QFileDialog and only on X11. In my real code I was not calling update directly but through QAbstractGraphicsShapeItem::prepareGeometryChange(). Once I reworked my code to call it less frequently dialog shows up.

            What is so special with QFileDialog that it couldn't be rendered but other dialogs like QMessageBox could?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @tomas-soltys
            I have tested your pasted code under Ubuntu 24.04, Qt 6.4.2, Xorg desktop. I agree with your findings: QFileDialog::getSaveFileName() (I also tried creating an instance and using exec()) cannot show the dialog, while a QMessageBox does show up. The sceneUpdate() in onSceneChanged() causes the issue.

            I don't know why. QFileDialog does quite a bit more than, say, QMessageBox. From attempting to put in suitable qDebug()s I believe onSceneChanged() is being called continuously in this situation, presumably as a result of the scene->update() class and some interaction with the QFileDialog being there or attempting to be there. That might be why you never get to see it.

            Updating the scene in a slot attached to QGraphicsScene::changed may be problematic. It seems to be in this circumstance at least. I think you are saying you have removed or reduced this and things are better. But why do you need to update the scene from its signal saying it has been updated, can't you avoid that?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              QFileDialog is a native dialog so it might react a bit differently with regard to other widgets.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved