簡體   English   中英

在QT4中使用自定義事件

[英]Using Custom Events in QT4

我有一個應用程序,它有一個進度條並產生一個工作線程來做一些工作並報告進度。 對話框類重寫了customEvent方法,以便我可以處理通過工作線程傳遞給gui線程的事件。 在我使用QThread派生類作為工作線程之前,我將其更改為使用帶有靜態函數的ACE_Thread_Manager-> spawn()。

當我運行應用程序並按下按鈕以便工作人員產生並開始工作時,問題就出現了。 當它發送信號以遞增進度條時,我將以下錯誤記錄到std out。

QPixmap:在GUI線程之外使用pixmaps是不安全的

這似乎發生在調用progressBar-> setValue()時。 所以似乎進度條的設置發生在與主gui線程不同的線程中。 我不清楚這是怎么可能的。 我的印象是我有一個主要的gui線程,它有我的gui和customEvent方法在同一個線程上,而worker正在它自己的線程上。 這個假設是錯的嗎? 使用QThread派生類與靜態run_svc方法有什么區別嗎?

任何幫助,將不勝感激。 下面是customEvent處理程序,run_svc和按鈕處理程序代碼的代碼片段,並附加了代碼。

void MyDlgEx::customEvent(QEvent * e)
{
    if (e->type() == IdNumOperations)
    {
        NumOperations* pEvt = static_cast<NumOperations*>(e); 
        _steps = 0; 
        cout << "Num Operations = " << pEvt->operations() << endl; 
    }
    else if (e->type() == IdStep)
    {
        if (_steps % 10 == 0)
        {
            cout << "Step++ = " << _steps << endl; 
        }

        _steps++;  
        _progressBar->setValue(_steps); 
    }
}

void* MyDlgEx::run_svc(void* args)
{
    auto_ptr<ThreadArgs> thread_args(static_cast<ThreadArgs*>(args)); 
    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new NumOperations(300)); 

    // does some work that takes time -- ommitted for clarity 
    // called in a loop
    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new Step());

    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new Completed()); 

    return 0; 
}

按鈕處理程序注釋掉我使用從QThread派生的QT類的行。 使用ACE必須產生線程已經發現了這個問題。

void MyDlgEx::btnShowProgress_clicked()
{
    //_pProc = new ProcessThread(this); 
    //_pProc->run();

    auto_ptr<ThreadArgs> thread_args(new ThreadArgs(this));
    if (ACE_Thread_Manager::instance()->spawn(
                MyDlgEx::run_svc,
                static_cast<void*>(thread_args.get()), 
                THR_DETACHED | THR_SCOPE_SYSTEM) == -1)
        cout << "Failed to spawn thread." << endl; 

    thread_args.release(); 
}

嘗試調用QApplication :: postEvent(...)而不是QApplication :: sendEvent()。 文檔說sendEvent直接發送事件,這意味着它直接從另一個線程調用customEvent()函數。 postEvent()將事件添加到事件隊列中,稍后可以通過主GUI事件循環將事件調度到customEvent()。

僅僅因為customEvent()函數是在主GUI線程中創建的對象的成員並不意味着另一個線程無法調用該函數。 我相信當你從另一個線程調用QApplication :: sendEvent()時會發生這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM