NASZE SERWISY:    ANDROID   LINUX   MAEMO   SYMBIAN   WEBOS




Hosting sponsoruje:



GRIN3 - polskie fonty

Profesjonalne czcionki z polskimi znakami - czcionki.com

OpenMobile on Facebook


 

[S60v3] Zabawy z Pythonem

Odpowiednie forum do zadawania pytań dotyczących rozpoczęcia programowania.

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 7 sierpnia 2008, o 00:30

Wszystkim fanom PyS60 polecam http://www.mobilepythonbook.org/ , szczególnie "Over 100 inspiring and fully working application examples are provided (see List of Examples) that can be instantly executed on your S60 phone. " , wszystkie do ściągnięcia i analizy. Jeśli są chętni na rozgryzanie Pythona zapraszam do analizy poszczególnych skryptów. Tak na zachętę , skrypt nr.28 (autorstwa Jurgena Scheible) , czyli wiązanie klawiatury ze zdefiniowanymi funkcjami:

import appuifw, e32, key_codes

def up():
appuifw.note(u"Arrow up was pressed")

def two():
appuifw.note(u"Key 2 was pressed")

def quit():
app_lock.signal()

canvas = appuifw.Canvas()
appuifw.app.body = canvas

canvas.bind(key_codes.EKeyUpArrow, up)
canvas.bind(key_codes.EKey2, two)

appuifw.app.exit_key_handler = quit
app_lock = e32.Ao_lock()
app_lock.wait()

importujemy moduł interfejsu graficznego , moduł e32 , który wedle opisu oferuje wiele użytecznych niskopoziomowych obiektów i funkcji , oraz moduł obsługi klawiatury
def(injujemy) funkcję up , której zadaniem będzie wyświetlenie notki o naciśnięciu strzałki (manipulatora) w górę
drugą funkcję wyświetlającą komunikat o naciśnięciu klawisza 2
definiujemy funkcję quit z obiektem e32.Ao_lock() i wywołanej na rzecz tego obiektu funckji sleep() , która musi być wywołana , jeśli chcemy zakończyć działanie aplikacji.

Tworzymy zmienną canvas (płótno) której przypisujemy Canvas() czyli płótno na którym można wyświetlać różne elementy aplikacji
ciału (body) aplikacji (app) obsługiwanej przez moduł appuifw przypisujemy "płótno" , można to zapisac nastepująco:

appuifw.app.body = canvas = appuifw.Canvas()

Funkcja canvas.bind wiąże przyciśnięty klawisz (key_codes. xxx) z wywoływaną funckją ,
w tym wypadku oczywiste jest , że wywołujemy funkcję up , bądź two
key_codes można znaleźć na stronie 25 PyS60 Library Reference 1.3.1 final

Jak widzimy poniżej funkcja quit jest przydzielona do specjalnej zmiennej appuifw.app.exit_key_handler
zmienna app_lock = przypisujemy obiekt (Object) e32.Ao_lock() , czyli wywołanie z modułu e32 funkcji Ao.lock() ,
a nastepnie wywołujemy funckję wait () dla obiektu e32.Ao_lock() która "wprawia" aplikację w stan oczekiwania aż do momentu wybrania opcji/funkcji wyjdź/quit (zdefiniowanej w naszym skrypcie)

Wszelkie krytyczne uwagi mile widziane.
Miłej zabawy z Pythonem:-)
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 7 sierpnia 2008, o 00:33

Sorry:
Kod: Zaznacz cały
import appuifw, e32, key_codes

def up():
    appuifw.note(u"Arrow up was pressed")
   
def two():
    appuifw.note(u"Key 2 was pressed")   

def quit():
    app_lock.signal()

canvas = appuifw.Canvas()
appuifw.app.body = canvas

canvas.bind(key_codes.EKeyUpArrow, up)
canvas.bind(key_codes.EKey2, two)

appuifw.app.exit_key_handler = quit
app_lock = e32.Ao_lock()
app_lock.wait()


, teraz powinno być lepiej (wcięcia , w kodzie)
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez reaper7 » 7 sierpnia 2008, o 07:23

@issa
select_access_point() może być w module e32socket - to skompilowany moduł ale są dostępne źródła w c więc można podglądnąć...

interesuje mnie jednak dokładnie taki przypadek jak jest u mnie czyli:
ustawiony punkt dostępu w menu narzędzia->ustawienia->połączenie->punkty dostępu,
z wpisanym ssid access pointa do którego się łączymy ale koniecznie z adresem ip uzyskiwanym z AP za pomocą DHCP (nie ustawionym na sztywno w telefonie!)

jeśli ktoś ma taką konfigurację i mógłby to sprawdzić u siebie byłbym bardzo wdzięczny.

tymczasem poradziłem sobie w troszkę okrężny sposób:
http://discussion.forum.nokia.com/forum/showpost.php?p=450527&postcount=10
Avatar użytkownika
reaper7
1%
1%
 
Posty: 23
Dołączył(a): 14 kwietnia 2008, o 08:37
    WindowsXPFirefox

Re: [S60v3] Zabawy z Pythonem

Postprzez Selph » 7 sierpnia 2008, o 09:45

A czy istnieje jakieś wygodniejsze od notatnika narzędzie do pisania które poza kolorowamiem składni (to sobie znajdę) będzie posiadało podpowiadanie składni? Np w borlandowskich (teraz codegear) kombajnach miałem taką fajną opcję że po wpisaniu nazwy jakiejś klasy i kropce dostawałem listę z metodami przez nią używanymi, typami danych pobieranymi i zwracanymi itp. Jest coś takiego do pythona? Albo chociaż jakiś spis instrukcji z typami danych i działaniem gdzieś jest?
Avatar użytkownika
Selph
70%
70%
 
Posty: 941
Dołączył(a): 11 maja 2008, o 14:32
Lokalizacja: Warszawa
Mod.tel.: Nokia N81 8GB
FW: 21.0.010
    unknownOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 7 sierpnia 2008, o 10:49

Według mojej wspaniałej , napisanej po mistrzowsku na odczepnego książki "Python od podstaw" , najlepie ściągnąć sobie Python Card , zawiera Python WinEditor , ze wspomnianymi podkolorowaniami , podowiedziami funkcji itp. Jeśli ktoś chciałby pisać kod w telefonie to najlepszy jest chyba wspomniany powyżej PED , czyli PythonEditor.
***reaper7 - czy mógłbym prosić o dokładne tłumaczenie skryptu w wolnej chwili? Kod jest dla mnie prawie zrozumiały , z chęcią dowiedziałbym się jednak coś więcej o argumentach funkcji socket , użycia atrybutu bidn i sendto , testowałem ten moduł z funkcją bt_obex_discover i przesyłania plików z funckją bt_obex_send_file , ale tu nie wszystko jest dla mnie jasne. Z góry dzięki.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez reaper7 » 7 sierpnia 2008, o 11:26

@issa

powiem tak...
ja korzystałem z gotowych przykładów modułu socket,
wymyśliłem sobie (znając podstawy protokołu udp) że poznam ip
wysyłając pakiet udp broadcastem na całą sieć - pakiet taki niesie dane ale także
ip maszyny (telefonu) z którego jest wysyłany.

skrypt zawiera więc po kolei:
deklaracje zmiennych
Kod: Zaznacz cały
msg = "Ok"
intip = "0.0.0.0"
port = 8511


ustawienie socket'a w tryb wysyłania datagramu udp
opisane np tu: http://www.ii.uni.wroc.pl/~marcinm/dyd/python/python_10.pdf
Kod: Zaznacz cały
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


tradycyjna metoda wybierania domyślnego punku dostępu do późniejszych operacji na nim:
Kod: Zaznacz cały
apid = None
apid = socket.select_access_point()
if not apid:
    sys.exit()
apo = socket.access_point(apid)
socket.set_default_access_point(apo)
apo.start()


no i teraz organizujemy serwer czyli nasłuchiwacza:
Kod: Zaznacz cały
s.bind(("0.0.0.0", port))


i klienta-nadawcę który wysyła dane (msg) w świat a nie do konkretnej maszyny(bo 255.255.255.255):
Kod: Zaznacz cały
s.sendto(msg, ("255.255.255.255", port))


i czekamy w pętelce na dane i upragnione IP nadawcy czyli moje własne :) :
Kod: Zaznacz cały
while 1:
    data, addr = s.recvfrom(1024)
    intip = addr[0]
    if intip <> "":
        print intip
        break
apo.stop()


nie jestem zbyt biegły w sztuce programowania więc może to wyjaśnienie też nie jest zbyt jasne i precyzyjne,
w każdym bądź razie wynik działania jest dla mnie satysfakcjonujący choć sam skrypt wymaga jeszcze szlifów
gdyż nie sprawdza istotnych rzeczy przed wysłaniem danych.
Avatar użytkownika
reaper7
1%
1%
 
Posty: 23
Dołączył(a): 14 kwietnia 2008, o 08:37
    WindowsXPFirefox

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 8 sierpnia 2008, o 23:44

Witam. Dziś opis skryptu nr. 56 z podręcznika "Mobile Python" , który umożliwi nam (albo i nie:) przesłanie zrobionej fotografii przez blutooth do innego telefonu. (skrypt nr 56 , autorstwa Jurgena Scheible). Nie będę go wrzucał w znacziki , ponieważ jest on do ściagnięcia , ale postaram się przedstawić go w nieco innej formie z czytelniejszym opisem kodu

import camera, e32, socket, appuifw
importujemy moduł kamery , e32 , socket oraz moduł interfejsu graficznego

PHOTO = u"e:\\Images\\bt_photo_send.jpg"
twrzymy obiekt PHOTO i ścieżkę do obiektu/pliku bt_photo_send , czyli naszą fotkę w folderze Images

def send_photo():
tworzymy funckję send_photo()
try:
tworzymy obsługę wyjątku , jeśli wywołanie funkcji bt_obex_discover z modułu socket
address, services = socket.bt_obex_discover(),
-------------------------------------------------------------------------------------------------
aby lepiej zrozumieć wartości zwracane , proponuję włączyć BT w drugim telefonie i w interaktywnym trybie wpisać
>>> from socket import *
>>> a,b = bt_obex_discover()
>>> print a , b
>>> print type(a) , print type (b)
--------------------------------------------------------------------------------------------------

nie zwróci wartości address oraz services , zostanie wywołany wyjątek

except:
appuifw.note(u"OBEX Push not available", "error")
czyli na ekranie zobaczymy notkę error , że urządzenie jest nieosiągalne
return
powrót do appuifw.app.menu , czyli wyboru opcji z rozwijanego Menu

if u'OBEX Object Push' in services:
jeżeli w słowniku services występuje łańcuch (klucz) 'OBEX Object Push', wtedy
channel = services.values()[0]
zmiennej channel przypisz wartość przyporządkowaną do pierwszego [0] klucza ze słownika services (przepraszam , sam się tu zamieszałem , jak to sensownie opisać)
socket.bt_obex_send_file(address, channel, PHOTO)
z modułu socket wywołujemy funkcję bt_obex_send_file , czyli jak sama nazwa mówi do urządzenia BT , będziemy wysyłac plik:

