zoukankan      html  css  js  c++  java
  • 用Python线程中更新QML内容

    这是一篇翻译过来的文章,是Qt和QML交互的一篇官方文章,原文地址在: http://developer.qt.nokia.com/wiki/Updating_QML_content_from_Python_threads

    这篇文章,是用PySide来制作的,因此练习之前,需要先安装PySide(Qt的另一种Python实现,由Nokia官方实现)。PySide的可以在下面下载:

    http://developer.qt.nokia.com/wiki/Category:LanguageBindings::PySide::Downloads

    如果你和我一样,使用的是Windows上的Python 2.6,则可以在下面路径下载:

    http://www.pyside.org/files/PySide-1.0.7qt474.win32-py2.6.exe

    =============================================================

    本文的PySide教程展现了如何使用内建的Python线程(非QThread,如threading.Thread)来负责背景的绘制(如下载文件)。在下载这个特殊的例子中,可能使用QNetworkAccessManager更加友好,但这是个例子,我们假定由于某种原因,你不能够使用QNetworkAccessManager这个类(如因为使用了Twisted或者因为已经有了特殊的下载代码,并且希望能够重用)。

    WorkingOnIt.py

    导入需要的模块

    我们将使用标准的Python线程模块(threading)和使用下载库(urllib)。对于PySide程序,我们需要标准的模块QtCore,QtGuiQtDeclarative:

    import os
    import sys
    import threading
    import urllib

    from PySide import QtCore, QtGui, QtDeclartive

    下载对象Downloader

    创建QObject的子类(这样我们可以在自己的下载对象中使用信号,槽和属性)和实现下载文件所需的所有属性以及在UI上显示当前状态。

    class Downloader(QtCore.QObject):
    def __init__(self, url, filename=None):
    super(Downloader, self).__init__()
    self._url = url
    if filename is None:
    filename = os.path.basename(self._url)

    self._filename = filename
    self._progress = 0
    self._running = False
    self._size = -1

    def _download(self):
    def reporthook(pos, block, total):
    if self.size != total:
    self._size = total
    self.on_size.emit()
    self.progress = float(pos * block ) / float(total)
    urllib.urlretrieve(self._url, self._filename, reporthook)
    self.running = False

    @QtCore.Slot()
    def start_download(self):
    if not self.running:
    self.running = True
    thread = threading.Thread(target = self._download)
    thread.start()

    def _get_progress(self):
    return self._progress

    def _set_progress(self, progress):
    self._progress = progress
    self.on_progress.emit()

    def _get_running(self):
    return self._running

    def _set_running(self, running):
    self._running = running
    self.on_running.emit()

    def _get_filename(self):
    return self._filename

    def _get_size(self):
    return self._size

    on_progress = QtCore.Signal()
    on_running = QtCore.Signal()
    on_filename = QtCore.Signal()
    on_size = QtCore.Signal()

    progress = QtCore.Property(float, _get_progress, _set_progress, notify=on_progress)
    running = QtCore.Property(bool, _get_running, _set_running, notify=on_running)
    filename = QtCore.Property(bool, _get_filename, notify=on_filename)
    size = QtCore.Property(bool, _get_size, notify=on_size)


    创建一个新的Downloader实例:

    作为一个例子,我们创建一个新的Downloader对象,用来从MeeGo库中下载N900的内核映像。(实际上测试的时候,发现该映像已经不能够被下载了,坑爹呀!,原先的代码是:

    downloader = Downloader('http://repo.meego.com/MeeGo/builds/trunk/1.1.80.8.20101130.1/handset/images/meego-handset-armv7l-n900/meego-handset-armv7l-n900-1.1.80.8.20101130.1-vmlinuz-2.6.35.3-13.6-n900')

    我替换为:)

    downloader = Downloader('http://www.pyside.org/files/PySide-1.0.7qt474.win32-py2.6.exe')

    QApplication,QDeclarativeView和上下文属性

    通常,我们创建一个QApplication和QDeclarativeView的实例。通过设置Downloader为view中的rootContext的上下文属性downloader,将Downloader导出到QML上下文中。然后简单的通过setSource导入QML文件,show出视图并执行应用:

        app = QtGui.QApplication(sys.argv)
    view = QtDeclarative.QDeclarativeView()
    view.rootContext().setContextProperty("downloader", downloader)
    view.setSource(__file__.replace('.py', '.qml'))
    view.show()
    sys.exit( app.exec_() )


    WorkingOnIt.qml

    该文件为downloader实例中的QML UI界面,最令人感兴趣的是:

    • 当按钮按下的时候,downloader.start_download()(一个PySide的槽)被调用,该方法启动线程
    • 当UI元素使用downloader的属性来决定元素可视与内容-当属性发出修改通知时自动更新。
    import Qt 4.7

    Rectangle
    {
    width
    :200; height:160;

    function formatProgress(size, progress){
    return "" + parseInt(progress*size/1024) + "KiB(" + parseInt(progress * 100.) + "%)";
    }

    Text
    {
    x
    : progressBar.x; y:20;
    width
    : progressBar.width;
    font.pixelSize
    :8;
    text
    :downloader.filename;
    elide
    :Text.ElideRight;
    }

    Rectangle
    {
    id
    :progressBar;
    color
    :"#aaa"

    x:20
    ; y:60;
    width
    :parent.width-40;
    height
    :20;

    Rectangle{
    color
    :downloader.progress<1?"#ee8":"#8e8"
    clip:true

    anchors{
    top:parent.top
    bottom:parent.bottom
    left:parent.left
    }

    parent.width * downloader.progress;

    Text
    {
    anchors{
    fill
    :parent;
    rightMargin
    :5;
    }
    color:"black";
    text:formatProgress(downloader.size, downloader.progress)
    verticalAlignment:Text.AlignVCenter;
    horizontalAlignment:Text.AlignRight;
    }
    }
    }

    Rectangle
    {
    anchors.left
    : progressBar.left;
    anchors.right
    : progressBar.right;

    color
    : "#aad";
    y
    : progressBar.y + progressBar.height + 20;
    height
    : 40;

    Text{
    anchors.fill
    :parent;
    color
    :"#003";
    text
    :downloader.running?"Please wait..." : "Start download"

    verticalAlignment : Text.AlignVCenter
    ;
    horizontalAlignment
    : Text.AlignHCenter;
    }

    MouseArea
    {
    anchors.fill
    : parent;
    onClicked
    : {
    downloader.start_download()
    ;
    }
    }
    }
    }


    (译注:没有合适的语法高亮,使用CSS类似的语法高亮机制。)

    例子执行的外观

    在同一个文件夹中保存文件WorkingOnIt.py和WorkingOnIt.qml,使用python WorkingOnIt.py执行应用。(官方的图片如下)

    thread-in-python-update-in-qml

    =============================================================

    我在windows上执行的时候,发现显示的时候会闪一下。

    这样的交互方式其实是Qt与JavaScript交互的一个重要特性。QML使用的是JavaScript语法进行控制操作,而Qt本身就内建支持了JavaScript语法,在Qt对象导出给JavaScript时,属性,槽是可以直接在JavaScript中调用的,这个在QScriptValue文档中就有明确的说明。

  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/ubunoon/p/QML_PySide.html
Copyright © 2011-2022 走看看