Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Unsolved 在关闭事件accept执行前一步发送信号,窗口无法正常关闭,出现无响应

    Chinese
    关闭窗口无响应 closeevent signals & slots qt5
    3
    7
    5588
    Loading More Posts
    • 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.
    • CN_Simo
      CN_Simo last edited by CN_Simo

      问题如标题所述,代码如下:

      /*
          重构关闭函数
      */
      void MainWindow::closeEvent(QCloseEvent *event)
      {
          if(!QMessageBox::information(this,tr("关闭窗口"),tr("确定要退出程序?"),tr("确定"),tr("取消")))
          {
              if(QSqlDatabase::database().isOpen())
              {
                  qDebug() << "Database is opening!" << endl;
                  emit ui->action_close->trigger();    // 发送一个关闭数据库信号
                 // QSqlDatabase::removeDatabase(QSqlDatabase::database().connectionName());
              }
              event->accept();
          }
          else
          {
              event->ignore();
          }
      }
      
      

      可能不是信号和槽的事情,当我直接执行槽函数的时候,依旧会无响应,槽函数如下:

      /*
          @SLOT
          在菜单栏上点击触发的信号槽-----断开
      */
      void MainWindow::on_action_close_triggered()
      {
          /*
              关闭数据库
          */
          QStringList dbList = QSqlDatabase::connectionNames();
          for(int i = 0; i < dbList.count(); ++i) {
          QSqlDatabase::removeDatabase(dbList[i]);
          }
      
          ui->statusBar->showMessage(tr("已关闭数据库连接!"));
      
      //    QString name;
      //    {
      //        name = QSqlDatabase::database().connectionName();
      //        QSqlDatabase::database().close();
      //    }//超出作用域,隐含对象QSqlDatabase::database()被删除。
      //    QSqlDatabase::removeDatabase(name);
      
          updateInterface(CloseMode);
      }
      

      只有直接执行关闭数据库的代码:

      QSqlDatabase::removeDatabase(QSqlDatabase::database().connectionName());
      

      才能正常关闭!

      错误演示:
      0_1505140545757_emit signal before execute the accept.gif

      joeQ 1 Reply Last reply Reply Quote 0
      • CN_Simo
        CN_Simo last edited by

        This post is deleted!
        1 Reply Last reply Reply Quote 0
        • SGaist
          SGaist Lifetime Qt Champion last edited by

          Hi and welcome to devnet,

          I've moved your post to the Chinese sub-forum so you will more likely get an answer in your native language.

          The forum official language is English.

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

          CN_Simo 1 Reply Last reply Reply Quote 1
          • CN_Simo
            CN_Simo @SGaist last edited by

            @SGaist ok,thank you very much!

            1 Reply Last reply Reply Quote 0
            • joeQ
              joeQ @CN_Simo last edited by joeQ

              @CN_Simo 您好,欢迎来到Qt社区。

              根据您的问题描述,进行以下思考:

              1. signal and slot 是否链接成功。 信号是否成功被slots接受,可以在slot中qDebug信息,您也可以设置断点进行调试;
              2. 注意 在slot函数中, 确保发射的object没有提前销毁。 有的情况下, 信号发射完后,该对象立刻销毁,导致槽函数中的对象失效。
              3. 如果signal object and slot object 在不同的线程, 可以尝试 在connect函数中,添加此变量。

              Qt::DirectConnection : The slot is invoked immediately when the signal is emitted. The slot is executed in the signalling thread.

              Just do it!

              CN_Simo 1 Reply Last reply Reply Quote 0
              • CN_Simo
                CN_Simo @joeQ last edited by

                @joeQ
                已经大概知道了由什么引起的无响应了!

                我的做法是: 我在槽函数中各处多放了几个qDebug,然后发现在下面这句代码前的qDebug都能输出,之后就出现了无响应

                ui->statusBar->showMessage(tr("已关闭数据库连接!"));
                

                就这么看的话,在关闭事件accept之后,这个ui可能被销毁了,所以再使用ui里的东西会造成无响应。

                但是还是有一点疑问,就是关闭事件accept明显是发生再触发槽之后的,ui怎么就被销毁了?是不同线程的操作吗?

                // 摘自在closeEvent()函数中
                if(QSqlDatabase::database().isOpen())
                {
                    qDebug() << "Database is opening!" << endl;
                    emit ui->action_close->trigger();    // 发送一个关闭数据库信号
                }
                
                event->accept();
                
                joeQ 1 Reply Last reply Reply Quote 0
                • joeQ
                  joeQ @CN_Simo last edited by

                  @CN_Simo

                  您是在MainWindow的close事件中,发射信号进行清理关闭工作的。

                  Qt signal and slot确实很方便。 可是有时候也会造成一些不必要的麻烦。很多时候,也可以传递对象的指针,直接在对应的地方调用对象的函数即可。

                  Just do it!

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post