I tu mały opis...
funkcja przyjmuje jako parametry (address urządzenia ) , który otrzymaliśmy z wywołania funkcji bt_obex_discover()
(channel) czyli kanał , który sobie wyekstrahowaliśmy w postaci wartości ze słownika services jaki zwróciła funkcja bt_obex_discover()
oraz oczywiście obiekt PHOTO , czyli ścieżkę która wskazuje nam na wysyłany plik
teraz czekamy aż plik się wyśle (długo czekamy:) i...
appuifw.note(u"photo sent", "info")
pojawia się nam komunikat/note , że fotka wysłana

else:
appuifw.note(u"OBEX Push not available", "error")
w przeciwnym wypadku znów pojawia się nam error , że urządzenie jest niedostępne.

def take_photo():
tworzymy funckję take_photo
photo = camera.take_photo()

zmiennej photo przypisujemy wynik wywołania funkcji take_photo () (odsyłam do pierwszego skryptu w wątku)
canvas.blit(photo, scale = 1)
to opiszę dokładnie później z wszelkimi parametrami , w skrócie metoda blit kopiuje nam
źródłowy obszar do docelowego obszaru , czli w tym wypadku kopiuje (ukazuje nam na ekranie/płótnie/canvas) , naszą źródłową fotkę (photo)
photo.save(PHOTO)
na rzecz zmiennej photo wywołujemy metodę save , w której wskazujemy ścieżkę do pliku

reszta mam nadzieję nie wymaga opisu , ponieważ poza appuifw.app.menu , czyli wywolaniem menu
rozwijanego pod polem wyboru "Opcje" , reszta jest identyczna jak we wczesniejszym skrypcie

def quit():
app_lock.signal()

canvas = appuifw.Canvas()
appuifw.app.body = canvas
appuifw.app.exit_key_handler = quit
appuifw.app.title = u"BT photo send"
appuifw.app.menu = [(u"Take photo", take_photo),
(u"Send photo", send_photo)]
app_lock = e32.Ao_lock()
app_lock.wait()

Postaram się niedługo rozszerzyć troszkę skrypt i podać opis funckji star_findera() , która wywołuje wczesniej zdefiniowaną funckję vievinder , która tworzy tak strumień obiektów , czyli w tym wypadku jak nietrudno się domyśleć pozwoli nam na bieżąco śledzić na wyświetlaczu wszystko co rejestruje aparat.
Może trochę to pozornie zawiłe , ale na przykładzie będzie to wyglądac o wiele łatwiej.
Kończę harcerskim pozdrowieniem :-) z legendarnej już książki do c++
"Zobacz jakie to proste , a nie - zobacz jaki jestem mądry".
Trening czyni mistrza:-)
Tradycyjnie z góry dziekuję za wszelkie poprawki i krytyczne uwagi.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 8 sierpnia 2008, o 23:48

Oczywiście na końcu miało być , "podać opis funkcji start_finder() , która wywołuje wczesniej zdefiniowaną funckję viewfinder , oczy się kleją...
Acha , w oryginalnym skrypcie uzyskanie wartości ze słownika odbywa się przez przypisanie channel = services[u'OBEX Object Push'] , nie jest to dla mnie do końca zrozumiałe , dlatego posłużyłem się przypisaniem channel = services.values()[0]
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 24 sierpnia 2008, o 15:50

Witam po przerwie. Trochę się obijałem:) , trochę chorowałem , wdawałem w (jałowe) spory na forach , ale i trochę się uczyłem. Doszły nowe ksiązki , jak choćby "Receptury.Python" , "Receptury. Java" , nic tylko się uczyć. Ale do rzecz... Obiecałem wczesniej rozszerzyć powyższy skrypt o tak zwanego "znajdowacza widoku" , który jak pisałem powyżej tworzy nam strumień obiektów , czyli pozwala nam mieć po prostu podgląd z kamery na ekranie naszego telefonu. Jako że Polacy nie gęsi , w skrypcie zdefiniowana jest przyjemnie brzmiąca funkcja o nazwie strumien_obrazow , która jako parametr przyjmuje obiekt obraz. Jak widać funkcja ta wywoływana jest z funkcji wbudowanej start_finder. W ciele funkcji strumien_obrazów , mamy tylko bardzo proste przypisanie które wywołuje nam na rzecz naszego ekranu/canvas , funkcję blit , która kopije nam nasz obiekt - obraz na ekran.

import camera, e32, socket, appuifw

PHOTO = u"e:\\Images\\bt_photo_send.jpg"

def send_photo():
try:
address, services = socket.bt_obex_discover()
except:
appuifw.note(u"OBEX Push not available", "error")
return

if u'OBEX Object Push' in services:
channel = services[u'OBEX Object Push']
socket.bt_obex_send_file(address, channel, PHOTO)
appuifw.note(u"photo sent", "info")
else:
appuifw.note(u"OBEX Push not available", "error")

def strumien_obrazow(obraz):
canvas.blit(obraz)


def take_photo():
camera.stop_finder()
photo = camera.take_photo()
canvas.blit(photo, scale = 1)
photo.save(PHOTO)

def quit():
app_lock.signal()

