如何更新 Pyside2 GUI 上的进度条? [英] How do I update the progress bar on my Pyside2 GUI?

查看:77
本文介绍了如何更新 Pyside2 GUI 上的进度条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试更新 GUI 上的进度条,但我不知道该怎么做...我提供的代码显示了进度更新 - 我只需要该值来更新进度条也在我的 GUI 上!这是来自 Qt Creator 的 QML 文件.

I've been trying to update my progress bar on my GUI but I can't figure out how to do it... The code I have provided shows the progress updating - I just need that value to update the progress bar on my GUI too! It's a QML file from Qt Creator.

main.py

import os
import sys
import time

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide2.QtCore import QObject, Slot, Signal, QTimer, QUrl, QThread
from pathlib import Path

from multiprocessing.pool import ThreadPool

class MainWindow(QObject):
    def __init__(self):
        QObject.__init__(self)

    @Slot()
    def thread_progress(self):
        print("Worker")
        self.worker = Worker()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)
        self.thread.start()
        self.worker.run()
        

class Worker(QObject):
    progress_value = Signal(float)

    @Slot()
    def run(self):
        self.progress = 0
        self.total = 100
        for i in range(0, self.total):
            self.update_progress()

    def update_progress(self):
        print(f"{self.progress} / {self.total}")
        self.progress += 1
        self.progress_value.emit(self.progress)
        time.sleep(1)

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    # Get Context
    main = MainWindow()
    engine.rootContext().setContextProperty("backend", main)
    # Set App Extra Info
    app.setOrganizationName("zardoss")
    app.setOrganizationDomain("N/A")

    engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

main.py 文件与 main.qml 文件连接.GUI 有一个按钮、进度条和一个文本输入元素.我只关心按下生成按钮后进度条是否填满.按下生成按钮后,您可以从控制台看到 1-100 的值正在填充,但它没有填充进度条,因为我不确定如何.

The main.py file connects with the main.qml file. The GUI has a button, progress bar and a text input element. I am only concerned with the progress bar filling up after the generate button has been pressed. You can see from the console after pressing the generate button that the values from 1-100 are being filled up but it doesn't fill the progress bar as I am unsure how.

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
import QtQuick.Shapes 1.15

Window {
    id: mainWindow
    width: 750
    height: 500
    visible: true
    color: "#00000000"

    // Remove title bar
    flags: Qt.Window | Qt.FramelessWindowHint

    // Properties
    property int windowStatus: 0
    property int windowMargin: 10

    title: qsTr("Progress Bar")
    Rectangle {
        id: bg
        color: "#2c313c"
        border.color: "#f12c313c"
        border.width: 1
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        anchors.rightMargin: windowMargin
        anchors.leftMargin: windowMargin
        anchors.bottomMargin: windowMargin
        anchors.topMargin: windowMargin
        z:1

        Rectangle {
            id: appContainer
            height: 480
            color: "#00000000"
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.top: parent.top
            anchors.bottom: parent.bottom
            anchors.rightMargin: 1
            anchors.leftMargin: 1
            anchors.bottomMargin: 1
            anchors.topMargin: 1

            Rectangle {
                id: content
                color: "#00000000"
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: topBar.bottom
                anchors.bottom: parent.bottom
                anchors.topMargin: 0

                Button {
                    id: btnGenerate
                    x: 265
                    y: 44
                    width: 200
                    height: 50
                    text: "Generate"
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.right: parent.right
                    anchors.horizontalCenterOffset: 0
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.verticalCenterOffset: 165
//                    colorPressed: "#1e5425"
//                    colorMouseOver: "#42b852"
                    font.pointSize: 14
                    display: AbstractButton.TextBesideIcon
                    font.bold: false
//                    colorDefault: "#328a3f"
                    anchors.rightMargin: 250
                    onPressed: {
                        // backend.generate()
                        backend.thread_progress()
                    }
                }

                ProgressBar{
                    id: progressBar
                    x: 239
                    y: 64
                    visible: true
                    width: 661
                    height: 250
//                    text: "%"
                    anchors.verticalCenter: parent.verticalCenter
                    value: 0
                    //bgColor: "#00000/*000"
                    //dropShadowColor: "#20000000"
                    //samples: 16
                    anchors.verticalCenterOffset: -15
                    anchors.horizontalCenter: parent.horizontalCenter
                    
                }
            }
        }
    }
    DropShadow{
        anchors.fill: bg
        horizontalOffset: 0
        verticalOffset: 0
        radius: 10
        samples: 16
        color: "#80000000"
        source:bg
        z: 0
    }

    Connections{
        target: backend

        function onLinkValid(valid)  {
            if(valid === true)    {
                textField.textColor = "#00FF00"
            } else {
                textField.textColor = "#FF00FF"
            }
        }
    }
}

推荐答案

您的情况的问题是具有进度值的信号未连接到 GUI 的任何元素.

The problem in your case is that the signal that has the progress value is not connected to any element of the GUI.

在这种情况下,必须在与 ProgressBar 连接的 QML 暴露的类中创建一个信号,并且该信号必须从 Worker 的信号中接收信息.另一方面,您不应该调用run()"方法直接,因为它将在调用它的线程中执行,在您的情况下是主线程,因此它将阻塞 GUI,而您必须使用信号或使用 QTimer 间接调用它.

In this case, a signal must be created in the class exposed to QML that connects with the ProgressBar, and this signal must receive information from the signal from the Worker. On the other hand, you should not invoke the "run()" method directly since it will be executed in the thread from which it was invoked, which in your case is the main thread so it will block the GUI, instead you must invoke it indirectly with a signal or using the QTimer.

import os
import sys
import time
from pathlib import Path

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal, QTimer, QUrl, QThread


class Backend(QObject):
    progress_changed = Signal(float, name="progressChanged")

    def __init__(self, parent=None):
        super().__init__(parent)

        self.worker = Worker()
        self.worker.progress_changed.connect(self.progress_changed)
        self.worker_thread = QThread()
        self.worker.moveToThread(self.worker_thread)
        self.worker_thread.start()

    @Slot()
    def start_worker(self):
        QTimer.singleShot(0, self.worker.run)


class Worker(QObject):
    progress_changed = Signal(float)

    @Slot()
    def run(self):
        self.progress = 0
        self.total = 100
        for i in range(0, self.total):
            self.update_progress()

    def update_progress(self):
        print(f"{self.progress} / {self.total}")
        self.progress += 1
        self.progress_changed.emit(self.progress)
        time.sleep(1)


if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    backend = Backend()
    engine.rootContext().setContextProperty("backend", backend)
 
    engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    ret = app.exec_()
    # backend.worker_thread.quit()
    # backend.worker_thread.wait()
    sys.exit(ret)

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15

Window {
    id: mainWindow

    width: 750
    height: 500
    visible: true
    color: "#00000000"
    title: qsTr("Progress Bar")

    Row {
        spacing: 10
        anchors.centerIn: parent

        Button {
            id: btnGenerate

            text: "start"
            onClicked: backend.start_worker()
        }

        ProgressBar {
            id: progressBar
            from: 0
            to: 100.0
        }

    }

    Connections {
        target: backend

        function onProgressChanged(progress) {
            progressBar.value = progress;
        }

    }

}

这篇关于如何更新 Pyside2 GUI 上的进度条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