QGraphicsObject in QThread

背景:
要至少能快速生成、显示50W+的图元。由于图元数目过多,以及绘制图形复杂还有很多文字因此生成显示效率非常之低。因此就希望采用其他方法进行效率提升。
在图元生成阶段一直想是否可以使用QThread多线程进行一部分图元的生成,但由于所有的图形显示操作都应该只由GUI主线程负责,其他线程无法直接控制GUI的绘制等操作。所以希望能通过子线程进行图元生成,最后通过GUI主线程来绘制。但这里又碰到一个问题,Qt里面每个QObject类对象都属于创建它的线程,除非手动对它进行moveToThread(QApplication->thread()),在进行编码过程中却发现这样得到的效果并没有比直接使用主线程好,甚至表现更差了。需要上论坛问问为什么~~

【20150708】问答发起了几天没有一个人回复,可能是自己表述不佳或者他们认为这个问题有点傻。不过在自己的实验中发现:

  • 一次性把所有的items都直接add到Scene里面,其效率会远远低于分层思想来组织items的结构。也就是说使用一个rootItem作为其他items的parentItem,然后把rootItem添加到scene里,其显示交互效率好很多。
  • Qt的图形体系与QObject是有区分的。QGraphicsItem并不继承于QObject,因此他们也没有signal/slot的成本。
  • Qt中QObject系列的类都是有线程归属的。而GUI操作都只能通过main thread来进行。所以绘制图形之类都只能是主线程。而如果是QGraphicsObject它继承自QObject和QGraphicsItem,那么它在显示时候就需要是属于主线程。
  • 可以通过次线程来构建图元(QGraphicsItem或者QGraphicsObject)但如果是Object那么需要手动将它们moveToThread()到主线程
  • 但经过测试发现,虽然可以通过次线程构建,然后move到主线程,但在后续添加到scene的过程中却花费了更多时间,同时后续缩放等操作也有更明显延迟。

问答链接

[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]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容