canvas = appuifw.Canvas()
appuifw.app.body = canvas
appuifw.app.exit_key_handler = quit
appuifw.app.title = u"BT photo send"
camera.start_finder(strumien_obrazow)
appuifw.app.menu = [(u"Take photo", take_photo),
(u"Send photo", send_photo)]
app_lock = e32.Ao_lock()
app_lock.wait()


I w zbacznikach:
Kod: Zaznacz cały

import camera, e32, socket, appuifw

PHOTO = u"e:\\Images\\bt_photo_send.jpg"

def send_photo():
    try:
            address, services = socket.bt_obex_discover()
    except:
            appuifw.note(u"OBEX Push not available", "error")
            return
       
    if u'OBEX Object Push' in services:
            channel = services[u'OBEX Object Push']
            socket.bt_obex_send_file(address, channel, PHOTO)
            appuifw.note(u"photo sent", "info")
    else:
            appuifw.note(u"OBEX Push not available", "error")

def strumien_obrazow(obraz):
    canvas.blit(obraz)


def take_photo():
    camera.stop_finder()
    photo = camera.take_photo()
    canvas.blit(photo, scale = 1)
    photo.save(PHOTO)

def quit():
    app_lock.signal()

canvas = appuifw.Canvas()
appuifw.app.body = canvas
appuifw.app.exit_key_handler = quit
appuifw.app.title = u"BT photo send"
camera.start_finder(strumien_obrazow)
appuifw.app.menu = [(u"Take photo", take_photo),
                    (u"Send photo", send_photo)]
app_lock = e32.Ao_lock()
app_lock.wait()

issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 24 sierpnia 2008, o 17:31

A teraz powiedzmy sobie parę słów o słownkach. W sumie pisaliśmy , czy raczej wykorzystywaliśmy słownik , czy raczej wartość ze słownika jaki zwracała nam funkcja bt_obex_discover. Zaawansowni programiści - proszę się nie śmiać:) , nie każdy wie wszystko od razu , a ten opis przyda nam się kiedy będziemy obsługiwać klawiaturę za pomocą funckji event_callback

A więc definicyjnie słownik przechowuje kolekcje dowolnych obiektów. Słownik ma tak zwany klucz i wartość , najlepiej zilustrować to na przykładzie:

słownik = {"sniadanie":"jajecznica" , "objad":"kotlecik" , "kolacja":"kanapeczka"}
I oto mamy słownik...
Słownik składa się z par , klucz : wartość , możemy to odczytywać na dwa sposoby:
sposób pierwszy z użyciem wbudowanej funkcji values() oraz keys()
Sprawdzmy użycie metody keys()

klucze=słownik.keys()
print klucze

i otrzymujemy liste kluczy (keys)

[kolacja , sniadanie , objad]

czyli lista kluczy nie odpowiada kolejności tych ze słownika , więc jest nieuporządkowana.
Możemy czywiście pobrać sobie klucz i wartość z listy za pomocą odpowiedniego indeksu , tak jak zrobiliśmy w skrypcie powyżej , gdzie mieliśmy zwrócony słownik

channel = services.values()[0]

, tak samo możemy więc postąpić z naszym słownikiem słownik , czyli

klucz=slownik.keys()[0] , albo [1] lub [2] (tyle ile mamy kluczy -1 , czyli [klucze-1] , bo indeksowanie zaczyna się od 0)
otrzymamy odpowiedni klucz = kolacja , śniadanie lub objad.
Wartości ze słownika można pobierać także w inny sposób przez klucz , a jak zobaczymy w następnym skrypcie , tak właśnie będziemy postępowac , by powiązać/porównać wartość jaką pobierzemy ze słownika z kodem klawiatury , który pozwoli nam na wywołanie porządanej funckji.
wartosc1=slownik ["sniadanie"] , oczywiście wartosc1 = "jajecznica" , wartosc2=slownik["objad"] , w zmiennej wartosc2 będzie oczywiście "kotlecik" itp.

Do zobaczenia przy następnym skrypcie.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 12 września 2008, o 11:21

Java. Się śni mi , się śni mi...
I nasz Python:-)
A teraz coś z własnie z nieco innej beczki , co spróbujemy porównać z naszym skryptem w Pythonie z którego będziemy dalej uczyć się możliwości Mobilnego Pythona
Na początek prosta klasa w Javie , zawierająca metodę , która umozliwi nam otrzymanie wyniku mnożenia dwóch liczb

class Mnozenie
{public Mnozenie (int a , int b)
{
liczba_a=a;
liczba_b=b;
}
public int oblicz()
{
return liczba_a*liczba_b;
}
private int liczba_a
private int liczba_b
}

W metodzie Main

Mnozenie iloczyn = new Mnozenie (2,3);
int wynik = iloczyn.oblicz();


Na samej górze tworzymy klasę Mnożenie , następnie tworzymy konstruktor , który będzie nam inicjalizował obiekty klasy Mnożenie , w ciele konstruktora następuje przypisanie podanych wartości do pól składowych , które są zadeklarowane na końcu. Następnie w metodzie Main tworzymy obiekt klasy Mnozenie , oraz wywołujemy metodę oblicz na rzecz obiektu iloczyn z wartościami 2,3

A teraz jak można osiągnąć ten sam efekt , wykorzystując metodę statyczną , czyli bez tworzenia w metodzie Main obiektu klasy Mnozenie (to jest kluczowa sprawa)



class Mnozenie
{
public static int oblicz (int a , int b)
{
return a*b
}
}
int wynik = Mnozenie.oblicz(2,3)
Proszę zwrócić uwagę na zapis
obiekt = Klasa.metoda()

Uściślając funkcja zawarta w Klasie przyjmuje w Pythonie nazwę metody.
--------------------------------------------------------------------------------------------------------------
Do rzeczy....
(autorem skryptu jest Jurgen Scheible)

import appuifw, e32, key_codes, graphics

BIALY = (255,255,255)
CZERWONY = (255,0,0)
NIEBIESKI = (0,0,255)
ZOLTY = (255,255,0)

def rysuj_kwadrat():
obiekt.rectangle((50,100,100,150), fill = ZOLTY)

def rysuj_punkt():
obiekt.point((90,50), outline = CZERWONY, width = 30)

def rysuj_tekst():
obiekt.text((10,40), u'Hello', fill = BIALY)

def przerysuj(rect):
if obiekt: plotno.blit(obiekt)

def zdarzeniet(event):
ev = event['keycode']
if event['type'] == appuifw.EEventKeyDown:
obiekt.clear(NIEBIESKI)

if ev == key_codes.EKeyUpArrow:
rysuj_punkt()
elif ev == key_codes.EKeyRightArrow:
rysuj_tekst()
elif ev == key_codes.EKeyDownArrow:
rysuj_kwadrat()
elif ev == key_codes.EKeyLeftArrow:
rysuj_punkt()
rysuj_tekst()
rysuj_punkt()
przerysuj(None)

def wyjscie():
aplikacja_zamknij.signal()

obiekt = None
plotno = appuifw.Canvas(\
redraw_callback = przerysuj,\
event_callback = zdarzenie)

appuifw.app.body = plotno
appuifw.app.screen = 'full'
appuifw.app.exit_key_handler = wyjscie

w, h = plotno.size
obiekt = graphics.Image.new((w, h))
obiekt.clear(NIEBIESKI)

aplikacja_zamknij = e32.Ao_lock()
aplikacja_zamknij.wait()

Importujemu moduł interfejsu graficznego , systemowy , obsługi klawiatury , grafiki
Tworzymy cztery zmienne do których przypisne są listy definiujące kolor (Red , Green , Blue)

Tworzymy funkcję rysuj_kwadrat , na rzecz utworzonego obiektu (o tym poniżej) wywołujemy funkcję kwadrat (a,b,c,d) , a,b to położenie leweg górnego rogu , c,d położenie prawego dolnego rogu , fillto oczywiście kolor wypełnienia

Tworzymy funkcję rysuj_punkt , która tworzy nam okrąg o srodku o współrzędnych a,b , outline to kolor , a width to szerokość czy raczej średnica w pikselach

Tworzymy funkcję rysuj_tekst a,b to oczywiście współrzędne lewego górnego rogu w którym będzie zawieszony łancuch tekstowy , nastepnie u"tresc tekstu" , oraz kolor

Funkcja przerysuj (rect)....

... zostawmy t i przeskoczmy do ciekawej częsci skryptu , która w moim odczuciu ma właśnie związek z metodami statycznymi Javy, których przykład podałem na samym poczatku:


w, h = plotno.size
obiekt = graphics.Image.new((w, h))


wywołujemy metode size , na rzecz zmiennej plotno , która zwraca na szerokość i wysokość ekranu
Następnie tworzymy obiekt , no właśnie - klasy Canvas() /to jest bardzo wazne/
W Javie istnieje takze klasa Canvas , jak i klasa Image, która umożliwia stworzenie nowego , mutowalnego/modyfikowalnego obrazka , który składa się z białych pikseli i można na nim wykonywać różne operacje , jak ryswanie pikseli , kół , linii , elips
Klasa ta należy do pakietu javax.microedition.lcdui , a metoda która umożliwia stworzenie owego mutowalnego obrazka ma postać

public Image Image.createImage (int szer , int dlug)
Czy ta metoda , po imporcie pakietu javax.microedition.lcdui.* , nie przypomina nam naszego wywołania z Pythona?
graphics.Image.new((w, h))
Własnie , przypomina....
Co więcej proszę spojrzeć na przykładową metodę statyczną którą zaczelismy powyższy wątek , czy gdybyśmy na początku naszego skryptu zaimportowali moduł graphics w postaci form graphics import * , tworzenie naszego mutowalnego obiekty obiekt nie miałoby postaci
Image.new((w.h)) ?
Wygląga na to , że tak by własnie było.
Na tę chwilę zostawmy sobie skrypt do dalszej analizy w której spróbujemy znaleźć analogię pomiędzy klasą Canvas z Javy która zawiera metody do obsłgi klawiatury , oraz przerysowywania płótna.
Zobaczymy , czy funkcje wywoływalne w klasie Canvas jakie zawiera nasz skrypt w Pythonie , można podciągnąć pod definicję metod abstracyjnych , czyli takich , które zmuszą nasz do własnoreczengo zdefiniowania naszych funkcji , oraz spróbujemy wykorzystać właściwości słownika o których pisałem w porpzednicz watkach , czyli pobierania wartości przez klucz i wykorzystwania tych wartości.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 21 września 2008, o 22:12

Witam.
W międzyczasie piękny , prościutki przykład z http://wiki.forum.nokia.com/index.php/A ... rive_space , który pokazuje w praktycznym skrypcie formatowanie % oraz pobieranie wartości ze słownika przez klucz. Walczę dalej z Java2me , próbuję sobie to wszystko powoli składać w całość , szukam analogii pomiędzy java2me i pys60. Czytałem o "słuchaczach zdarzeń" , zastanawiam się , czy wywołanie:

appuifw.app.exit_key_handler=quit

nie jest klasycznym słuchaczem zdarzenia w Pythonie. Wprawdzie z tą nazwą się tam nie spotkałem , ale wygląda , że zaimplementowanie funkcji quit/wyjście , która musi być zdefiniowana by zamknąć aplikację w reakcji na naciśnięcie klawisza "wyjście" , jest owym "słuchaczem".
Polecam forum Nokii , jest tam masa ciekawych , prostych skryptów z bardzo dokładnymi opisami.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez reaper7 » 26 września 2008, o 11:02

poniżej źródło programu jaki napisałem sobie w związku z nerwowym przeszukiwaniem książki adresowej za każdym razem jak otrzymywałem sms'a od operatora o nieodebranym połączeniu(program opisany dokładniej TU: http://forum.symbianos.pl/viewtopic.php?f=68&t=28502 ) :
Kod: Zaznacz cały
# Reaper7
import e32
import os
import re
import string
import appuifw
import inbox
import contacts
import telephone

try:
  import minidb
except:
  appuifw.note(ru('Please install minidb module'),'error')
  os.abort()
 
path = 'C:\\data\\'

#PLUS
wr_def = u'\d+\D*(\d{2}.\d{2}.\d{2}/\d{2}:\d{2})\D{4}\d{2}(\d{11})'
smsfrom_def = u'KtoDzwoni'
kolind_def = 1

#ERA
#wr_def = u'\D*(\d{11})\D*(\d{2}/\d{2}_\d{2}:\d{2})'
#smsfrom_def = u'Kto tam'
#kolind_def = 0

def writekey(klucz, wartz):
  minidb.Open(u'wc_sets',path, update=0)
  minidb.Write(klucz, unicode(wartz))
  minidb.Close()

def readkey(str):
  minidb.Open(u'wc_sets',path, update=0)
  warto=minidb.Read(str)
  minidb.Close()
  return warto
 
def naekran():
    if ilosc <> 0:
        index = lb.current()
        dzwon = appuifw.query(add_1[index] + '\n' + add_2[index] + u'\n' + 'Call?', 'query')
        if dzwon:
            telephone.dial(add_1[index])

def checksettings():
    if not os.path.exists(path+'wc_sets.pydb'):
      minidb.Create(u'wc_sets',path)
      writekey(u'smsfrom',unicode(smsfrom_def))
      writekey(u'smsregexpr',unicode(wr_def))
      writekey(u'datorder',unicode(kolind_def))

def readsettings():
    global smsfrom, wr, kolind
    smsfrom = readkey(u'smsfrom')
    wr = readkey(u'smsregexpr')
    kolind = readkey(u'datorder')


class Settings:
    def __init__(s):
        import powlite_fm
        s.powlite_fm=powlite_fm
    def opeditor(s):
        kolejnosc=[u'Phone Number, Date&Time', u'Date&Time, Phone Number']
        form=appuifw.Form([
            (u'SmsFrom','text',readkey(u'smsfrom')),
            (u'RegExpr','text',readkey(u'smsregexpr')),
            (u'DataOrder','combo',(kolejnosc,int(readkey(u'datorder')))),],
            appuifw.FFormEditModeOnly|appuifw.FFormDoubleSpaced)
        form.execute()
       
        smsfrom = unicode(form[0][2])
        if not(smsfrom):
            smsfrom = smsfrom_def
        writekey(u'smsfrom',smsfrom)
       
        wr = unicode(form[1][2])
        if not(wr):
            wr = unicode(wr_def)
        writekey(u'smsregexpr',wr)
       
        kolind = int(form[2][2][1])
        writekey(u'datorder',unicode(kolind))
       
        readsettings()
        checkinbox()

def checkinbox():
    global entries, add_1, add_2, ilosc
    entries = []
    add_1 = []
    add_2 = []
    ilosc = 0
    for sms_id in box.sms_messages():
        if box.address(sms_id).find(smsfrom) >= 0:
            tekst = box.content(sms_id)
            polaczenia = tekst.split(';')
            for pol in polaczenia:
                roz = re.findall(wr, pol)
                if roz <> []:
                    ilosc += 1
                    datgod = roz[0][(not(kolind))]
                    numkont = roz[0][(kolind)]
                    kont_tmp = db.find(numkont)
                    if kont_tmp == []:
                        kont_tmp = db.find(numkont[2:])
                    if kont_tmp:
                        kont = kont_tmp[0]
                        kontid = kont.id
                        try:
                            imie = kont.find('first_name')[0].value
                        except:
                            imie = ''
                        try:
                            nazw = kont.find('last_name')[0].value
                        except:
                            nazw = ''
                        if (imie == '') & (nazw == ''):
                            nazw = 'Name & Surname are empty'
                        entries.append(unicode(nazw) + ' ' + unicode(imie))
                    else:
                        entries.append(u'Unknown Number')
                    add_1.append(u'+' + unicode(numkont))
                    add_2.append(unicode(datgod))
    ekran()

def ekran():
    global lb
    if ilosc == 0:
        entries.append(u'No Entry')
    lb = appuifw.Listbox(entries,naekran)
    appuifw.app.body = lb

def quit():
    app_lock.signal()
    appuifw.app.set_exit()

box = inbox.Inbox()
db = contacts.open()

checksettings()
readsettings()
settings=Settings()

appuifw.app.title = u'Who Called?'
appuifw.app.menu=[(u'Check Inbox',checkinbox),(u'Settings',settings.opeditor),(u'Exit',quit)]

checkinbox()

appuifw.app.exit_key_handler = quit
app_lock = e32.Ao_lock()
app_lock.wait()
Avatar użytkownika
reaper7
1%
1%
 
Posty: 23
Dołączył(a): 14 kwietnia 2008, o 08:37
    WindowsXPFirefox

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 2 listopada 2008, o 15:42

Witam po przerwie. Dalej cały czas zakuwam Javę i Pythona , ciągnę kilka srok (książek) za ogon , czytam po kilka razy , analizuję , wracam do tego co przeczytałem , czyli szara , siermiężna nauka programowania. Ten wpis nie będzie może o Pythonie , więc mam nadzieję , że mi się nie oberwie od admina , ale wpisuje się ogólnie w podstawy programowania. Jest to bardzo dokładny opis jednego z kodów źródłowych , tym razem Javy , dotyczący wysłania smsa. W moich książkach do Javy podkresla się wartość edukacyjną tego typu przykładów popartych dokładnym opisem , więc może komuś akurat się przyda w nauce. Przykład pochodzi ze strony http://wiki.forum.nokia.com/index.php/P ... e_Examples , http://wiki.forum.nokia.com/index.php/C ... a_text_SMS Oczywiście jeśli popełniłem jakiekolwiek błędy w "tłumaczeniu" , proszę o poprawki.
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Re: [S60v3] Zabawy z Pythonem

Postprzez issa » 2 listopada 2008, o 15:46

import java.io.IOException;
import java.io.InterruptedIOException;
import javax.microedition.io.Connector;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;

import klas
---------------

public class SMSMIDlet extends MIDlet implements CommandListener {
private Command sendCommand;
private Command exitCommand;
private Form mainForm;
private TextField smsNumber;
private TextField smsText;
private MessageConnection connection;

deklaracja klasy , implementacja interfejsu CommandListner (słuchacza zdarzeń) , implementacja interfesu wymusza wlasną definicję metod z klasy CommandListner
tworzenie pól składowych klasy SMSMIDlet, dwóch klasy Command do obsługi zdarzeń , send , exit , klasy Form , czyli formant/formatka na pozostałe elementy graficzne , pojemniki tekstowe klasy TextField , które będą zawierały numer docelowy oraz treśc wiadomości , obiekt klasy MessageConnection connection
-----------


public SMSMIDlet() {
mainForm = new Form("SMS Example");

smsNumber = new TextField("Phone number", null, 20,
TextField.PHONENUMBER);
mainForm.append(smsNumber);

smsText = new TextField("Text", null, 160, TextField.PLAIN);
mainForm.append(smsText);

sendCommand = new Command("Send", Command.ITEM, 0);
mainForm.addCommand(sendCommand);

exitCommand = new Command("Exit", Command.EXIT, 0);
mainForm.addCommand(exitCommand);

mainForm.setCommandListener(this);
}

definicja konstruktora (konstruktor inicjalizuje automatycznie każdy obiekt MIDletu klasy SMSMIDlet)
konstruktor obiektu mainForm tworzy formant i nadaje mu tytu "SMS Example" , konstruktor obiektu smsNumber - argumenty konstruktora: opis pola tekstowego , null/ten parametr ustawiony na null jest stringiem i umozliwia ustawienie domyślnego tekstu który będzie się pojawiał po pierwszym wyświetleniu pola tekstowego , liczba znaków , stała określająca dopuszczalny typ wprowadzanych danych , w tym wypadku tylko cyfry , konstruktor obiektu smsText : opis pola tekstowego , null , liczba znaków smsa 160 , stała PLAIN / czyli tekst zwykły , nie widziałem dokładnego opisu tej stałej)
, oraz konstruktor obiektu sendCommand , konstruktor: opis "przycisku" , typ , dzięki któremu telefon interpretuje rodzaj polecenia , oraz priorytet , jeśli dodana jest większa ilośc poleceń do przycisku.
obiekt ExitCommand - analogicznie jak powyżej
wszystkie inicjalizowane przez konstruktor obiekty dodawane są do formantu metodą append , obiekty odpowiedzialne za obsługę zdarzeń , dodawane są do formantu za pomocą metody addCommand ,czyli na rzecz formantu wywołaj metodę append oraz addCommand

ustaw słuchacza zdarzeń do formantu - setCommandListner , jako argument przekazywany jest niejawnie obiekt MIDletu (dlaczego , nie wiem)
-----------------
public void startApp() {
Display.getDisplay(this).setCurrent(mainForm);
}

public void pauseApp() {

}

public void destroyApp(boolean unconditional) {
if (connection != null) {
try {
// Close the message connection
connection.close();
} catch (IOException ex) {
// TODO: Exception handling
}
}
}
Ponieważ KAŻDY MIDlet dziedziczy z bazowej klasy MIDlet , należy w niej zdefiniować trzy abstrakcyjne metody które obsługują cykl życia MIDletu , a więc start aplikacji , pauzę (na przykład zachowanie podczas odebrania płaczenia) oraz zakończenie.
Publiczna metoda startApp() , w ciele metody następuje utworzenie obiektu menadżera ekranu który odpowiada za zarządzanie wyświetlaniem formantów
zwykle zapisywane jest to jako:
Display ekran=Display.getDisplay(this)
ekran.setCurrent(mainForm)
czyli tworzony jest obiekt menadżera ekranu , na jego rzecz wywoływana jest metoda ustawienia bieżącego formantu z formantem jako argumentem

metoda pauseApp w krótkich aplikacjach nie wymaga implementacji

