穩定版原碼下載
用我寫的move_object.py 這模組,已可做出一些想要的動畫,目前我很滿意這模組,修正一些bug,不合程式邏輯(try全拿掉了),並增加一些爆炸畫面抖動效果,哈哈,寫這模組,是純好玩的,和專業的pygame比,當然差很多,不過我這,不用裝其他套件,就可在liux gnome桌面下執行
再來在說一下cairo,我完全弄懂cairo的運作原理了,當初開始寫這模組,清除畫面是用一個透明40x40像素,就算del掉,這surface是不會消失的,時間久,畫圖區充滿了透明40x40像素,queue_draw()就會更新一次,畫面會教lag,我試著用self.p_boom=self.p1=cairo.ImageSurface(cairo.FORMAT_ARGB32,0,0)#無像素png,清除畫面,改善很多,後來我再試著用self.cr=None也可以清除畫面,這更好讓memory也連帶淨空,終於是我要的效果了.
我認為cairo的原理真的很棒,程式稍用亂數改一下座標位置,就讓碰撞物或爆炸畫面產生抖動效果,如下
offset= random.randint(-self.move_offset,self.move_offset)
self.cr.set_source_surface(self.p1, self.x+offset, self.y+offset)
真的很棒,實際可看 一下move_object.py原碼,其實程式很短,大部分都在寫一些預設的移動,都只是在處理座標位置self.x,self.y,座標變,queue_draw()更新畫布,物體就會移動,很簡單的,新的畫面
read more...
2015年2月23日 星期一
2015年2月22日 星期日
pygtk cairo動畫(續)執行續,不同物件中信號傳遞
這是一個用move_object.py就完成的,一個不起眼的小遊戲,當然有興趣改一改,可做成其他遊戲,按這下載原碼
執行速度尚可,再來是想讓move_object.py這模組執行更順,才會具續下一步,寫這只是純好玩的,有興趣可拿來修改,參考都很歡迎
move_object.py,用選擇性參數,初始化物件,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這4參數可給,可不給,跟java多重建構子功能一樣
,最後_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這2參數採用不具方式,用來設定方法,讓使用者在主程式實做,前面是碰撞發送,後者是移動發送,若2者都不給,就是非碰撞物,不做信號實做
#建構式,用來初始化物件
def __init__(self,main_obj,frame,darea,image_path,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None):
來看這2參數實際運作,下面getattr(self.main_obj,self.RECEVER_MOVE)(self),呼叫主程式self.main_obj的不具名方法,把本身當參數(self)
主程式,產生move_object物件時把"SEND_move_bullet"當參數,因此_RECEVER_MOVE_就是SEND_move_bullet,此時move_object.py不具名方法就是SEND_move_bullet,就變成self.main_obj.SEND_move_bullet(self),所以主程式就必須實做SEND_move_bullet這個方法(如下面狀況)
主程式
...............................
move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")
...................
def SEND_move_bullet(self,move_object):
...........................
move_object.py程式
##############################碰撞時透過thread發送信號,把本身和碰撞物當參數,否則送出本身##
def SEND_MOVE_SIGNAL(self):
d="RECEVER"
if(self.check_yes):
if(self.is_check_move):#判斷是否要實作移動發送
#self.main_obj.RECEVER_MOVE(self)
getattr(self.main_obj,self.RECEVER_MOVE)(self)
###############和其他是否碰撞,若碰撞回傳True,否則False###################################
def check_collision(self,other_obj):
...................................
if(self.check_collision_p(xo,yo,xo1,yo1,xs,ys,xs1,ys1)):
if(self.is_collision_check):
#在這實作碰撞發送,若碰撞,送出本身和被撞物
getattr(self.main_obj,self.RECEVER_COLLISION)(self,other_obj)
.............................
本遊戲中機台,子彈,飛碟,是碰撞物,因此要實做碰撞或移動發送,也可2者皆做,這裡我才用機台,和子彈是作移動發送,飛碟是作碰撞發送,如下,只要使用move_object這模組,就可完成不同動畫了
#畫出機台
def draw_body(self):
if(len(self.move_list_body)<1 br=""> p="body.png"
w,h=self.get_frame_w_h()
#最後2個參數不給,給None代表不作碰撞接收,但作移動發送SEND_move_body,0,0是要產生的位置,也可用set_move_to_xy放到想要位置
self.move_body=move_object.move_object(self,self.framme1,self.darea,p,w/2-20,h-60,None,"SEND_move_body")
self.move_list_body.append(self.move_body)
#畫出子彈
def draw_bullet(self): #if key == gtk.keysyms.Right:self.generate()
if(len(self.move_list_bullet)<6 and="" len="" self.move_list_body="">0):
p="bullet.png"
#最後2個參數實作接收移動發送,收移動發送後碰撞檢查
w,h=self.move_body.get_width_height()[0]/2,self.move_body.get_width_height()[1]
x,y=self.move_body.get_xy()[0]+w,self.move_body.get_xy()[1]-h
move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")
move_bullet.set_move_type("直線向上")
move_bullet.set_move_speed(0.005)
move_bullet.set_explosion_png("boom2.png")
self.move_list_bullet.append(move_bullet)
#加到列表list
#畫出隨機飛碟
def generate(self):
p="logo"+str(random.randint(1,5))+".png"
#最後2個參數實作接收移動發送後碰撞檢查RECEVER_collision和None不作移動發送,代表check碰撞,不給座標None,None,位置會隨機產生
move_fly=move_object.move_object(self,self.framme1,self.darea,p,None,None,"RECEVER_collision_fly",None)
speed=float(random.randint(1,100))/100
move_fly.set_move_speed(speed)
if(random.randint(1,100) >50 ):
move_fly.set_move_type("亂數")
else:
move_fly.set_move_type("直線X")
#加到列表list
self.move_list_fly.append(move_fly)
然後下面實做SEND_move_body,SEND_move_body移動發送,RECEVER_collision_fly碰撞接收,機台單純發送移動,送給move_list_signal做逐一送給飛碟做碰撞檢查,子彈打到最上方就從list移走並爆炸,否則送給move_list_signal做逐一送給飛碟做碰撞檢查,當飛碟檢查到碰撞發生時,RECEVER_collision_fly會收到信號,做碰撞後的後續處理,讓它爆炸,從list移走,增加分數,等等後續處理
##########################################移動發送,碰撞接收實作######################################################
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def SEND_move_body(self,move_object):
#接到移動物,送過來信號,送給move_list_signal逐一檢查碰撞
self.move_list_signal.check_collision(move_object,self.move_list_fly)
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def SEND_move_bullet(self,move_object):
#print(move_object.get_xy()[1])
#接到移動物,送過來信號,超過視窗上方就移走bullet,否則,送給move_list_signal逐一檢查碰撞
if(move_object.get_xy()[1]<0-move_object .get_xy="" br=""> #True打到最上面會爆炸,設False到最上面不會爆炸
if(move_object in self.move_list_bullet):self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
else:
self.move_list_signal.check_collision(move_object,self.move_list_fly)
#接收移動物和碰撞物,碰撞時會收到信號,參數為移動物和碰撞物送給move_list_signal移走移動物,和碰撞物
#飛碟是作碰撞,第一個參數傳本身,第2個參數傳實作移動,發送的是機台或子彈
def RECEVER_collision_fly(self,c_object,move_object):
#print(c_object.get_name())
#更改了爆炸圖片,大隻飛碟爆炸不同
if(c_object.get_name()=="logo4.png"):c_object.set_explosion_png("boom1.png")
#self.move_body=None
#從list中移走移動物,和碰撞物,True代表產生爆炸畫面,若不要爆炸畫面設False,注意是那個list移走,否則不會爆炸
self.move_list_signal.kill_move_obj(c_object,True,self.move_list_fly)
if(move_object in self.move_list_body):
self.move_list_signal.kill_move_obj(move_object,True,self.move_list_body)
self.GAME_OVER()
self.score=0
if(move_object in self.move_list_bullet):
#設子彈爆炸不一樣,畫面較逼真
#move_object.set_explosion_png("boom2.png")
self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
self.score=self.score+1
self.show_score()
if(self.score>self.score_high):self.score_high=self.score#不要在執行續中呼叫 0-move_object>6>1>
read more...
執行速度尚可,再來是想讓move_object.py這模組執行更順,才會具續下一步,寫這只是純好玩的,有興趣可拿來修改,參考都很歡迎
move_object.py,用選擇性參數,初始化物件,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這4參數可給,可不給,跟java多重建構子功能一樣
,最後_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這2參數採用不具方式,用來設定方法,讓使用者在主程式實做,前面是碰撞發送,後者是移動發送,若2者都不給,就是非碰撞物,不做信號實做
#建構式,用來初始化物件
def __init__(self,main_obj,frame,darea,image_path,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None):
來看這2參數實際運作,下面getattr(self.main_obj,self.RECEVER_MOVE)(self),呼叫主程式self.main_obj的不具名方法,把本身當參數(self)
主程式,產生move_object物件時把"SEND_move_bullet"當參數,因此_RECEVER_MOVE_就是SEND_move_bullet,此時move_object.py不具名方法就是SEND_move_bullet,就變成self.main_obj.SEND_move_bullet(self),所以主程式就必須實做SEND_move_bullet這個方法(如下面狀況)
主程式
...............................
move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")
...................
def SEND_move_bullet(self,move_object):
...........................
move_object.py程式
##############################碰撞時透過thread發送信號,把本身和碰撞物當參數,否則送出本身##
def SEND_MOVE_SIGNAL(self):
d="RECEVER"
if(self.check_yes):
if(self.is_check_move):#判斷是否要實作移動發送
#self.main_obj.RECEVER_MOVE(self)
getattr(self.main_obj,self.RECEVER_MOVE)(self)
###############和其他是否碰撞,若碰撞回傳True,否則False###################################
def check_collision(self,other_obj):
...................................
if(self.check_collision_p(xo,yo,xo1,yo1,xs,ys,xs1,ys1)):
if(self.is_collision_check):
#在這實作碰撞發送,若碰撞,送出本身和被撞物
getattr(self.main_obj,self.RECEVER_COLLISION)(self,other_obj)
.............................
本遊戲中機台,子彈,飛碟,是碰撞物,因此要實做碰撞或移動發送,也可2者皆做,這裡我才用機台,和子彈是作移動發送,飛碟是作碰撞發送,如下,只要使用move_object這模組,就可完成不同動畫了
#畫出機台
def draw_body(self):
if(len(self.move_list_body)<1 br=""> p="body.png"
w,h=self.get_frame_w_h()
#最後2個參數不給,給None代表不作碰撞接收,但作移動發送SEND_move_body,0,0是要產生的位置,也可用set_move_to_xy放到想要位置
self.move_body=move_object.move_object(self,self.framme1,self.darea,p,w/2-20,h-60,None,"SEND_move_body")
self.move_list_body.append(self.move_body)
#畫出子彈
def draw_bullet(self): #if key == gtk.keysyms.Right:self.generate()
if(len(self.move_list_bullet)<6 and="" len="" self.move_list_body="">0):
p="bullet.png"
#最後2個參數實作接收移動發送,收移動發送後碰撞檢查
w,h=self.move_body.get_width_height()[0]/2,self.move_body.get_width_height()[1]
x,y=self.move_body.get_xy()[0]+w,self.move_body.get_xy()[1]-h
move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")
move_bullet.set_move_type("直線向上")
move_bullet.set_move_speed(0.005)
move_bullet.set_explosion_png("boom2.png")
self.move_list_bullet.append(move_bullet)
#加到列表list
#畫出隨機飛碟
def generate(self):
p="logo"+str(random.randint(1,5))+".png"
#最後2個參數實作接收移動發送後碰撞檢查RECEVER_collision和None不作移動發送,代表check碰撞,不給座標None,None,位置會隨機產生
move_fly=move_object.move_object(self,self.framme1,self.darea,p,None,None,"RECEVER_collision_fly",None)
speed=float(random.randint(1,100))/100
move_fly.set_move_speed(speed)
if(random.randint(1,100) >50 ):
move_fly.set_move_type("亂數")
else:
move_fly.set_move_type("直線X")
#加到列表list
self.move_list_fly.append(move_fly)
然後下面實做SEND_move_body,SEND_move_body移動發送,RECEVER_collision_fly碰撞接收,機台單純發送移動,送給move_list_signal做逐一送給飛碟做碰撞檢查,子彈打到最上方就從list移走並爆炸,否則送給move_list_signal做逐一送給飛碟做碰撞檢查,當飛碟檢查到碰撞發生時,RECEVER_collision_fly會收到信號,做碰撞後的後續處理,讓它爆炸,從list移走,增加分數,等等後續處理
##########################################移動發送,碰撞接收實作######################################################
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def SEND_move_body(self,move_object):
#接到移動物,送過來信號,送給move_list_signal逐一檢查碰撞
self.move_list_signal.check_collision(move_object,self.move_list_fly)
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def SEND_move_bullet(self,move_object):
#print(move_object.get_xy()[1])
#接到移動物,送過來信號,超過視窗上方就移走bullet,否則,送給move_list_signal逐一檢查碰撞
if(move_object.get_xy()[1]<0-move_object .get_xy="" br=""> #True打到最上面會爆炸,設False到最上面不會爆炸
if(move_object in self.move_list_bullet):self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
else:
self.move_list_signal.check_collision(move_object,self.move_list_fly)
#接收移動物和碰撞物,碰撞時會收到信號,參數為移動物和碰撞物送給move_list_signal移走移動物,和碰撞物
#飛碟是作碰撞,第一個參數傳本身,第2個參數傳實作移動,發送的是機台或子彈
def RECEVER_collision_fly(self,c_object,move_object):
#print(c_object.get_name())
#更改了爆炸圖片,大隻飛碟爆炸不同
if(c_object.get_name()=="logo4.png"):c_object.set_explosion_png("boom1.png")
#self.move_body=None
#從list中移走移動物,和碰撞物,True代表產生爆炸畫面,若不要爆炸畫面設False,注意是那個list移走,否則不會爆炸
self.move_list_signal.kill_move_obj(c_object,True,self.move_list_fly)
if(move_object in self.move_list_body):
self.move_list_signal.kill_move_obj(move_object,True,self.move_list_body)
self.GAME_OVER()
self.score=0
if(move_object in self.move_list_bullet):
#設子彈爆炸不一樣,畫面較逼真
#move_object.set_explosion_png("boom2.png")
self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
self.score=self.score+1
self.show_score()
if(self.score>self.score_high):self.score_high=self.score#不要在執行續中呼叫 0-move_object>6>1>
read more...
2015年2月19日 星期四
pygtk Cairo動畫(續)碰撞信號處理實做
程式原碼下載
我寫的move_object.py這模組,算蠻強大的,後續會應用這模組,製造更多動畫,主程式下面以move_object.py我製造一張會抖動的太空背景,因ubuntu1410,我先關掉抖動,後續在改,若是debian可把
#self.move_obj_b.set_move_speed(.5)
#self.move_obj_b.set_move_type("背景")
打開,就會有抖動效果,按方向建右鍵增加移動飛碟,若飛碟相撞會產生爆炸,並從視窗消失,按方向建左鍵移走飛碟
#畫出背景
def draw_background(self):
p="background.png"
#ubuntu1410 bug座標不能0,0
self.move_obj_b=move_object.move_object(self,self.framme1,self.darea,p,1,1)
#self.move_obj_b.set_move_to_xy(0,0) ubuntu1410 don't work跑到0,0會X error
#若不要背景移動,下面不要設定
#self.move_obj_b.set_move_speed(.5)
#self.move_obj_b.set_move_type("背景")
#畫出隨機飛碟
def generate(self):
p="logo"+str(random.randint(1,3))+".png"
move_obj=move_object.move_object(self,self.framme1,self.darea,p)
speed=float(random.randint(1,100))/100
move_obj.set_move_speed(speed)
if(random.randint(1,100) >50 ):
move_obj.set_move_type("亂數")
else:
move_obj.set_move_type("直線X")
#加到列表list
self.move_list_signal.move_list_append(move_obj)
再來重要的動畫碰撞信號實做,來看看如何實做,到目前程式很少就做出了很複雜動作,其實在於邏輯是否夠好,可行,程式就會簡潔有力,在move_object.py修改了SEND_MOVE_SIGNAL方法,碰撞時呼叫self.main_obj.RECEVER否則呼叫self.main_obj.RECEVER_MOVE
#碰撞時透過thread發送信號,把本身和碰撞物當參數,否則送出本身
def SEND_MOVE_SIGNAL(self):
if(self.is_check_collision):
self.main_obj.RECEVER(self,self.c_obj)
else:
self.main_obj.RECEVER_MOVE(self)
在move_object.py增加了碰撞方法,碰撞產生時self.is_check_collision=True,此時SEND_MOVE_SIGNAL改成呼叫self.main_obj.RECEVER,一開始self.is_check_collision=False
def check_collision(self,other_obj):
xo,yo=other_obj.get_xy()
xo_w,yo_h=other_obj.get_width_height()
xo1=xo+xo_w
yo1=yo+yo_h
#本身座標和寬高
xs,ys=self.get_xy()
xs_w,ys_h=self.get_width_height()
xs1=xs+xs_w
ys1=ys+ys_h
#print(xo,yo,xo1,yo1,xs,ys,xs1,ys1)
if(self.is_collision(xo,yo,xo1,yo1,xs,ys,xs1,ys1)):
self.is_check_collision=True
self.c_obj=other_obj
self.set_move_type=None#碰撞後不要在移動了
在來看主程式,如何接收信號,非碰撞時接收RECEVER_MOVE,然後將移動物參數送給move_list_signal(類似界面),move_list_signal這個類,會將移動物送給各個移動物,做碰撞判斷,若主程式收到碰撞信號RECEVER,會透過move_list_signal這個類,會將移動物和被碰撞物刪除,並產生爆炸畫面,簡單邏輯,就能造成強大效果,做出複雜的動作,很神奇吧!
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def RECEVER_MOVE(self,move_object):
#檢查碰撞,若不要檢查,忽略
self.move_list_signal.check_collision(move_object)
#接收移動動畫信號,移動物,和碰撞物碰撞時會收到信號,參數為移動物和碰撞物
def RECEVER(self,move_object,c_object):
#print(move_object.get_name())
#從list中移走移動物,和碰撞物,True代表產生爆炸畫面,若不要爆炸畫面設False
self.move_list_signal.kill_move_obj(move_object,True)
self.move_list_signal.kill_move_obj(c_object,True)
其餘看程式註解,下面是執行畫面
read more...
我寫的move_object.py這模組,算蠻強大的,後續會應用這模組,製造更多動畫,主程式下面以move_object.py我製造一張會抖動的太空背景,因ubuntu1410,我先關掉抖動,後續在改,若是debian可把
#self.move_obj_b.set_move_speed(.5)
#self.move_obj_b.set_move_type("背景")
打開,就會有抖動效果,按方向建右鍵增加移動飛碟,若飛碟相撞會產生爆炸,並從視窗消失,按方向建左鍵移走飛碟
#畫出背景
def draw_background(self):
p="background.png"
#ubuntu1410 bug座標不能0,0
self.move_obj_b=move_object.move_object(self,self.framme1,self.darea,p,1,1)
#self.move_obj_b.set_move_to_xy(0,0) ubuntu1410 don't work跑到0,0會X error
#若不要背景移動,下面不要設定
#self.move_obj_b.set_move_speed(.5)
#self.move_obj_b.set_move_type("背景")
#畫出隨機飛碟
def generate(self):
p="logo"+str(random.randint(1,3))+".png"
move_obj=move_object.move_object(self,self.framme1,self.darea,p)
speed=float(random.randint(1,100))/100
move_obj.set_move_speed(speed)
if(random.randint(1,100) >50 ):
move_obj.set_move_type("亂數")
else:
move_obj.set_move_type("直線X")
#加到列表list
self.move_list_signal.move_list_append(move_obj)
再來重要的動畫碰撞信號實做,來看看如何實做,到目前程式很少就做出了很複雜動作,其實在於邏輯是否夠好,可行,程式就會簡潔有力,在move_object.py修改了SEND_MOVE_SIGNAL方法,碰撞時呼叫self.main_obj.RECEVER否則呼叫self.main_obj.RECEVER_MOVE
#碰撞時透過thread發送信號,把本身和碰撞物當參數,否則送出本身
def SEND_MOVE_SIGNAL(self):
if(self.is_check_collision):
self.main_obj.RECEVER(self,self.c_obj)
else:
self.main_obj.RECEVER_MOVE(self)
在move_object.py增加了碰撞方法,碰撞產生時self.is_check_collision=True,此時SEND_MOVE_SIGNAL改成呼叫self.main_obj.RECEVER,一開始self.is_check_collision=False
def check_collision(self,other_obj):
xo,yo=other_obj.get_xy()
xo_w,yo_h=other_obj.get_width_height()
xo1=xo+xo_w
yo1=yo+yo_h
#本身座標和寬高
xs,ys=self.get_xy()
xs_w,ys_h=self.get_width_height()
xs1=xs+xs_w
ys1=ys+ys_h
#print(xo,yo,xo1,yo1,xs,ys,xs1,ys1)
if(self.is_collision(xo,yo,xo1,yo1,xs,ys,xs1,ys1)):
self.is_check_collision=True
self.c_obj=other_obj
self.set_move_type=None#碰撞後不要在移動了
在來看主程式,如何接收信號,非碰撞時接收RECEVER_MOVE,然後將移動物參數送給move_list_signal(類似界面),move_list_signal這個類,會將移動物送給各個移動物,做碰撞判斷,若主程式收到碰撞信號RECEVER,會透過move_list_signal這個類,會將移動物和被碰撞物刪除,並產生爆炸畫面,簡單邏輯,就能造成強大效果,做出複雜的動作,很神奇吧!
#接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
def RECEVER_MOVE(self,move_object):
#檢查碰撞,若不要檢查,忽略
self.move_list_signal.check_collision(move_object)
#接收移動動畫信號,移動物,和碰撞物碰撞時會收到信號,參數為移動物和碰撞物
def RECEVER(self,move_object,c_object):
#print(move_object.get_name())
#從list中移走移動物,和碰撞物,True代表產生爆炸畫面,若不要爆炸畫面設False
self.move_list_signal.kill_move_obj(move_object,True)
self.move_list_signal.kill_move_obj(c_object,True)
其餘看程式註解,下面是執行畫面
read more...
2015年2月18日 星期三
pygtk cairo動畫(續) BUG修正(debian 7.7 memory增加的問題),增加鍵盤事件
程式原碼下載
修正在debian7.7下,memory一直增加問題,以及所有OS,執行會漰潰的問題.
memory增加是deb7.7 pygtk3.0的問題,改用gtk2.0正常
執行會漰潰的問題是gtk button元件的問題(使用者一直按button可能crash),改用鍵盤正常
避開BUG,就可好好來使用pygtk cairo製作想要的動畫
鍵盤事件,如下,把key-press-event事件跟 self.window連結,指定處理方法on_key_down
這裡實做是放到move_list_singal模組中,當使用者按下方向鍵右鍵,增加一隻移動物,每支
移動物都有自己特徵,按下方向鍵左鍵,刪除一隻移動物,移動物速度都不一樣,移動方式目前有2種,亂移,跟水平亂移,要怎移動,只是在加上去
main.py
...................................................................................................................
self.window.connect("key-press-event", self.on_key_down)
....................................................................................................................
#處理鍵盤,由move_list_signal物件來實作,呼叫self.move_list_signal.on_key_down(event)
def on_key_down(self, widget, event):
key = event.keyval
self.move_list_signal.on_key_down(event)
#if key == gtk.keysyms.Right:self.generate()
move_list_signal.py
.................................
#鍵盤事件,若想不同動作,可繼承複寫
def on_key_down(self, event):
key = event.keyval
if key == gtk.keysyms.Right:
self.main.generate()
if key == gtk.keysyms.Left:
self.kill_move_first()
要增加移動方式 ,self.move_type是設定type給begin_move方法來判斷,程式碼,都有詳細註解
#移動方式
def set_move_type(self, mtype):
self.move_type=mtype
def begin_move(self,):#不給type為靜止
if(self.move_type=="亂數"):self.set_move_random()
if(self.move_type=="直線X"):self.set_move_line_x_radom()
執行畫面
read more...
修正在debian7.7下,memory一直增加問題,以及所有OS,執行會漰潰的問題.
memory增加是deb7.7 pygtk3.0的問題,改用gtk2.0正常
執行會漰潰的問題是gtk button元件的問題(使用者一直按button可能crash),改用鍵盤正常
避開BUG,就可好好來使用pygtk cairo製作想要的動畫
鍵盤事件,如下,把key-press-event事件跟 self.window連結,指定處理方法on_key_down
這裡實做是放到move_list_singal模組中,當使用者按下方向鍵右鍵,增加一隻移動物,每支
移動物都有自己特徵,按下方向鍵左鍵,刪除一隻移動物,移動物速度都不一樣,移動方式目前有2種,亂移,跟水平亂移,要怎移動,只是在加上去
main.py
...................................................................................................................
self.window.connect("key-press-event", self.on_key_down)
....................................................................................................................
#處理鍵盤,由move_list_signal物件來實作,呼叫self.move_list_signal.on_key_down(event)
def on_key_down(self, widget, event):
key = event.keyval
self.move_list_signal.on_key_down(event)
#if key == gtk.keysyms.Right:self.generate()
move_list_signal.py
.................................
#鍵盤事件,若想不同動作,可繼承複寫
def on_key_down(self, event):
key = event.keyval
if key == gtk.keysyms.Right:
self.main.generate()
if key == gtk.keysyms.Left:
self.kill_move_first()
要增加移動方式 ,self.move_type是設定type給begin_move方法來判斷,程式碼,都有詳細註解
#移動方式
def set_move_type(self, mtype):
self.move_type=mtype
def begin_move(self,):#不給type為靜止
if(self.move_type=="亂數"):self.set_move_random()
if(self.move_type=="直線X"):self.set_move_line_x_radom()
執行畫面
read more...
2015年2月15日 星期日
pygtk cairo 如何讓每一個動畫都有自己行為,以及如和建立每一個動畫信號
move_object.py以做修正,它不應該含有gtk ui部份,我希望它可以在畫圖區可以一直產生,若含有ui這樣是不對的,當然這邏輯很棒,每一隻都是一個執行續,擁有自己的生命行為,
我到可讓隻飛碟行徑路線,生命都不一樣,一般人可能只會想到用一個thread讓每隻動起來,這樣邏輯不好,而且程式複雜化了.
目前,每按一次按鈕,就會在frame隨機位置,隨機產生3種飛碟中之一種,每隻飛碟速度都不同,按停止扭,會一隻一隻的清空,我是每隻一一,用空白圖來清空
move_list_signal.py用來存放,每隻飛碟的list,到時每隻飛碟信號應該會這模組建立,有點像界面,做溝通用的,
說真的,這樣的邏輯思考,已經算滿神奇的,在來看一下,更神奇的信號處理,我如何讓飛碟飛碟一直增加,又能每隻飛碟能讓信號傳回主程式
下面START方法,按產生飛碟,就會建立一個move_object物件(就是一台亂跑的飛碟),用self把本身整個傳給每一隻建立的move_object物件,那move_object接收
這參數,就可使用RECEVER發法,又把自己self回傳給主程式,主程式可接收move_object所有東西
#接收移動動畫信號,print印出每隻檔案名(測試用沒什意義,到時還要完成)
def RECEVER(self,move_object):
print(move_object.get_name())
def START(self, widget, *event):
if bt_active_label=='產生飛碟':
...............................................................
move_obj=move_object.move_object(self,self.framme1,self.darea,p)
...............................................................
在來看move_object如何送信號過來,self.main_obj就是接收了主程式self,SEND_MOVE_SIGNAL方法呼叫了主程式中的RECEVER,然後move_object自帶的thread
會一直呼叫self.move_object.SEND_MOVE_SIGNAL(),終端機就看到每隻飛碟的3種飛碟檔名一直被印出來了,很神奇吧!!這樣就可用來做碰撞判斷用,其實我還試著想有沒有什方法
直接就可把飛碟信號傳給每隻飛碟,這樣的或應該就是超神的了,只想到透過類似界面,這界面會存放所有飛碟,主程式接受到每隻飛碟傳過來信號,逐一用for來傳這,
就是我在建立move_list_signal.py的原因,執行畫畫面就像下圖一樣,然後這是目前的程式源碼下載,有需要可拿去參考,只是無聊愛亂玩程式,哈哈哈
class move_object():
#建構式,用來初始化物件
def __init__(self,main_obj,frame,darea,image_path):
self.main_obj=main_obj
..........................................................
#初始化thread,把自己當參數,傳給thread,用來製照動畫,並啟動它
self.thread = MyThread(self) ...........................................
def SEND_MOVE_SIGNAL(self):
self.main_obj.RECEVER(self)
class MyThread(Thread):
def __init__(self,move_obj):
super(MyThread,self).__init__()
self.move_object=move_obj
..........................
def run(self):#執行續,執行的地方
print("執行續啟動")
while self.is_move:
......................................
self.move_object.SEND_MOVE_SIGNAL()
.....................................
read more...
我到可讓隻飛碟行徑路線,生命都不一樣,一般人可能只會想到用一個thread讓每隻動起來,這樣邏輯不好,而且程式複雜化了.
目前,每按一次按鈕,就會在frame隨機位置,隨機產生3種飛碟中之一種,每隻飛碟速度都不同,按停止扭,會一隻一隻的清空,我是每隻一一,用空白圖來清空
move_list_signal.py用來存放,每隻飛碟的list,到時每隻飛碟信號應該會這模組建立,有點像界面,做溝通用的,
說真的,這樣的邏輯思考,已經算滿神奇的,在來看一下,更神奇的信號處理,我如何讓飛碟飛碟一直增加,又能每隻飛碟能讓信號傳回主程式
下面START方法,按產生飛碟,就會建立一個move_object物件(就是一台亂跑的飛碟),用self把本身整個傳給每一隻建立的move_object物件,那move_object接收
這參數,就可使用RECEVER發法,又把自己self回傳給主程式,主程式可接收move_object所有東西
#接收移動動畫信號,print印出每隻檔案名(測試用沒什意義,到時還要完成)
def RECEVER(self,move_object):
print(move_object.get_name())
def START(self, widget, *event):
if bt_active_label=='產生飛碟':
...............................................................
move_obj=move_object.move_object(self,self.framme1,self.darea,p)
...............................................................
在來看move_object如何送信號過來,self.main_obj就是接收了主程式self,SEND_MOVE_SIGNAL方法呼叫了主程式中的RECEVER,然後move_object自帶的thread
會一直呼叫self.move_object.SEND_MOVE_SIGNAL(),終端機就看到每隻飛碟的3種飛碟檔名一直被印出來了,很神奇吧!!這樣就可用來做碰撞判斷用,其實我還試著想有沒有什方法
直接就可把飛碟信號傳給每隻飛碟,這樣的或應該就是超神的了,只想到透過類似界面,這界面會存放所有飛碟,主程式接受到每隻飛碟傳過來信號,逐一用for來傳這,
就是我在建立move_list_signal.py的原因,執行畫畫面就像下圖一樣,然後這是目前的程式源碼下載,有需要可拿去參考,只是無聊愛亂玩程式,哈哈哈
class move_object():
#建構式,用來初始化物件
def __init__(self,main_obj,frame,darea,image_path):
self.main_obj=main_obj
..........................................................
#初始化thread,把自己當參數,傳給thread,用來製照動畫,並啟動它
self.thread = MyThread(self) ...........................................
def SEND_MOVE_SIGNAL(self):
self.main_obj.RECEVER(self)
class MyThread(Thread):
def __init__(self,move_obj):
super(MyThread,self).__init__()
self.move_object=move_obj
..........................
def run(self):#執行續,執行的地方
print("執行續啟動")
while self.is_move:
......................................
self.move_object.SEND_MOVE_SIGNAL()
.....................................
read more...
2015年2月13日 星期五
pygtk3.0 cairo動畫
又更進一步了,製造動畫,會選cairo,是想自己寫,當然其他有更複雜好用的module譬如pygame,pygame我不懂,cairo也是剛開始學,看了網路上的例子,終於稿懂了,下面是一個會在視窗隨機移動的圖片,因為只完成一點點,可能會跑出視窗外,重點是cairo讓圖片動起來,當然一定要用執行續的方式,這應該都知道.
現在來說原理,
self.darea = Gtk.DrawingArea()
只是制造一個畫圖區
self.p1 = cairo.ImageSurface.create_from_png("src/logo.png")
制造一個image cairo圖層
關鍵
1.
self.darea.connect("draw", self.expose)
指畫畫這件事會被觸發 self.expose,pygtk3.0已經改成"draw"
2.
畫出圖的方式
def expose(self, widget, event):
#創造cairo畫布區域
self.cr = widget.get_property("window").cairo_create()
#圖層來源
self.cr.set_source_surface(self.p1, self.x, self.y)
#畫出
self.cr.paint()
3.執行續是只要做
self.darea.queue_draw()動作就可以,畫畫這件事就畫觸發self.expose,畫面就會update到最新狀態,一開始就是不懂這原理,一直用執行續跑expose(),結果圖片是一直加上去,在網路上看很多例子,就想通了
來看下面的例子
# move_object.py
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# Copyright (C) 2015 -
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see.
#預計目的,給個window參數,圖片參數,產生一個動畫,具有各種移動方式,速度,給個碰撞機制,爆炸畫面,生命結束
import os, sys
import time, cairo,random
from threading import Timer,Thread,Event
from gi.repository import GObject
from gi.repository import Gtk, Gdk
class move_object(Gtk.DrawingArea):
#建構式,用來初始化物件
def __init__(self,window):
self.window=window
self.darea = Gtk.DrawingArea()
#製照image cairo圖層
self.p1 = cairo.ImageSurface.create_from_png("src/logo.png")
#self.darea.set_size_request(250, 150)
#self.cr = self.window.get_property("window").cairo_create()
#self.cr = cairo.Context(self.p1)
#畫布事件expose方法
self.darea.connect("draw", self.expose)
self.window.add(self.darea)
#self.window.queue_draw_area(0,0,300,300)
self.move_type=""#動畫移動方式
self.speed=0.1#動畫速度預設更新為0.1second
#初始位置
self.x=random.randint(0,self.window.get_allocation().width)
self.y=random.randint(0,self.window.get_allocation().height)
#self.x=0
#self.y=0
#初始化thread,把自己當參數,傳給thread,用來製照動畫,並啟動它
self.thread = MyThread(self )
self.thread.start()
#畫出圖
def expose(self, widget, event):
#創造cairo畫布區域
self.cr = widget.get_property("window").cairo_create()
#圖層來源
self.cr.set_source_surface(self.p1, self.x, self.y)
#畫出
self.cr.paint()
#更新畫布,已經有畫布,執行續只要queue_draw()既可,會觸發expose,不是用執行續去執行expose
def re_draw(self):
self.darea.queue_draw()
#更新速度
def set_move_speed(self,speed):
self.speed=speed
#取得速度
def get_move_speed(self):
return self.speed
#移動位置,更新圖片位置
def set_move_to_xy(self, x, y):
self.x=x
self.y=y
def get_xy(self, x, y):
return self.x,self.y
#移動方式
def set_move_type(self, mtype):
self.move_type=mtype
def set_move_random(self):
self.x = self.x+random.randint(-1, 1)*5
self.y = self.y+random.randint(-1, 1)*5
def kill_move(self):
self.thread.stop()
#此行一定要加,否則執行續,會停住
GObject.threads_init()
#執行續,不能restart,只能重新產生,並等run執行完,會自動KILL
class MyThread(Thread,Gtk.DrawingArea):
def __init__(self,move_obj):
super(MyThread,self).__init__()
self.move_object=move_obj
self.stopped = Event()
self.is_move=True
def run(self):#執行續,執行的地方
print("執行續啟動")
while self.is_move:
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
#self.move_object.set_move_to_xy(x*2,x*2)
#set_move_random()變更圖片位置
self.move_object.set_move_random()
#更新畫布
self.move_object.re_draw()
time.sleep(self.move_object.get_move_speed())
print("執行續結束")
#except:pass
#讓執行續,快速結束
def stop(self):
self.stopped.set()
self.is_move=False
read more...
現在來說原理,
self.darea = Gtk.DrawingArea()
只是制造一個畫圖區
self.p1 = cairo.ImageSurface.create_from_png("src/logo.png")
制造一個image cairo圖層
關鍵
1.
self.darea.connect("draw", self.expose)
指畫畫這件事會被觸發 self.expose,pygtk3.0已經改成"draw"
2.
畫出圖的方式
def expose(self, widget, event):
#創造cairo畫布區域
self.cr = widget.get_property("window").cairo_create()
#圖層來源
self.cr.set_source_surface(self.p1, self.x, self.y)
#畫出
self.cr.paint()
3.執行續是只要做
self.darea.queue_draw()動作就可以,畫畫這件事就畫觸發self.expose,畫面就會update到最新狀態,一開始就是不懂這原理,一直用執行續跑expose(),結果圖片是一直加上去,在網路上看很多例子,就想通了
來看下面的例子
# move_object.py
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# Copyright (C) 2015 -
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
#預計目的,給個window參數,圖片參數,產生一個動畫,具有各種移動方式,速度,給個碰撞機制,爆炸畫面,生命結束
import os, sys
import time, cairo,random
from threading import Timer,Thread,Event
from gi.repository import GObject
from gi.repository import Gtk, Gdk
class move_object(Gtk.DrawingArea):
#建構式,用來初始化物件
def __init__(self,window):
self.window=window
self.darea = Gtk.DrawingArea()
#製照image cairo圖層
self.p1 = cairo.ImageSurface.create_from_png("src/logo.png")
#self.darea.set_size_request(250, 150)
#self.cr = self.window.get_property("window").cairo_create()
#self.cr = cairo.Context(self.p1)
#畫布事件expose方法
self.darea.connect("draw", self.expose)
self.window.add(self.darea)
#self.window.queue_draw_area(0,0,300,300)
self.move_type=""#動畫移動方式
self.speed=0.1#動畫速度預設更新為0.1second
#初始位置
self.x=random.randint(0,self.window.get_allocation().width)
self.y=random.randint(0,self.window.get_allocation().height)
#self.x=0
#self.y=0
#初始化thread,把自己當參數,傳給thread,用來製照動畫,並啟動它
self.thread = MyThread(self )
self.thread.start()
#畫出圖
def expose(self, widget, event):
#創造cairo畫布區域
self.cr = widget.get_property("window").cairo_create()
#圖層來源
self.cr.set_source_surface(self.p1, self.x, self.y)
#畫出
self.cr.paint()
#更新畫布,已經有畫布,執行續只要queue_draw()既可,會觸發expose,不是用執行續去執行expose
def re_draw(self):
self.darea.queue_draw()
#更新速度
def set_move_speed(self,speed):
self.speed=speed
#取得速度
def get_move_speed(self):
return self.speed
#移動位置,更新圖片位置
def set_move_to_xy(self, x, y):
self.x=x
self.y=y
def get_xy(self, x, y):
return self.x,self.y
#移動方式
def set_move_type(self, mtype):
self.move_type=mtype
def set_move_random(self):
self.x = self.x+random.randint(-1, 1)*5
self.y = self.y+random.randint(-1, 1)*5
def kill_move(self):
self.thread.stop()
#此行一定要加,否則執行續,會停住
GObject.threads_init()
#執行續,不能restart,只能重新產生,並等run執行完,會自動KILL
class MyThread(Thread,Gtk.DrawingArea):
def __init__(self,move_obj):
super(MyThread,self).__init__()
self.move_object=move_obj
self.stopped = Event()
self.is_move=True
def run(self):#執行續,執行的地方
print("執行續啟動")
while self.is_move:
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
#self.move_object.set_move_to_xy(x*2,x*2)
#set_move_random()變更圖片位置
self.move_object.set_move_random()
#更新畫布
self.move_object.re_draw()
time.sleep(self.move_object.get_move_speed())
print("執行續結束")
#except:pass
#讓執行續,快速結束
def stop(self):
self.stopped.set()
self.is_move=False
read more...
2015年2月8日 星期日
PYTHON的繼承
圖片播放器原碼下載
新增了一個播放效果
執行樣本:
試了使用Python的繼承方式,實際操作一次,大概就了解如何運作Python的繼承,這裡我沒用到覆寫,所謂覆寫,就是子類別,重寫父類別Method,就是def名稱一樣
我又新增了tree_show模組(tree_show.py),繼承了treeview_filechooser模組,首先treeview_filechooser必須是一個object,而非class,如下的A
A.t_filechosser是一個object,繼承了object
class t_filechosser(object):
B.t_filechosser是一個class
class t_filechosser():
為甚物件導向要使用繼承,就是要程式碼簡單,重複使用,不需要重寫程式碼,看一下tree_show是如何繼承t_filechosser,小括號內就是被繼承對象
tree_show建構式比t_filechosser多了image,view初始化參數,是處理圖片要用到的,用super呼叫了父類別建構式,以便能夠初始化父類別,
在tree_show只出始化self.image_viewport_new,self.image,self.pixbuf(如下面程式碼),其他都是在父類別初始化的
邏輯和構想,目的我希望t_filechosser專注在樹狀表單(檔案選擇器),到時要寫其他就不用改甚,可用在其他如播放MP3的表單等
,讓tree_show則專注在處理圖片方面,讓程式簡單易讀,程式碼重複使用率提高
class tree_show(treeview_filechooser.t_filechosser):
def __init__(self,add_widget,window,_type_,ifile,image,view):
#呼叫了父類別建構式
super(tree_show,self).__init__(add_widget,window,_type_,ifile)
self.tt.connect('cursor-changed', self.SHOW_ITEM_SIGNAL)
#self.tt.connect('cursor-changed', self.SHOW_ITEM_MOVE)
self.image_viewport_new=view
self.image=image
self.pixbuf = Pixbuf.new_from_file(self.file)
在tree_show中的4個方法,實做了處理圖片方法(須透過配合size_image類別)
def SHOW_ITEM_MOVE(self):取得2張圖片,丟給size_image類別,造成移動效果,resize效果
def SHOW_ITEM(self):取得1張圖片,丟給size_image類別,造成resize效果
def call_resize(self):非執行續啟動時resize效果
def SHOW_ITEM_SIGNAL(self, widget,*event):非執行續啟動時,點選列表造成resize效果
來看主程式如何使用,首先產生了tree_show物件self.t_filechosser,如下初始化tree_show,同始t_filechosser也會被初始化,雖然沒產生t_filechosser物件,
但t_filechosser中的方法,都可在tree_show物件使用(如下),這就是繼承的好處
..................
#初始化,tree_show,tree_show是繼承t_filechosser,在t_filechosser的方法(def),都可使用
self.t_filechosser=tree_show.tree_show(self.scrolledwindow1,self.window,"DELETE",self.file,self.image,self.image_viewport_new)
.............................
if bt_active_label=="停止播放":self.t_filechosser.KILL_TIMER()
if bt_active_label=="由右向左播放":self.t_filechosser.SHOW_TIMER(self.time,"TYPE_MOVE")
....................................
特別重要的是不同類別中的溝通,當A類別產生B類別物件,B類別回過頭去即時使用A類別方法,就是個問題,此時是不能用產生A類別物件再去呼叫的,重新初始化記憶體資料就不一樣了
那要如何作到,一般可宣告成static method,可解決這種情況,python不是很熟,試一下沒完成,就沒試了,我改試了下面這個方式
有趣的一點,我發現A類別竟然可用self把自己本身當參數,整個傳給產生的B物件,過程就像下面這樣,真的很有趣,因為好久沒寫程式,之前在玩QT,JAVA,是不是這樣,真的忘了
我寫程式也喜歡try來try去,寫程式只是玩票性質,無聊亂玩
import b
class a():
def __init__(self)
selfb=b(self)#產生b物件,並把整個class a當參數傳給b,self參數就是整個class a
selfb.B()#使用b類別B()方法
def A(self):
print("class A")
class b():
def __init__(self,obj)
selfa=obj
def B(self):
selfa.A()#使用A類別A()方法
下面在treeview_filechooser.py中就有使用到此技巧,class t_filechosser用self參數,整個傳給了執行續
class t_filechosser(object):
........
def SHOW_TIMER(self,t_time,_type_):
#thread停止,才能在產生thread ,判定thread是否停止
#if(self.thread.is_run_stop()):
self.t_time=t_time
if(not self.thread.isAlive()):
#產生thread,self.play_begin_number是選中項編號,注意最後參數,將自己傳給了thread,使得thread能使用tree_show的method
self.thread = MyThread(self.tt,self.t_time,self.play_begin_number,_type_,self)
print('NUMBER',self.play_begin_number)
#開始thread
self.thread.start()
........
下面MyThread中self.tree_obj.SHOW_ITEM_MOVE(),使用了t_filechosser的方法,即時取t_filechosser的資料
class MyThread(Thread):
.........
def run(self):#執行續,執行的地方
#try:
#while not self.stopped.wait(self.t):
#判斷播放完,self.player_number應設成0,在重播
if(self.player_number+1>=self.len):self.player_number=0
print("執行續啟動")
for x in range(self.player_number,self.len):
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
if(self.is_PLAY):
#try:
#設定treeview選中項目,因為cursor-changed所以會發出信號,調整圖片,定時選中圖片,
#Gdk.threads_enter()
#GObject.idle_add(self.tt.set_cursor(x))
self.tt.set_cursor(x)
#選中列表,根據type,由繼承者實作Method,SHOW_ITEM_MOVE(),SHOW_ITEM()
if(self.type=="TYPE_MOVE"):self.tree_obj.SHOW_ITEM_MOVE()
if(self.type=="TYPE_STEP"):self.tree_obj.SHOW_ITEM()
#Gdk.threads_leave()
time.sleep(self.t)
#except:self.stop()
#self.stopped.wait(1)
print("執行續結束")
#except:pass
試了使用Python的繼承方式,實際操作一次,大概就了解如何運作Python的繼承,這裡我沒用到覆寫,所謂覆寫,就是子類別,重寫父類別Method,就是def名稱一樣
我又新增了tree_show模組(tree_show.py),繼承了treeview_filechooser模組,首先treeview_filechooser必須是一個object,而非class,如下的A
A.t_filechosser是一個object,繼承了object
class t_filechosser(object):
B.t_filechosser是一個class
class t_filechosser():
為甚物件導向要使用繼承,就是要程式碼簡單,重複使用,不需要重寫程式碼,看一下tree_show是如何繼承t_filechosser,小括號內就是被繼承對象
tree_show建構式比t_filechosser多了image,view初始化參數,是處理圖片要用到的,用super呼叫了父類別建構式,以便能夠初始化父類別,
在tree_show只出始化self.image_viewport_new,self.image,self.pixbuf(如下面程式碼),其他都是在父類別初始化的
邏輯和構想,目的我希望t_filechosser專注在樹狀表單(檔案選擇器),到時要寫其他就不用改甚,可用在其他如播放MP3的表單等
,讓tree_show則專注在處理圖片方面,讓程式簡單易讀,程式碼重複使用率提高
class tree_show(treeview_filechooser.t_filechosser):
def __init__(self,add_widget,window,_type_,ifile,image,view):
#呼叫了父類別建構式
super(tree_show,self).__init__(add_widget,window,_type_,ifile)
self.tt.connect('cursor-changed', self.SHOW_ITEM_SIGNAL)
#self.tt.connect('cursor-changed', self.SHOW_ITEM_MOVE)
self.image_viewport_new=view
self.image=image
self.pixbuf = Pixbuf.new_from_file(self.file)
在tree_show中的4個方法,實做了處理圖片方法(須透過配合size_image類別)
def SHOW_ITEM_MOVE(self):取得2張圖片,丟給size_image類別,造成移動效果,resize效果
def SHOW_ITEM(self):取得1張圖片,丟給size_image類別,造成resize效果
def call_resize(self):非執行續啟動時resize效果
def SHOW_ITEM_SIGNAL(self, widget,*event):非執行續啟動時,點選列表造成resize效果
來看主程式如何使用,首先產生了tree_show物件self.t_filechosser,如下初始化tree_show,同始t_filechosser也會被初始化,雖然沒產生t_filechosser物件,
但t_filechosser中的方法,都可在tree_show物件使用(如下),這就是繼承的好處
..................
#初始化,tree_show,tree_show是繼承t_filechosser,在t_filechosser的方法(def),都可使用
self.t_filechosser=tree_show.tree_show(self.scrolledwindow1,self.window,"DELETE",self.file,self.image,self.image_viewport_new)
.............................
if bt_active_label=="停止播放":self.t_filechosser.KILL_TIMER()
if bt_active_label=="由右向左播放":self.t_filechosser.SHOW_TIMER(self.time,"TYPE_MOVE")
....................................
特別重要的是不同類別中的溝通,當A類別產生B類別物件,B類別回過頭去即時使用A類別方法,就是個問題,此時是不能用產生A類別物件再去呼叫的,重新初始化記憶體資料就不一樣了
那要如何作到,一般可宣告成static method,可解決這種情況,python不是很熟,試一下沒完成,就沒試了,我改試了下面這個方式
有趣的一點,我發現A類別竟然可用self把自己本身當參數,整個傳給產生的B物件,過程就像下面這樣,真的很有趣,因為好久沒寫程式,之前在玩QT,JAVA,是不是這樣,真的忘了
我寫程式也喜歡try來try去,寫程式只是玩票性質,無聊亂玩
import b
class a():
def __init__(self)
self.b=b(self)#產生b物件,並把整個class a當參數傳給b,self參數就是整個class a
self.b.B()#使用b類別B()方法
def A(self):
print("class A")
class b():
def __init__(self,obj)
self.a=obj
def B(self):
self.a.A()#使用A類別A()方法
下面在treeview_filechooser.py中就有使用到此技巧,class t_filechosser用self參數,整個傳給了執行續
class t_filechosser(object):
........
def SHOW_TIMER(self,t_time,_type_):
#thread停止,才能在產生thread ,判定thread是否停止
#if(self.thread.is_run_stop()):
self.t_time=t_time
if(not self.thread.isAlive()):
#產生thread,self.play_begin_number是選中項編號,注意最後參數,將自己傳給了thread,使得thread能使用tree_show的method
self.thread = MyThread(self.tt,self.t_time,self.play_begin_number,_type_,self)
print('NUMBER',self.play_begin_number)
#開始thread
self.thread.start()
........
下面MyThread中self.tree_obj.SHOW_ITEM_MOVE(),使用了t_filechosser的方法,即時取t_filechosser的資料
class MyThread(Thread):
.........
def run(self):#執行續,執行的地方
#try:
#while not self.stopped.wait(self.t):
#判斷播放完,self.player_number應設成0,在重播
if(self.player_number+1>=self.len):self.player_number=0
print("執行續啟動")
for x in range(self.player_number,self.len):
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
if(self.is_PLAY):
#try:
#設定treeview選中項目,因為cursor-changed所以會發出信號,調整圖片,定時選中圖片,
#Gdk.threads_enter()
#GObject.idle_add(self.tt.set_cursor(x))
self.tt.set_cursor(x)
#選中列表,根據type,由繼承者實作Method,SHOW_ITEM_MOVE(),SHOW_ITEM()
if(self.type=="TYPE_MOVE"):self.tree_obj.SHOW_ITEM_MOVE()
if(self.type=="TYPE_STEP"):self.tree_obj.SHOW_ITEM()
#Gdk.threads_leave()
time.sleep(self.t)
#except:self.stop()
#self.stopped.wait(1)
print("執行續結束")
#except:pass
read more...
新增了一個播放效果
執行樣本:
試了使用Python的繼承方式,實際操作一次,大概就了解如何運作Python的繼承,這裡我沒用到覆寫,所謂覆寫,就是子類別,重寫父類別Method,就是def名稱一樣
我又新增了tree_show模組(tree_show.py),繼承了treeview_filechooser模組,首先treeview_filechooser必須是一個object,而非class,如下的A
A.t_filechosser是一個object,繼承了object
class t_filechosser(object):
B.t_filechosser是一個class
class t_filechosser():
為甚物件導向要使用繼承,就是要程式碼簡單,重複使用,不需要重寫程式碼,看一下tree_show是如何繼承t_filechosser,小括號內就是被繼承對象
tree_show建構式比t_filechosser多了image,view初始化參數,是處理圖片要用到的,用super呼叫了父類別建構式,以便能夠初始化父類別,
在tree_show只出始化self.image_viewport_new,self.image,self.pixbuf(如下面程式碼),其他都是在父類別初始化的
邏輯和構想,目的我希望t_filechosser專注在樹狀表單(檔案選擇器),到時要寫其他就不用改甚,可用在其他如播放MP3的表單等
,讓tree_show則專注在處理圖片方面,讓程式簡單易讀,程式碼重複使用率提高
class tree_show(treeview_filechooser.t_filechosser):
def __init__(self,add_widget,window,_type_,ifile,image,view):
#呼叫了父類別建構式
super(tree_show,self).__init__(add_widget,window,_type_,ifile)
self.tt.connect('cursor-changed', self.SHOW_ITEM_SIGNAL)
#self.tt.connect('cursor-changed', self.SHOW_ITEM_MOVE)
self.image_viewport_new=view
self.image=image
self.pixbuf = Pixbuf.new_from_file(self.file)
在tree_show中的4個方法,實做了處理圖片方法(須透過配合size_image類別)
def SHOW_ITEM_MOVE(self):取得2張圖片,丟給size_image類別,造成移動效果,resize效果
def SHOW_ITEM(self):取得1張圖片,丟給size_image類別,造成resize效果
def call_resize(self):非執行續啟動時resize效果
def SHOW_ITEM_SIGNAL(self, widget,*event):非執行續啟動時,點選列表造成resize效果
來看主程式如何使用,首先產生了tree_show物件self.t_filechosser,如下初始化tree_show,同始t_filechosser也會被初始化,雖然沒產生t_filechosser物件,
但t_filechosser中的方法,都可在tree_show物件使用(如下),這就是繼承的好處
..................
#初始化,tree_show,tree_show是繼承t_filechosser,在t_filechosser的方法(def),都可使用
self.t_filechosser=tree_show.tree_show(self.scrolledwindow1,self.window,"DELETE",self.file,self.image,self.image_viewport_new)
.............................
if bt_active_label=="停止播放":self.t_filechosser.KILL_TIMER()
if bt_active_label=="由右向左播放":self.t_filechosser.SHOW_TIMER(self.time,"TYPE_MOVE")
....................................
特別重要的是不同類別中的溝通,當A類別產生B類別物件,B類別回過頭去即時使用A類別方法,就是個問題,此時是不能用產生A類別物件再去呼叫的,重新初始化記憶體資料就不一樣了
那要如何作到,一般可宣告成static method,可解決這種情況,python不是很熟,試一下沒完成,就沒試了,我改試了下面這個方式
有趣的一點,我發現A類別竟然可用self把自己本身當參數,整個傳給產生的B物件,過程就像下面這樣,真的很有趣,因為好久沒寫程式,之前在玩QT,JAVA,是不是這樣,真的忘了
我寫程式也喜歡try來try去,寫程式只是玩票性質,無聊亂玩
import b
class a():
def __init__(self)
selfb=b(self)#產生b物件,並把整個class a當參數傳給b,self參數就是整個class a
selfb.B()#使用b類別B()方法
def A(self):
print("class A")
class b():
def __init__(self,obj)
selfa=obj
def B(self):
selfa.A()#使用A類別A()方法
下面在treeview_filechooser.py中就有使用到此技巧,class t_filechosser用self參數,整個傳給了執行續
class t_filechosser(object):
........
def SHOW_TIMER(self,t_time,_type_):
#thread停止,才能在產生thread ,判定thread是否停止
#if(self.thread.is_run_stop()):
self.t_time=t_time
if(not self.thread.isAlive()):
#產生thread,self.play_begin_number是選中項編號,注意最後參數,將自己傳給了thread,使得thread能使用tree_show的method
self.thread = MyThread(self.tt,self.t_time,self.play_begin_number,_type_,self)
print('NUMBER',self.play_begin_number)
#開始thread
self.thread.start()
........
下面MyThread中self.tree_obj.SHOW_ITEM_MOVE(),使用了t_filechosser的方法,即時取t_filechosser的資料
class MyThread(Thread):
.........
def run(self):#執行續,執行的地方
#try:
#while not self.stopped.wait(self.t):
#判斷播放完,self.player_number應設成0,在重播
if(self.player_number+1>=self.len):self.player_number=0
print("執行續啟動")
for x in range(self.player_number,self.len):
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
if(self.is_PLAY):
#try:
#設定treeview選中項目,因為cursor-changed所以會發出信號,調整圖片,定時選中圖片,
#Gdk.threads_enter()
#GObject.idle_add(self.tt.set_cursor(x))
self.tt.set_cursor(x)
#選中列表,根據type,由繼承者實作Method,SHOW_ITEM_MOVE(),SHOW_ITEM()
if(self.type=="TYPE_MOVE"):self.tree_obj.SHOW_ITEM_MOVE()
if(self.type=="TYPE_STEP"):self.tree_obj.SHOW_ITEM()
#Gdk.threads_leave()
time.sleep(self.t)
#except:self.stop()
#self.stopped.wait(1)
print("執行續結束")
#except:pass
試了使用Python的繼承方式,實際操作一次,大概就了解如何運作Python的繼承,這裡我沒用到覆寫,所謂覆寫,就是子類別,重寫父類別Method,就是def名稱一樣
我又新增了tree_show模組(tree_show.py),繼承了treeview_filechooser模組,首先treeview_filechooser必須是一個object,而非class,如下的A
A.t_filechosser是一個object,繼承了object
class t_filechosser(object):
B.t_filechosser是一個class
class t_filechosser():
為甚物件導向要使用繼承,就是要程式碼簡單,重複使用,不需要重寫程式碼,看一下tree_show是如何繼承t_filechosser,小括號內就是被繼承對象
tree_show建構式比t_filechosser多了image,view初始化參數,是處理圖片要用到的,用super呼叫了父類別建構式,以便能夠初始化父類別,
在tree_show只出始化self.image_viewport_new,self.image,self.pixbuf(如下面程式碼),其他都是在父類別初始化的
邏輯和構想,目的我希望t_filechosser專注在樹狀表單(檔案選擇器),到時要寫其他就不用改甚,可用在其他如播放MP3的表單等
,讓tree_show則專注在處理圖片方面,讓程式簡單易讀,程式碼重複使用率提高
class tree_show(treeview_filechooser.t_filechosser):
def __init__(self,add_widget,window,_type_,ifile,image,view):
#呼叫了父類別建構式
super(tree_show,self).__init__(add_widget,window,_type_,ifile)
self.tt.connect('cursor-changed', self.SHOW_ITEM_SIGNAL)
#self.tt.connect('cursor-changed', self.SHOW_ITEM_MOVE)
self.image_viewport_new=view
self.image=image
self.pixbuf = Pixbuf.new_from_file(self.file)
在tree_show中的4個方法,實做了處理圖片方法(須透過配合size_image類別)
def SHOW_ITEM_MOVE(self):取得2張圖片,丟給size_image類別,造成移動效果,resize效果
def SHOW_ITEM(self):取得1張圖片,丟給size_image類別,造成resize效果
def call_resize(self):非執行續啟動時resize效果
def SHOW_ITEM_SIGNAL(self, widget,*event):非執行續啟動時,點選列表造成resize效果
來看主程式如何使用,首先產生了tree_show物件self.t_filechosser,如下初始化tree_show,同始t_filechosser也會被初始化,雖然沒產生t_filechosser物件,
但t_filechosser中的方法,都可在tree_show物件使用(如下),這就是繼承的好處
..................
#初始化,tree_show,tree_show是繼承t_filechosser,在t_filechosser的方法(def),都可使用
self.t_filechosser=tree_show.tree_show(self.scrolledwindow1,self.window,"DELETE",self.file,self.image,self.image_viewport_new)
.............................
if bt_active_label=="停止播放":self.t_filechosser.KILL_TIMER()
if bt_active_label=="由右向左播放":self.t_filechosser.SHOW_TIMER(self.time,"TYPE_MOVE")
....................................
特別重要的是不同類別中的溝通,當A類別產生B類別物件,B類別回過頭去即時使用A類別方法,就是個問題,此時是不能用產生A類別物件再去呼叫的,重新初始化記憶體資料就不一樣了
那要如何作到,一般可宣告成static method,可解決這種情況,python不是很熟,試一下沒完成,就沒試了,我改試了下面這個方式
有趣的一點,我發現A類別竟然可用self把自己本身當參數,整個傳給產生的B物件,過程就像下面這樣,真的很有趣,因為好久沒寫程式,之前在玩QT,JAVA,是不是這樣,真的忘了
我寫程式也喜歡try來try去,寫程式只是玩票性質,無聊亂玩
import b
class a():
def __init__(self)
self.b=b(self)#產生b物件,並把整個class a當參數傳給b,self參數就是整個class a
self.b.B()#使用b類別B()方法
def A(self):
print("class A")
class b():
def __init__(self,obj)
self.a=obj
def B(self):
self.a.A()#使用A類別A()方法
下面在treeview_filechooser.py中就有使用到此技巧,class t_filechosser用self參數,整個傳給了執行續
class t_filechosser(object):
........
def SHOW_TIMER(self,t_time,_type_):
#thread停止,才能在產生thread ,判定thread是否停止
#if(self.thread.is_run_stop()):
self.t_time=t_time
if(not self.thread.isAlive()):
#產生thread,self.play_begin_number是選中項編號,注意最後參數,將自己傳給了thread,使得thread能使用tree_show的method
self.thread = MyThread(self.tt,self.t_time,self.play_begin_number,_type_,self)
print('NUMBER',self.play_begin_number)
#開始thread
self.thread.start()
........
下面MyThread中self.tree_obj.SHOW_ITEM_MOVE(),使用了t_filechosser的方法,即時取t_filechosser的資料
class MyThread(Thread):
.........
def run(self):#執行續,執行的地方
#try:
#while not self.stopped.wait(self.t):
#判斷播放完,self.player_number應設成0,在重播
if(self.player_number+1>=self.len):self.player_number=0
print("執行續啟動")
for x in range(self.player_number,self.len):
#因為thread一起動,便不能中止,指能讓run不做任何事,走完自動KILL
if(self.is_PLAY):
#try:
#設定treeview選中項目,因為cursor-changed所以會發出信號,調整圖片,定時選中圖片,
#Gdk.threads_enter()
#GObject.idle_add(self.tt.set_cursor(x))
self.tt.set_cursor(x)
#選中列表,根據type,由繼承者實作Method,SHOW_ITEM_MOVE(),SHOW_ITEM()
if(self.type=="TYPE_MOVE"):self.tree_obj.SHOW_ITEM_MOVE()
if(self.type=="TYPE_STEP"):self.tree_obj.SHOW_ITEM()
#Gdk.threads_leave()
time.sleep(self.t)
#except:self.stop()
#self.stopped.wait(1)
print("執行續結束")
#except:pass
read more...
訂閱:
文章 (Atom)