用Python线程中更新QML内容
2011-11-18 22:24
169 查看
这是一篇翻译过来的文章,是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,QtGui和QtDeclarative:
下载对象Downloader
创建QObject的子类(这样我们可以在自己的下载对象中使用信号,槽和属性)和实现下载文件所需的所有属性以及在UI上显示当前状态。
创建一个新的Downloader实例:
作为一个例子,我们创建一个新的Downloader对象,用来从MeeGo库中下载N900的内核映像。(实际上测试的时候,发现该映像已经不能够被下载了,坑爹呀!,原先的代码是:
我替换为:)
QApplication,QDeclarativeView和上下文属性
通常,我们创建一个QApplication和QDeclarativeView的实例。通过设置Downloader为view中的rootContext的上下文属性downloader,将Downloader导出到QML上下文中。然后简单的通过setSource导入QML文件,show出视图并执行应用:
WorkingOnIt.qml
该文件为downloader实例中的QML UI界面,最令人感兴趣的是:
当按钮按下的时候,downloader.start_download()(一个PySide的槽)被调用,该方法启动线程
当UI元素使用downloader的属性来决定元素可视与内容-当属性发出修改通知时自动更新。
(译注:没有合适的语法高亮,使用CSS类似的语法高亮机制。)
例子执行的外观
在同一个文件夹中保存文件WorkingOnIt.py和WorkingOnIt.qml,使用python WorkingOnIt.py执行应用。(官方的图片如下)
=============================================================
我在windows上执行的时候,发现显示的时候会闪一下。
这样的交互方式其实是Qt与JavaScript交互的一个重要特性。QML使用的是JavaScript语法进行控制操作,而Qt本身就内建支持了JavaScript语法,在Qt对象导出给JavaScript时,属性,槽是可以直接在JavaScript中调用的,这个在QScriptValue文档中就有明确的说明。
这篇文章,是用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,QtGui和QtDeclarative:
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 } width: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执行应用。(官方的图片如下)
=============================================================
我在windows上执行的时候,发现显示的时候会闪一下。
这样的交互方式其实是Qt与JavaScript交互的一个重要特性。QML使用的是JavaScript语法进行控制操作,而Qt本身就内建支持了JavaScript语法,在Qt对象导出给JavaScript时,属性,槽是可以直接在JavaScript中调用的,这个在QScriptValue文档中就有明确的说明。
相关文章推荐
- MFC子线程中更新控件内容的两种办法
- 个人对于线程安全的理解(内容会不断更新,只是个人理解,不具备权威性)
- QML的渲染方式相较于之前的版本也有了重大的更新(CPU线程负责绘制,GPU线程负责渲染),还有好多经常评论 good
- python基础内容概要(实时更新)
- 不同线程更新WinForm窗体的内容
- Python 3从入门到精通12-创建新文件并写入内容,在文件尾部更新内容
- 更新主窗口控件的内容1:子线程工作时同时更新主线程内的控件内容
- MFC——子线程中(跨线程)更新控件显示内容
- python 类编程相关内容(更新)
- python实现更新页面内容的小例子,已经修改成“更新订饭菜单“
- PostgreSQL连接python,postgresql在python 连接,创建表,创建表内容,插入操作,选择操作,更新操作,删除操作。
- python更新已经存在的excel 表内容
- [转]MFC子线程中更新控件内容的两种办法
- python使用多线程与自定义event更新tinter的内容
- 更新主窗口控件的内容2:子线程工作时同时更新主线程内的控件内容
- python 实现文件打开读取内容然后写入更新内容(文件只打开一次)
- 利用python-docx更新word中的表格内容
- Python 通过网站search功能监控网站内容更新
- 2.4学习内容 线程更新ui、
- Python使用subprocess更新文件内容