在 Qt 窗口树上寻找某个窗口

Node Editor中有许多窗口,它们都是 主窗口 QMainWindow的子窗口。

  • Parameter Widget: 当点击某个节点时,会显示这个节点的信息,以及可以调整的参数。 当前选中了 Comment 节点,在 Parameter Widget上可以显示、修改它的标题。同时 Comment节点也会联动。

  • ListWidget: 节点列表。拖到 GraphicsView 时,可以动态创建一个节点。

  • Graphics View: Graphics Scene 的视口。

image.png

这些窗口的父子关系如下,每一个方块代表一个类。


窗口关系1.png

现在,需要判断 Comment 节点是否被选中。 如果选中,就根据 Comment里的属性字段,动态创建一个 QWidget ,并添加到 Parameter Widget中。

Comment节点,其实是一个 QGraphicsItem对象。判断QGraphicsItem是否被选中,非常简单,只要重写一个虚函数即可:

QVariant DmGraphicsComment::itemChange(GraphicsItemChange change, const QVariant& value)
{
    /* 如果 GraphicsItem “被选中”这个状态发生了改变... */
    if (change == QGraphicsItem::ItemSelectedChange)
    {
        if (!m_isSelected)
        {   
            m_isSelected = true;

            /* 做出相应的举动 */
            Self::OnSelected();
        }
        else
        {
            m_isSelected = false;

            Self::OnUnselected();
        }
    }

    return Super::itemChange(change, value);
}

如何根据属性动态生成不同的QWidget对象,需要反射的支持,这个我们后来再说。我们假定下面代码的dynamicUi变量是已经生成好的,那么,现在的重点变为,怎么在当前的窗口树下,找到parameterWidget,然后把dynamicUi挂在它的上面,作为一个子窗口。

void DmGraphicsComment::OnSelected()
{
    /* 要如何实现这个函数? */
    QWidget* parameterWidget = FindWindowByObjectName("ParameterWidget");
    assert(parameterWidget && "Parameter widget is nullptr");

    /* 假定这个函数已经实现 */
    QWidget* dynamicUi = GenerateDynamicUi();

    QLayout* layout = parameterWidget->layout();
    layout->addWidget(dynamicUi );
}

方法非常简单,只有三步:

  • 给各窗口设置object name,比如MainWindowobject nameMainWindowParameterWidgetobject nameParameterWidget
  • 找到名叫MainWindow的顶层窗口
  • MainWindow的子窗口里寻找名叫ParameterWidget的子窗口
QWidget* DmGraphicsComment::FindWindowByObjectName(const QString& name)
{
    /* 拿到 Graphics View 窗口 */
    QGraphicsView* graphicsView = Super::scene()->views()[0];
    assert(graphicsView && "Graphics view of the item is null");

    /* 遍历所有父窗口,直到找到名叫 MainWindow 的父窗口。 线性查找。 */
    QWidget* parentWidget = graphicsView->parentWidget();
    assert(parentWidget && "Parent widget of the graphics view is null");

    while (parentWidget && parentWidget->objectName() != "MainWindow")
    {
        parentWidget = parentWidget->parentWidget();
    }

    /* 调用 Qt Api,查找子窗口 */
    QWidget* parameterWidget = parentWidget->findChild<QWidget*>(name);

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

推荐阅读更多精彩内容