QGraphicsObject in QThread

背景:
要至少能快速生成、顯示50W+的圖元。由于圖元數(shù)目過多,以及繪制圖形復(fù)雜還有很多文字因此生成顯示效率非常之低。因此就希望采用其他方法進(jìn)行效率提升。
在圖元生成階段一直想是否可以使用QThread多線程進(jìn)行一部分圖元的生成,但由于所有的圖形顯示操作都應(yīng)該只由GUI主線程負(fù)責(zé),其他線程無法直接控制GUI的繪制等操作。所以希望能通過子線程進(jìn)行圖元生成,最后通過GUI主線程來繪制。但這里又碰到一個(gè)問題,Qt里面每個(gè)QObject類對象都屬于創(chuàng)建它的線程,除非手動(dòng)對它進(jìn)行moveToThread(QApplication->thread()),在進(jìn)行編碼過程中卻發(fā)現(xiàn)這樣得到的效果并沒有比直接使用主線程好,甚至表現(xiàn)更差了。需要上論壇問問為什么~~

【20150708】問答發(fā)起了幾天沒有一個(gè)人回復(fù),可能是自己表述不佳或者他們認(rèn)為這個(gè)問題有點(diǎn)傻。不過在自己的實(shí)驗(yàn)中發(fā)現(xiàn):

  • 一次性把所有的items都直接add到Scene里面,其效率會(huì)遠(yuǎn)遠(yuǎn)低于分層思想來組織items的結(jié)構(gòu)。也就是說使用一個(gè)rootItem作為其他items的parentItem,然后把rootItem添加到scene里,其顯示交互效率好很多。
  • Qt的圖形體系與QObject是有區(qū)分的。QGraphicsItem并不繼承于QObject,因此他們也沒有signal/slot的成本。
  • Qt中QObject系列的類都是有線程歸屬的。而GUI操作都只能通過main thread來進(jìn)行。所以繪制圖形之類都只能是主線程。而如果是QGraphicsObject它繼承自QObject和QGraphicsItem,那么它在顯示時(shí)候就需要是屬于主線程。
  • 可以通過次線程來構(gòu)建圖元(QGraphicsItem或者QGraphicsObject)但如果是Object那么需要手動(dòng)將它們moveToThread()到主線程
  • 但經(jīng)過測試發(fā)現(xiàn),雖然可以通過次線程構(gòu)建,然后move到主線程,但在后續(xù)添加到scene的過程中卻花費(fèi)了更多時(shí)間,同時(shí)后續(xù)縮放等操作也有更明顯延遲。

問答鏈接

[SIZE=2]Hi, Everyone.
I am using QGraphicsView system to show a layout in chip design system.(EDA tools like Virtuso、Thunder、ICC)
And the max amount of QGraphicsObject/QGraphicsItem can be 500,000+, or even more.
Thus i have problem making items easy and quick to be drawn or view in the scene.
I followed the Chips demo, and query the solutions from Google, also read lots of topics in QtCentre.
But still i did not find a viable solution, Also Text item impact enormous.
Out group use the tree structure to organize the objects, which use a root item as the top level item, and then level 2, level 3...
But the users always need to flat all the items. And Then i use QTransform()::m11() to control the shape the item is paint.
But with so many items inside even this methods does not work.

There are two difficult parts on this case:[/SIZE]
[SIZE=3][SIZE=2]1)how to reduce the loading time for creating QGraphicsItem.
2)how to make it smoother while zoom in/zoom out, with so many items.[/SIZE][/SIZE]

[SIZE=2]Codes below are the sample i tried to use QThread to save loading time. But it does not work, or the program works
bad than no sub thread is used to load the items. I am very curious why the program has no response when i used sub thread,
and the program runs smoother with no sub thread.

Thanks all.
[/SIZE]
[CODE]

// Used to as Root item
class CRoot: public QGraphicsObject
{
public:
CRoot(QGraphicsObject *opParent = NULL) : QGraphicsObject(opParent)
{}

QRectF boundingRect() { return QRectF(); } 
...

};

// Leaf Item
class Chip : public QGraphicsObject
{
...
void paint(QPainter *opPainter, const QStyleOptionGraphicsItem *opOPtion, QWidget *opWidget)
{
Q_UNUSED(opOPtion);
Q_UNUSED(opWidget);
opPainter->save();
double d_value = mdWidth * transform().m11();
if (d_value >= 7)
{
opPainter->drawShape(moShape);
}
else
{
opPainter->drawPoint(0, 0);
}

    opPainter->restore();
}

private:
QPainterPath moShape; // used to store the path of Chip
QGraphicsTextItem *mopLabel; // Label item of this cell.
};

class CLayout : public QGraphicsObject
{
Q_OBJECT
public:
CLayout(QGraphicsObject *opParent = NULL) : QGraphicsObject(opParent)
{

}

CRoot *mopGetRoot() 
{
    QReadLocker o_locker(&moLock); 
    return mopRoot;
}

signals:
void msigLoadDone();

public slots:
void mslotLoadItems()
{
QWriteLocker o_locker(&moLock);
mopRoot = new CRoot;

    const int I_COUNT = 500000;
    for (int i_cnt = 0; i_cnt < I_COUNT; ++i_cnt)
    {
        Chip *op_chip = new chip(CRoot);
        op_chip->setPos(i_cnt / 10000, i_cnt / 10000);
        mlstopItems.push_back(op_chip);
    }
    
    // move items from curThread to GUI thread.
    moveToThread(QApplication::instance()->thread());
    mopRoot->moveToThread(QApplication::instance()->thread());
    foreach(Chip *op_item, mlstopItems)
    {
        op_item->moveToThread(QApplication::instance()->thread());
    }
    
    emit msigLoadDone();
}

private:
CRoot *mopRoot;
QList<Chip *> mlstopItems;
QReadWriteLock moLock;
};

class CMainWindow: public QMainWindow
{
Q_OBJECT
public:
...
void mvInitScene()
{
mopScene = new QGraphicsScene();
}

signals:
void msigGoToLoad();

public slots:
void mslotSetRootItem()
{
std::call_once(meFlag, &CMainWindow::mvInitScene, this);
mopScene()->addItem(mopLayout->mopGetRoot());
}

void mslotBtnClicked()
{
    mopThread = new QThread();
    mopLayout = new Layout();
    
#ifdef USED_THREAD
    connect(this, SIGNAL(msigGoToLoad()), mopLayout, SLOT(mslotLoadItems()));
    connect(mopLayout, SIGNAL(msigLoadDone()), this, SLOT(mslotSetRootItem()));
    connect(mopThread, SIGNAL(finished()), mopThread, SLOT(deleteLater()));
    mopLayout->moveToThread(mopThread);
    mopThread->start();
#else
    mopLayout->mslotLOadItems();
    mslotSetRootItem();
#endif
    emit msigGoToLoad();
}

private:
QThread *mopThread;
CLayout *mopLayout;
QGraphicsScene *mopScene;
std::once_flag meFlag;
};

[/CODE]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容