首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >QML如何强制更新/重绘

QML如何强制更新/重绘
EN

Stack Overflow用户
提问于 2019-11-26 12:22:48
回答 2查看 3.5K关注 0票数 2

在我的应用程序中,我有一个通过单击按钮启动的进程。按钮已经有了一个属性来指示它什么时候忙,这会改变颜色以反映忙碌状态。当进程完成后,忙碌属性将被设置为false。

问题是,尽管这些步骤是:

代码语言:javascript
运行
复制
    button.busy = true
    ... Do something ...
    button.busy = false

实际上,直到进程几乎完成后,按钮才会改变以反映繁忙状态,然后又会更改为非繁忙状态。

无论如何,我是否可以在将繁忙状态设置为true之后,以及在做一些使GUI更新和反映状态的操作之前,插入一些内容?

我的按钮QML:

代码语言:javascript
运行
复制
Button {
    id: root
    property bool busy: false
    property bool showDropShadow: true
    property color bottomColour: MerlinStyle.greenButtonBottom
    property color iconColour: "white"
    property color topColour: MerlinStyle.greenButtonTop
    property string icon: ""
    opacity: (pressed || !enabled) ? 0.5 : 1.0

    onBusyChanged: {
    //Set the colours according to busy state
        if ( root.busy == true ) {
            root.bottomColour = MerlinStyle.indicatorOrange;
            root.topColour = MerlinStyle.indicatorOrange;
        } else {
            root.bottomColour = MerlinStyle.greenButtonBottom;
            root.topColour = MerlinStyle.greenButtonTop;
        }
    }
    background: Item {
        RadiusRectangle {
            id: rect
            anchors.fill: parent
            radius: MerlinStyle.rectRadius
            topLeftPointed: true

            gradient: Gradient {
                GradientStop { position: 0.0; color: root.topColour }
                GradientStop { position: 1.0; color: root.bottomColour }
            }
        }
        DropShadow {
            visible: showDropShadow && !pressed && enabled
            anchors.fill: rect
            horizontalOffset: 1
            verticalOffset: 2
            color: "#80000000"
            source: rect
        }
    }
    contentItem: Item {
        ColoredImage {
            anchors.centerIn: parent
            height: parent.height * 0.85
            width: parent.width * 0.85
            source: icon
            color: root.iconColour
        }
    }
}

我尝试使用以下方法触发更新:

代码语言:javascript
运行
复制
idOfButton.update

这总是导致:

代码语言:javascript
运行
复制
Button_QMLTYPE_28 : Update called for a item without content

update函数不接受参数。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-26 13:48:47

当您调用该函数时,它只会阻塞GUI线程,而那些已经放到事件队列中的事件将等待直到程序再次返回到事件循环。这就是为什么您看不到根据属性更改更新按钮的原因。这是因为糟糕的设计。根据Qt文档:

在可能的情况下,processing

  • never

  • 使用异步事件驱动编程,

  • 使用辅助线程执行重要的

,手动旋转事件循环

  • ,在阻塞函数

中,每帧不超过几毫秒。

您不应该从GUI线程中调用阻塞函数。您需要从另一个线程运行该函数,或者如果您有此目的,您可以使用计时器调用您的函数,这是一个肮脏的黑客。

代码语言:javascript
运行
复制
Timer{
 id: dummyTimer
 interval:1
 repeat: false
 running: false
 onTriggered: {
   control.someLazyBlockingFunction();
   idOfButton.busy = false;
 }
}
Button{
 id: anotherButton
 ...
 onClicked:{
    idOfButton.busy = true;
    dummyTimer.running= true;
 }
}
票数 1
EN

Stack Overflow用户

发布于 2021-11-26 13:30:19

迟答,但可能会帮上忙。

在我的例子中,我的应用程序运行在python (PyQt5 + QML)上,事件来自QML代码,并且是在一个槽中处理的(这里没有什么新的)。问题是,正如qt文档中所述,您不能阻止主线程,因此,我找到的处理它的最佳方法是旋转一个新的守护进程线程,以运行事件代码而不挂起前端。

代码语言:javascript
运行
复制
@pyqtslot(name="doMyButtonCallback")
def do_mybuttoncallback():
  def mybuttonwork():
    time.sleep(3)
    print("i did not hang your code!"
  t=threading.Thread(target=mybuttonwork)
  t.daemon=True
  t.start()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59050917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档