親手翻譯,歡迎轉載。動態修訂,請附原址:http://my.oschina.net/u/2306127/admin/edit-blog?blog=596025python
關於Orange Widgets的開發完整教程參見:http://orange-development.readthedocs.org/git
在建立了一個簡單的widgets幫助瞭解了基本概念以後,咱們來製做一個真正有用的widgets,能夠安裝到系統與其它的widgets一塊兒協同工做。github
咱們先從簡單的開始,在input中接收data set而後output輸出10%的數據實例。將其命名爲OWDataSamplerA。shell
首先,爲了在Orange Canvas的toolbox顯示,咱們建立 python project 名字爲:orange-demoapp
工程文件目錄以下:dom
orange-demo/ setup.py orangedemo/ __init__.py OWDataSamplerA.py
這個 orange-demo/setup.py
文件包括:svg
from setuptools import setup setup(name="Demo", packages=["orangedemo"], package_data={"orangedemo": ["icons/*.svg"]}, classifiers=["Example :: Invalid"], # Declare orangedemo package to contain widgets for the "Demo" category entry_points={"orange.widgets": ("Demo = orangedemo")}, )
注意,咱們申明瞭一個orangedemo軟件包,包含了的widgets放在Demo這一個類目中。函數
參考:https://github.com/biolab/orange3/wiki/Add-Ons測試
與前面的教程(快速入門)相似,新定義的模塊OWDataSamplerA所包含的widget以下:ui
import sys import numpy import Orange.data from Orange.widgets import widget, gui class OWDataSamplerA(widget.OWWidget): name = "Data Sampler" description = "Randomly selects a subset of instances from the data set" icon = "icons/DataSamplerA.svg" priority = 10 inputs = [("Data", Orange.data.Table, "set_data")] outputs = [("Sampled Data", Orange.data.Table)] want_main_area = False def __init__(self): super().__init__() # GUI box = gui.widgetBox(self.controlArea, "Info") self.infoa = gui.widgetLabel(box, 'No data on input yet, waiting to get something.') self.infob = gui.widgetLabel(box, '')
Widget 定義了一個input和一個output通道。對於input,是Data通道l,接受的對象類型爲Orange.data.Table,指定了
set_data()
方法來進行處理。咱們使用 output通道,命名爲「Sampled Data」,也是一樣的對象類型(Orange.data.Table
).
可能你已經注意到了,channels的類型是經過class來指定的,能夠使用任何類。但若是但願widgets能跟別的widgets通信的話,須要使用那些通用的類,若是不同的話,就要避免已經使用的名稱重複。幸運的是,做爲一個主要的設計原則,只有不多的channel類型在目前的Orange widgets中使用。
咱們的widget不顯示任何東西,咱們放置兩個labels在控件區域圍繞一個「Info」區域。
下面的四行指定了widgets的GUI。很是簡單,僅僅包含兩行文本,若是沒有什麼發生第一行將報告「no data yet」,第二行是空的狀態。
爲了完成這個widget,咱們如今須要定義如何處理輸入數據。這個工做放在set_data()
方法中(上面在介紹input channel時,咱們提到了這個方法的定義。)
def set_data(self, dataset): if dataset is not None: self.infoa.setText('%d instances in input data set' % len(dataset)) indices = numpy.random.permutation(len(dataset)) indices = indices[:int(numpy.ceil(len(dataset) * 0.1))] sample = dataset[indices] self.infob.setText('%d sampled instances' % len(sample)) self.send("Sampled Data", sample) else: self.infoa.setText('No data on input yet, waiting to get something.') self.infob.setText('') self.send("Sampled Data", None)
這個 dataset
參數就是經過input channel傳送過來的token。
對非空的token進行處理,widget在收到數據時更新界面,而後進行數據抽樣data sampling更新界面,報告抽樣的實例。最後,抽完樣的數據被送往output channel,名稱爲「Sampled Data」。
儘管咱們的widget已經準備好了測試,爲了最後的感受,咱們爲其設計一個圖標。圖標文件在widget header中指定,咱們命名爲DataSamplerA.svg
,而後放在icons子目錄下,位於orangedemo目錄中。
如今咱們安裝 orangedemo 軟件包。運行 pip install -e .
命令,在orange-demo目錄下,按照缺省的安裝,須要預先激活Orange的VirtualEnv環境,執行:
source orange3env/bin/activate
注意:安裝時可能須要 administrator/superuser 權限,根據python的安裝環境有關。
爲了測試,咱們把這個widget放到 Orange Canvas中,將會出現一個新的widget toolbox 叫作 Demo。點擊這個面板,將顯示數據抽樣器的圖標。鼠標在上面晃動時能夠看到更詳細的提示信息:
如今開始實際的測試,放置一個File widget ,而後載入iris.tab 數據集。再放上Data Sampler widget,而後雙擊打開窗口:
如今鏈接文件和抽樣器,從文件右側點按鼠標拉到抽樣器圖標的左側,釋放鼠標就能夠看到鏈接被創建起來。 token等待輸入,而後從文件widget發送到Data Sampler widget,,而後更新窗口:
要看一下抽樣器確實發送了數據到output通道,再添加和鏈接一個Data Table widget,以下所示:
試着打開另一個數據文件,改變將會經過Widget擴散,當數據表窗口打開時,可以當即看到抽樣的結果。試着移去文件和抽樣器之間的鏈接(右鍵點擊鏈接),看看數據表將發生什麼狀況?
做爲一個通用的規則,每個widget都有一個 main 啓動函數,這樣能夠在Orange Canvas以外獨立地運行。
將下面的代碼複製到到DataSampleDemo.py中,而後在Orange的VirtualEnv的環境下運行。
def main(argv=sys.argv): from PyQt4.QtGui import QApplication app = QApplication(list(argv)) args = app.argv() if len(argv) > 1: filename = argv[1] else: filename = "iris" ow = OWDataSamplerA() ow.show() ow.raise_() dataset = Orange.data.Table(filename) ow.set_data(dataset) ow.handleNewSignals() app.exec_() ow.set_data(None) ow.handleNewSignals() return 0 if __name__=="__main__": sys.exit(main())