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








沒有留言: