2013年6月1日星期六

PyObjC教學

Apple教寫Objective C program,其中一個經典example是Currency Converter,已經不見於Mac Developer Library。這個example也有移植到PyObjC,但功能有限,要用家自行輸入Currency rate,所以本教學以補充這功能為例子。

要取得最新的匯價,可以見前作《Google Currency Converter》,換句話只要將這兩個program合併便成。原有program是要用家輸入Currency rate,將會改為用家選擇Local currency和Foreign currency。所以要先在CurrencyConverter.py裡增加兩個objc.IBOutlet()。

打開English.lproj/MainMenu.nib,

加兩個Pop Up Button和兩個Label。然後由ConverterController ctrl-drag去兩個Pop Up Button,指明它們的IBOutlet。

然後在awakeFromNib中,populate ISO Currency code到兩個Pop Up Button,幸好OS X的NSLocale已經內置selector commonISOCurrencyCodes,不需自行打這個list,真方便。除此之外,還可以取得system currency,將Local Country預設為system currency。

然後是在IBAction convert_中,加入Google url request便成。

詳細program如下,任何更新會push到github,歡迎fork和pull request。

import sys
from urllib.request import urlopen
from AppKit import *


class ConverterController(NSObject):

    # First define the IB Outlets, the 'ivar' calls below define new
    # instance variables in the objective-C class (e.g. visible
    # for introspection in objective-C)
    localCountry = objc.IBOutlet()
    foreignCountry = objc.IBOutlet()
    converter = objc.IBOutlet()
    dollarField = objc.IBOutlet()
    totalField = objc.IBOutlet()

    def awakeFromNib(self):
        # Provide some defaults for the user...
        currency_code = NSLocale.commonISOCurrencyCodes()
        self.localCountry.addItemsWithTitles_(currency_code)
        self.foreignCountry.addItemsWithTitles_(currency_code)
        # Get system currency setting
        locale = NSLocale.currentLocale()
        self.localCountry.selectItemWithTitle_(locale.objectForKey_(NSLocaleCurrencyCode))
        self.dollarField.setFloatValue_(100.0)

    @objc.IBAction
    def convert_(self, sender):
        amt = self.dollarField.floatValue()
        l = self.localCountry.titleOfSelectedItem()
        f = self.foreignCountry.titleOfSelectedItem()
        url = 'https://www.google.com/ig/calculator?hl=en&q={}{}=?{}'.format(amt, l, f)
        s = urlopen(url).read().replace(b'\xa0', b'').decode("utf-8")[1:-1].split(',')
        _, rv = s[1].split(':')
        print(rv)
        self.totalField.setStringValue_(rv.lstrip()[1:].split(' ')[0])


if __name__ == '__main__':
    sys.exit(NSApplicationMain(sys.argv))

沒有留言:

發佈留言