Leadership, Strategy and Qt By Mirko Boehm
一開始看到這篇文章有點嚇一跳(雖然大家都預期這遲早會發生的)。不過,後來又看了其他的網路上的討論,似乎不完全是這樣。Nokia是砍了德國Ulm這個地方的員工,裡面有大約100人是與Qt相關的。但是,Qt主要的開發者主要還是在Oslo,Brisbane及Berlin等地。
總之,我想最近Qt社群應該難免有點憂心吧!
Leadership, Strategy and Qt By Mirko Boehm
一開始看到這篇文章有點嚇一跳(雖然大家都預期這遲早會發生的)。不過,後來又看了其他的網路上的討論,似乎不完全是這樣。Nokia是砍了德國Ulm這個地方的員工,裡面有大約100人是與Qt相關的。但是,Qt主要的開發者主要還是在Oslo,Brisbane及Berlin等地。
總之,我想最近Qt社群應該難免有點憂心吧!
本文將要說明如何將PySide中的string list當成data model,讓QML可以顯示它。首先,我們先看看Python的程式部分。
[][1]
#!/usr/bin/env python
# coding: utf-8
import sys
import codecs
# Workaround to handle exception of cp65001 issue.
try:
codecs.lookup('cp65001')
except:
def cp65001(name):
if name.lower() == 'cp65001':
return codecs.lookup('utf-8')
codecs.register(cp65001)
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *
# The string list to show.
Zodiac = [
'Aries',
'Taurus',
'Gemini',
'Cancer',
'Leo',
'Virgo',
'Libra',
'Scorpius',
'Sagittarius',
'Capricornus',
'Aquarius',
'Pisces',
]
app = QApplication(sys.argv)
view = QDeclarativeView()
# Set model to view's context.
ctx = view.rootContext()
ctx.setContextProperty('exampleModel', Zodiac)
view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
view.setSource(QUrl('main.qml'))
view.show()
app.exec_()
這裡,我們建立了一個string list名為Zodiac,裡面放的就是黃道十二宮的名稱。要將任何資料由PySide傳遞給QML,最簡單的方式就是透過setContextProperty()來做。我們將Zodiac這個string list透過setContextProperty()將其命名為exampleModel,然後傳給QML。 PySide的部份就是這麼簡單,接下來就是QML的工作了。讓我們看看QML這邊要怎麼做:
import QtQuick 1.0
Rectangle {
width: 600
height: 600
Text {
id: caption
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 64
text: "Zodiac:"
font.pixelSize: 36
font.family: "Arial Black"
}
ListView {
anchors.top: caption.bottom
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
clip: true
/* exampleModel is passed from main.py by setContextProperty(). */
model: exampleModel
delegate: Component {
Rectangle {
color: "silver"
width: 450
height: 64
border.color: "DarkBlue"
border.width: 5
anchors.topMargin: 10
anchors.bottomMargin: 10
anchors.leftMargin: 10
anchors.rightMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
radius: 10
Text {
anchors.horizontalCenter: parent.horizontalCenter
/* The role of data in string list which made by PySide is
* 'modelData'. So we use modelData here to get the content
* of data.
*/
text: modelData
font.pixelSize: 36
font.family: "Arial Black"
color: "DarkBlue"
}
}
}
}
}
這邊我們不多廢話的說明QML使用model的方法,這方面的資訊可以到QML的文件去查。這個QML中的重點有兩個地方,第一個就是我們要將前面PySide所指定的exampleModel property透過的model屬性指定給ListView。第二就是在ListView的delegate裡面,當string list指定給QML後,我們要記得此時預設的資料的role是叫做modelData。所以我們只需要在要顯示資料的地方放上modelData,string list的內容就會一個接著一個的被取出來。就是這麼簡單!
[1]:
參加PyCon Taiwan 2012回來了!說是參加,實際上就是去了半天而已。說實在的,什麼時候工作才會不要這麼忙,這樣我才可以好好的參加這些在週末舉辦的研討會。看到前面幾位講者的投影片內容都很豐富,頁數也不少。我實在為自己大概不到10頁的內容感到擔心,上台前,還一直在想如果只講了10分鐘就把投影片用完的話,要準備怎麼樣的話笑話來撐場面。後來,臨時在前一個人演講的時候,另外加了一頁上去,剛好湊滿10頁!
另外,這次演講,我採用了一個很大膽的策略。也就是我的內容都是用QtQuick+PySide寫出來的。並且在現場直接執行跟操作的。以演講來說,這是個風險蠻大的作法。這考驗著QtQuick+PySide的穩定性,還有我自己coding的品質。如果現場程式crash掉或是丟出什麼exception而結束掉,那就糗大啦!
之所以使用這樣大膽的策略,主要是考慮到當大家最後知道原來整場presenation就是一個demo時,應該會印象深刻吧!而且,如果最後太快講完了,我就拿source code出來講。哈哈!
還好,這次的時間掌控的比我想像中的好,時間剛剛好!可惜最後『假裝demo』的梗鋪陳的不夠有力,有點弱掉了。應該要假裝DEMO失敗來嚇嚇大家,這樣才會讓所有人印象更深刻吧!
無論如何,這次talk的表現還不算太難看。最令人高興的是,整個活動很成功!第一次看到這麼多Python同好聚在一起,好像空氣中都充滿了Python粒子,吸了一口就全身充滿了Python的力量 :)
這些舉辦活動的工作人員真是辛苦了。謝謝他們。
PS: 其實這次發現一個蠻令我驚訝的事情,我坐位置上的時候,放眼往去一般NB與Mac Book Air的比例居然接近 1 : 1。這還蠻有趣的,值得研究研究。
對於檔案的搜尋,我們可以透過glob或是fnmatch的方式進行。但是如果只是比對字串,是不是也能用同樣的wildcard語法呢?其實,一切遠比你想的簡單。因為fnmatch有提供一個叫做translate的方法,可以把用來比對的wildcard字串,轉換成為regexp。去看看fnmatch module的文件,你就會看到一個說明如何使用的範例了。我將這個範例修改一下,使他變得更容易使用。
[][1]
import fnmatch, re
def wildcard_match(wildcard, *string_list):
"""Wildcard-style string match function.
:param wildcard: the wildcard string.
:param string_list: The list of string to be search.
:return: The result is a list which contains the matched strings.
If no string matched, an empty list will be returned.
"""
regex = fnmatch.translate(wildcard)
pattern = re.compile(regex)
matched_list = []
for s in string_list:
if pattern.match(s):
matched_list.append(s)
return matched_list
[1]:
你是否有這樣的經驗,明明沒問題的script,拿到某的電腦一直看到下面的訊息而無法執行。
LookupError: unknown encoding: cp65001
cp65001是什麼鬼!?其實,它就是UTF8阿!只是,Microsoft喜歡叫他cp65001(code page 65001號)。附帶一提,我們常用的Big5是cp950。想要知道你目前所使用的code page可以在Windows的console視窗執行
[][1] chcp
就可以看到。 為了要避免這樣的問題,我們要告訴Python,cp65001就是utf-8。因此,利用下面的script我們可以讓cp65001變成utf-8。
## A workaround to alias utf8 encoding to cp65001(Microsoft's utf8)
try:
codecs.lookup('cp65001')
except:
def cp65001(name):
if name.lower() == 'cp65001':
return codecs.lookup('utf-8')
codecs.register(cp65001)
解決Python script無法在cp65001的console下執行的問題
[1]:
假設你已經有一個使用QDeclarativeView的程式,你覺得顯示效能始終不夠滿意。如何才能增進程式的效能了?讓我們看看下面這個簡單的程式。
[][1]
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *
class MyView(QDeclarativeView):
def __init__(self, src):
super(MyView, self).__init__()
self.setAttribute(Qt.WA_TranslucentBackground)
self.viewport().setAutoFillBackground(False)
self.setWindowTitle('My QML Windows')
self.setSource(src)
self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
app = QApplication([])
view = MyView(src="MyView.qml")
view.show()
app.exec_()
其實,需要的工作遠比你想像的容易。只要稍作修改,就可以透過OpenGL來加速程式了!
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtOpenGL import *
from PySide.QtDeclarative import *
class MyView(QDeclarativeView):
def __init__(self, src, useOpenGL=False):
super(MyView, self).__init__()
if useOpenGL:
format = QGLFormat.defaultFormat()
format.setSampleBuffers(False)
glw = QGLWidget(format)
glw.setAutoFillBackground(False)
self.setViewport(glw)
self.setAttribute(Qt.WA_TranslucentBackground)
self.viewport().setAutoFillBackground(False)
self.setWindowTitle('My QML Windows')
self.setSource(src)
self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
app = QApplication([])
view = MyView(src="MyView.qml", useOpenGL=True)
view.show()
app.exec_()
[1]:
之前透過MinGW32與Qwt來開發程式一直都相安無事。最近嘗試使用Visual Studio 2010,Qt及Qwt來開發另外一個程式,卻遇上了下面這樣的錯誤:
moc_xxx.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject const QwtPlot::staticMetaObject" (?staticMetaObject@QwtPlot@@2UQMetaObject@@B)
[][1]後來終於在stackoverflow上面找到答案。其實解決方法極為簡單,只需要把QWT_DLL設成empty就可以了。看起來是因為Qwt對於import/export library的地方沒有自動偵測,所以導致這個問題。因此,強制設定QWT_DLL為empty就可以讓Qwt內由 moc 與 Q_DECL_EXPORT 所引起的問題得到解決。
可以在你的pro檔案內,加上下面的敘述:
DEFINES += QWT_DLL
這樣就可以把QWT_DLL變成empty了。
[1]:
之前買了一塊Xilinx Spartan-3E Starter Kit在家裡,除了寫寫小東西讓LED燈閃來閃去外,也就沒有做過什麼了。其實之前一直想把OpenRISC弄上去試看看。無奈當時相關資訊有限,所以弄了一兩天弄不出來,也就打住了!
不過,最近重新上網找了一下,發現在OpenRISC網站上已經有人弄成HOWTO了!找個時間來試看看吧!
開始使用Git,寫點筆記幫助記憶。
今天在編譯了Qwt 6.0.1給Qt 4.7.4使用,但是在連結到我自己的程式時遇到了奇怪的問題,首先是編譯時出現了一個奇怪的警告:
:-1: warning: auto-importing has been activated without --enable-auto-import
specified on the command line.
接著就是在執行的時候看連畫面都看不到就跑出下面這個包含錯誤代碼(0xC0000005)的對話框。
[][1]
由於什麼都看不到,連debug的工具都派不上用場。只好到網路上找找有沒有人跟我有一樣的問題。果然找到了下面這篇:
根據這篇文章是說,不知道為何Qt 4.7.4中把一個關於linker的--enable-auto-import參數給拿掉了。所以只要把它加回去就OK了!
查了一下ld的文件,簡單的說,這個選項是把 連結到 _imp 。意思還不是很瞭解,但是我想大概是符號連結的naming convention相容性的處理吧。
接著就是要把這個選項給弄回去了!文章中提到了一個作法是在qmake.conf中對QMAKE_LFLAGS加上"-Wl,--import-auto-import"。qmake.conf是放在 $(QT_DIR)\Desktop\Qt\4.7.4\mingw\mkspecs\win32-g++。
但是,不過因為我不確定這個東西有沒有副作用,所以就改在自己程式的pro檔案中加入下面的敘述:
QMAKE_LFLAGS += -Wl,-enable-auto-import
加了這行後,程式就順利的compile出來,也可以正常執行了!
[1]: