現在來說原理,
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
沒有留言:
張貼留言