Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

instantiating QMessageBox in a slot it doesn't respond



  • I have a QDialog managing connection and login to a server. When login response arrives on the socket I propagate the result calling a function of my custom dialog, here I send a signal which is connected to a slot of same dialog and here finally I handle the result and UI changes.
    Signal-slot are necessary because socket reading thread is not the same where UI is.
    It works correctly as far as I change dialog widgets, but if I create a message box in that slot it gets no focus nor it's possible to close it or even interact with it and the whole application UI.

    code for creating message box is simple:

    QMessageBox::warning(this , "Login Result", "Log In Attempt FAILED");

    "this " should be my custom dialog object.
    I've tested the same code in my dialog constructor and it works perfectly.
    So the problem is : how do I instantiate such a message box in a slot ?


  • Qt Champions 2019

    Please provide some code / an example. I would guess your threading is wrong and the QMessageBox is not called in the main thread.
    Why do you need to read data from a socket in a separate thread at all?



  • @Christian-Ehrlicher
    I was just supposing it does. It's not my thread...

    in the class holding socket I have a slot for reading from socket. I hold a listeners list , classes instances that registered themself to ClassWithSocket. Those classes must implement

    class ConnectionListener
    {
    public:
    virtual void onConnectionStatusChanged(ConnectionStatus status) = 0;
    virtual void onLogStatusChanged(LogStatus satus) = 0;
    virtual void onMessageSent(bool ok) = 0;
    };

    My conncetion dialog inherits from this.

    Class containing socket :

    ClassWithSocket::ClassWithSocket()
    {
    ...
    connect(mSocket, SIGNAL(readyRead()), this, SLOT(onDataReadyFromSocket()));
    ...
    }

    (this is a slot)
    ClassWithSocket::onDataReadyFromSocket()
    {
    readLoginResponse();
    }

    void ClassWithSocket::readLoginResponse()
    {
    ... listener->onLogStatusChanged(NotConnected);
    }

    my connection dialog is declared as follows:

    class ConnectionDialog : public QDialog, public ConnectionListener
    {
    Q_OBJECT
    public:
    ConnectionDialog();
    void onConnectionStatusChanged(ConnectionStatus status);
    void onLogStatusChanged(LogStatus status);
    void onMessageSent(bool ok) {}
    signals:
    void connectionStatusChanged(ConnectionStatus status);
    void logStatusChanged(LogStatus status);
    private slots:
    void connectionStatusChangedSlot(ConnectionStatus status);
    void logStatusChangedSlot(LogStatus status);
    ...
    }

    constructor:
    ConnectionDialog::ConnectionDialog()
    {

    connect(this, SIGNAL(connectionStatusChanged(ConnectionStatus)), this, SLOT(connectionStatusChangedSlot(ConnectionStatus)));
    connect(this, SIGNAL(logStatusChanged(LogStatus)), this, SLOT(logStatusChangedSlot(LogStatus)));
    }

    void ConnectionDialog::onConnectionStatusChanged(ConnectionStatus status)
    {
    emit connectionStatusChanged(status);
    }

    void ConnectionDialog::onLogStatusChanged(LogStatus status)
    {
    emit logStatusChanged(status);
    }

    void ConnectionDialog::logStatusChangedSlot(LogStatus status)
    {
    ...
    }

    so in a slot of ClassWithSocket i read response, i call a function of stored listener which is a QDialog, in this dialog i send a signal which is connected to a slot of the same class and here I try to instantiate the messagebox.



  • I 've just tried a bypass:
    in

    void ConnectionDialog::onLogStatusChanged(LogStatus status) which is the function called by socket reading slot I dont' emit any signal and I modify directly my UI and create message box.

    void ConnectionDialog::onLogStatusChanged(LogStatus status)
    {
    //emit logStatusChanged(status);
    logStatusChangedSlot(status);
    }
    void ConnectionDialog::logStatusChangedSlot(LogStatus status)
    {
    QMessageBox::warning(this , "Login Result", "Log In Attempt FAILED"); // I've tried passing 0 as well instead of this as parent
    logStatus->setText("Login FAILED!");
    }

    same result. I cant interact with message box and it's all frozen


  • Qt Champions 2019

    I would use a QueuedConnection for such things because the way you do it now is to create a new QEventLoop within a socket operation which is maybe not that good.



  • My bad. I thought qt would recognize automatically this kind of situation.

    NOW it works. THANK YOU!

    for those who may be interested:

    I had to add

    qRegisterMetaType<LogStatus>();

    to main.cpp function and modify signal slot connection like this:

    connect(this, SIGNAL(logStatusChanged(LogStatus)), this, SLOT(logStatusChangedSlot(LogStatus)), Qt::QueuedConnection);


Log in to reply