Как я могу закрыть диалог, из другого потока?Qt - PullRequest
0 голосов
/ 19 февраля 2019

Я хочу обработать свою кнопку следующим образом:

  1. Изменить текст на этикетке (что-то вроде «Пожалуйста, подождите ...»)
  2. Загрузить некоторые данные из базы данных
  3. Когда загрузка будет завершена, закройте диалоговое окно, где находится эта кнопка.

Когда я сделаю это:

void LoadingDialog::on_pushButton_clicked()
{
m_ui->labelStatus->setText("Pobieranie wysyłek...");

if(m_methodToDo == MethodToDo::LoadShipment)
{
    if(DataManager::getManager()->loadShipments())
    {
        this->close();
    }
}
}

метка не изменила текст, занимает несколько секундlag (загружает несколько k записей) и диалоговое окно закрывается.

Когда я пытаюсь это сделать:

void LoadingDialog::changeStatus(QString status)
{
m_ui->labelStatus->setText(status);
}

bool LoadingDialog::load()
{
if(m_methodToDo == MethodToDo::LoadShipment)
{
    if(DataManager::getManager()->loadShipments())
    {
        this->close();
    }
}
}

void LoadingDialog::on_pushButton_clicked()
{
QFuture<void> future3 = QtConcurrent::run([=]() {
    changeStatus("Pobieranie wysyłek..."); // "Downloading.."
});

QFuture<void> future = QtConcurrent::run([=]() {
    load();
});
}

метка имеет текст изменения - это нормально, несколько секунд лага - это нормальноно диалоговое окно не закрывается, и мое приложение выдает исключение:

Cannot send events to objects owned by a different thread. Current thread 229b1178. Receiver 'Dialog' (of type 'LoadingDialog') was created in thread 18b00590

Есть предложения?

1 Ответ

0 голосов
/ 19 февраля 2019

Во-первых, changeStatus не блокируется, поэтому не запускайте его в другом потоке.С другой стороны, если вы хотите вызвать слот из другого потока, вы можете использовать QMetaObject::invokeMethod():

bool LoadingDialog::load()
{
    if(m_methodToDo == MethodToDo::LoadShipment)
        if(DataManager::getManager()->loadShipments())
            QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
}

void LoadingDialog::on_pushButton_clicked()
{
    changeStatus("Pobieranie wysyłek..."); // "Downloading.."

    QFuture<void> future = QtConcurrent::run([=]() {
        load();
    });
}
...