metpda destroyApp z parametrem którym jest zmienna logiczna typu boolean unconditional
W ciele metody korzystamy z pola składowego connection , jeżeli pole connection nie jest null , należy zamknąć otwarte połaczenie , jeśli to się nie powiedzie generowany jest wyjątek
---------------------


public void commandAction(Command command, Displayable displayable) {
if (command == exitCommand) {
destroyApp(true);
notifyDestroyed();
} else if (command == sendCommand) {
handleSendCommand();
}
}
Zaimplementowana własnoręcznie jako metoda abstrakcyjna z interfejsu CommandListner metoda commandAction , która przyjmuje jako argument obiekt command klasy Command czyli zdrarzenie wyjdź/wyślij oraz obiekt menadżera ekranu , w ciele metody następuje porównanie == wartości obiektu , jeśli warunek jest spełniony metodzie zamykającej aplikację przekazywana jest wartośc true
jeśli zaś obiekt command jest równy sendCommand , następuje wywołanie metody handleSendCommand.
Najczęsciej do obsługi zdarzeń korzysta się z nastepującego wywołania zawierającego metodę getCommandType
(command.getCommandType() == Command.ITEM) i w wypadku naszego MIDletu (command,getCommandType() == Command.EXIT) , po spełnieniu którego nastepuje wywpłanie metod jak powyżej
--------------------------

private void handleSendCommand() {
try {
// Open the connection
connection = (MessageConnection)Connector.open("sms://:5000");
} catch (IOException ex) {
// TODO: Exception handling
}

TextMessage message = prepareSMS();
sendSMS(message);
}

Prywatna (mozliwa do użycia tylko w klasie w której została zdefiniowana) metoda handleSendCommand próbuje w ciele stworzyć połączenie do wysyłki smsa.
Odbywa się to przy wykorzystaniu metody statyczne open z klasy Connector , z argumentem (stringiem) "sms://5000" , obiekt zwrócony przez wywołanie tej metody rzutowany jest na klasę (MessageConnection) i przypisywany do zmiennej connection
Jeśli nie uda się stworzenie połaczenia wyłapywany jest błąd.
Po udanym utworzeniu połaczenia na rzecz zmiennej message klasy TextMessage wywoływana jest metoda prepareSMS()
a następnie metoda sendSMS która jako wartość przyjmuje , jak widzimy , obiekt message zwrócony z wywolania metody prepareSMS()


private TextMessage prepareSMS() {

TextMessage message = (TextMessage)connection.newMessage(
MessageConnection.TEXT_MESSAGE);


String number = "sms://" + smsNumber.getString();
message.setAddress(number);


String text = smsText.getString();
message.setPayloadText(text);

return message;
}

na rzecz oBiektu connection wywoływana jest metoda newMessage ze stałą TEXT_MESSAGE , nie znam dokładnego popisu tej metody i przyjmowanych w argumencie stałych , ale można wnosić na logike , że chodzi o utworzenie nowej wiadomości tekstowej. Wynik wywołania tej metody na rzecz obiektu connection (naszego połaczenia) rzutowany jest na klasę (TextMessage). Tak otrzymujemy obiekt który będzie zawierał naszą wiadomość / message klasy TextMessage
Z pola tekstowego smsNumber pobieramy metodą getString numer , z pola tekstowego smsText pobieramy metodą getString treść wiadomości.
Jak pisałem nie znam dokładnych opisów metod z pakietu javax.wireless.messaging , ale działania metod setAddres (number) oraz setPayload(text) na rzecz obiektu message można się domyśleć.

wiadomość jest zwracana , a program wraca do miejsca gdzie nastepuje wywołanie sendSMS(message);

-----------------------

private void sendSMS(final TextMessage message) {

Thread smsThread = new Thread() {
public void run() {
try {
connection.send(message);
mainForm.append("Message sent.");
} catch (InterruptedIOException ex) {
// TODO: Exception (e.g. timeout) handling
} catch (IOException ex) {
// TODO: Exception (e.g. network failure) handling
} catch (IllegalArgumentException ex) {
// TODO: Exception (e.g. too big or otherwise invalid
// message) handling
} catch (SecurityException ex) {
// TODO: Exception (e.g. insufficient permissions) handling
}
}
};
smsThread.start();
}
}

Prywatna metoda sendSMS przyjmuje jako argument obiekt message klasy TextMessage , jest to obiekt finalny , więc w zaden sposób nie można wpłynąć już na niego i w jakiś sposób go przypadkowo zmienić.
W metodzie tej tworzony jest egzemplarz klasy wątku smsThread klasy Thread i wywołaniu na jego rzecz metody start() , która spróbuje w zdefiniowanej abstrakcyjnej metodzie run pochodzącej z interfejsu Thread ,wysłać smsa metodą send(message) dzięki utworzonemu połaczeniu , które reprezentuje obiekt connection. Jeśli wysłanie uda się , na formancie zobaczymy komunikat "Message sent". Jeśli wysłanie z jakiegoś powodu się nie powiedzie , następuje hierarchiczna obsługa wyjątków , liznąłem tylko ten temat , więc pozostawiam go bez dokładniejszego opisu.
Oczywiście dzięki nowemu wątkowi , program wysyła smsa , a na formancie można już wpisywać nowy numer i nowy adres. Gdyby nowy wątek nie został utworzony program "zawiesiłby się"/przestał reagować do mometu uporania się , bądź nie z wysyłką smsa.

--------
issa
10%
10%
 
Posty: 49
Dołączył(a): 11 sierpnia 2006, o 20:13
    WindowsXPOpera

Poprzednia stronaNastępna strona

Powrót do Od czego zacząć?

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość

cron