2013-08-03 2 views
0

У меня есть QDialog в моем основном потоке, и у меня есть логика, которая происходит в отдельном потоке. Когда начинается логика, в диалоговом окне вызывается сигнал show(). Когда логика заканчивается, выдается сигнал, который подключен к hide() в диалоговом окне. Когда логика действительно работает, диалог отображается/скрывается должным образом. Если логика «ничего» и сигналы просто испускаются последовательно, диалог не всегда отображается/скрываться должным образом.QT QDialog не скрывается должным образом при быстром вызове/скрытии

Мои соединения выполнены подобным образом:

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 
public: 
    MainWindow(QWidget* parent = 0) : 
     Ui(new Ui::MainWindowUi), 
     Transferer(new DataTransferer()), 
     TransferProgress(this), 
     TransferThread() 
    { 
     Ui->setupUi(); 
     connect(&Transferer, SIGNAL(Begin()), &TransferProgress, SLOT(show())); 
     connect(&Transferer, SIGNAL(End()), &TransferProgress, SLOT(hide())); 

     Transferer.moveToThread(&TransferThread); 
     TransferThread.start(); 

     Transferer.DoStuff(true); 
    } 

    virtual ~MainWindow() 
    { 
     TransferThread.quit(); 
     TransferThread.wait(1000);    

     delete Ui; 
     Ui = NULL; 
    } 

private: 
    Ui::MainWindowUi* Ui; 
    DataTransferer Transferer; 
    TransferProgressDialog TransferProgress; 
    QThread TransferThread; 
} 

Логика выглядит примерно так:

class DataTransferer : public QObject 
{ 
    Q_OBJECT 
public: 
    DataTransferer(QObject *parent) : QObject(parent) {} 
    virtual ~DataTransferer() {} 

    void DoStuff(bool dontDoStuff) 
    { 
     emit Start(); 
     if (!dontDoStuff) 
     { 
      QThread::sleep(1); 
     } 
     emit End(); 
    } 
} 

Когда DataTransferer делает вещи, все работает отлично. Когда диалог отображается и скрывается в быстрой последовательности, я получаю диалог призрака примерно каждый раз, когда я вызываю DoStuff().

Я использовал QThread :: currentThreadId() и проверил, что диалог и логика работают на отдельных потоках.

Почему мой диалог не спрятался должным образом в этом случае? Должен ли я просто заставить мою логику всегда работать в течение по крайней мере нескольких сотен миллисекунд (это решение плохо)? Есть ли способ, которым мой диалог может быть полностью загружен, прежде чем пытаться скрыть себя? Должен ли я обрабатывать эти сигналы/слоты по-разному?

EDIT: Я в настоящее время смирился с тем, что просто вставил QThread :: sleep (1) после того, как я издал сигнал, чтобы показать() диалог. Мне не нравится это решение, но больше ничего не работает. Сон (1) позволяет диалогу пройти весь путь, прежде чем скрывать его. Я также смог заставить это работать с QThread :: msleep (10), но это все равно привело к диалогу призрака примерно 1 из 6 попыток.

Я попытался использовать член QMutex в логике диалога всякий раз, когда я вызывал либо show(), либо hide(), но это не сработало.

Я изменил все кросс-потоковые подключения, чтобы использовать Qt :: BlockingQueuedConnection и Qt :: QueuedConnection, и ни одна попытка не была успешной.

Я попытался переместить соединения слота из диалогового окна в объект, который устанавливает соединения, а затем вызывает слоты напрямую, но это тоже не оказалось успешным.

ответ

0

Я предполагаю, что проблема возникает из-за чередования «шоу» и «скрытия». Чтобы убедиться в этом, используйте семафор - заблокируйте объект до тех пор, пока не закончите показ, и дождитесь его в скрытии. Также посмотрите на верхний проголосовавший ответ здесь для другого возможного (возможно, лучшего) решения: connecting signal/slot across different threads between QObjects

+0

Используется QMutex для установки блокировки функций Show()/Hide() для блокировки/разблокировки до и после действий; нет успеха. Я также прочитал связанное решение и попытался использовать все типы логических подключений, и проблема все еще сохраняется. –

0

Используйте Qt::BlockingQueuedConnection для подключения сигналов к слотам. Убедитесь, что цикл событий основного потока не заблокирован. Кроме того, если ваш рабочий поток использует много времени процессора - вы можете позвонить по телефону QThread::yeldCurrentThread().

Смежные вопросы