从QML文件到.py文件获取属性

2024-06-30 12:44:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用PySide2、QtQuick和QtCreator。 我试图使它使用QML文件中存储的文本字段中的变量,并运行命令,使用print()将变量打印到控制台中

在main.py文件中,我创建了以下代码,用于查找加密货币资产的价格

def assetSet(self):
    asset = "xrp"
    url2 = f'https://coinmarketcap.com/currencies/{asset}'
    page2 = requests.get(url2)
    soup2 = bs(page2.text, 'html.parser')
    price2 = soup2.find(class_="priceValue___11gHJ")
    price12 = str(price2)
    result2 = re.search('<div class="priceValue___11gHJ">(.*)</div>', price12)
    result12 = result2.group(1)
    self.setAsset.emit(f"The price of {asset} is {result12}")

在QML文件中,我有

            CustomButton{
                id: btnBdo
                text: "Check"
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenterOffset: 200
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenterOffset: 0
                font.pointSize: 20
                colorMouseOver: "#21252d"
                colorPressed: "#191d23"
                colorDefault: "#2a303a"
                onClicked: {
                    backend.assetSet()
                }
            }
            CustomTextField {
                id: textField
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenterOffset: -100
                anchors.horizontalCenter: parent.horizontalCenter
                font.pointSize: 20
                placeholderText: qsTr("Enter a name")
                objectName: "assetField"
            }

我希望资产变量等于存储在QML文件中的文本字段,并在单击按钮时运行此命令。 有办法做到这一点吗


Tags: 文件文本命令self资产assetqmlparent
1条回答
网友
1楼 · 发布于 2024-06-30 12:44:20

在这种情况下,最好使用接收数据的插槽,由于功能的执行也是同步的,因此不需要信号:

@Slot(str, result=str)
def assetSet(self, asset):
    url2 = f'https://coinmarketcap.com/currencies/{asset}'
    page2 = requests.get(url2)
    soup2 = bs(page2.text, 'html.parser')
    price2 = soup2.find(class_="priceValue___11gHJ")
    price12 = str(price2)
    result2 = re.search('<div class="priceValue___11gHJ">(.*)</div>', price12)
    result12 = result2.group(1)
    return f"The price of {asset} is {result12}"
onClicked: function(){
    var resp = backend.assetSet(textField.text)
    console.log(resp)
}

另一方面,请求会阻止Qt事件循环,导致GUI冻结,因此最好在另一个线程中执行该任务:

from functools import cached_property
import os.path
import re
import sys
import threading

import requests
from bs4 import BeautifulSoup as bs
from PySide2.QtCore import QObject, Qt, QUrl, Signal, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine


class Worker(QObject):
    finished = Signal(str)

    def start(self, asset):
        threading.Thread(target=self._execute, args=(asset,), daemon=True).start()

    def _execute(self, asset):
        url2 = f"https://coinmarketcap.com/currencies/{asset}"
        page2 = requests.get(url2)
        soup2 = bs(page2.text, "html.parser")
        price2 = soup2.find(class_="priceValue___11gHJ")
        price12 = str(price2)
        result2 = re.search('<div class="priceValue___11gHJ">(.*)</div>', price12)
        if result2 is not None:
            result12 = result2.group(1)
            self.finished.emit(f"The price of {asset} is {result12}")
            return
        self.finished.emit(f"failed for {asset}")


class Backend(QObject):
    assetChanged = Signal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.worker.finished.connect(self.assetChanged)

    @cached_property
    def worker(self):
        return Worker()

    @Slot(str)
    def assetSet(self, asset):
        self.worker.start(asset)


def main():
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    backend = Backend()

    engine.rootContext().setContextProperty("backend", backend)

    CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))

    file = os.path.join(CURRENT_DIR, "main.qml")
    url = QUrl.fromLocalFile(file)

    def handle_object_created(obj, obj_url):
        if obj is None and url == obj_url:
            QCoreApplication.exit(-1)

    engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
    engine.load(url)

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    width: 640
    height: 480
    visible: true

    Column {
        Button {
            id: button

            text: "Press me"
            onClicked: function() {
                backend.assetSet(textField.text);
            }
        }

        TextField {
            id: textField

            placeholderText: qsTr("Enter a name")
        }

        Label {
            id: label
        }

    }

    Connections {
        function onAssetChanged(asset) {
            label.text = asset;
        }

        target: backend
    }

}

相关问题 更多 >