您的位置:首页 > 编程语言 > ASP

在RaspberryPi中用Pygame做信息显示屏

2016-05-10 18:14 253 查看
家母患眼疾已久,艰于视物,看电视时头都快钻进机子里了。

为了弘扬物尽其用精神,改善生活质量,本着家人为我我为家人的宗旨,我用树莓派对某些图像信息的尺寸尽量放大,并连接到电视上显示,比如天气预报类信息,以便她一目了然成竹在胸,收吾之晾衣而无受浸雨侵袭。

关注的信息数据可以用相应API获取,或者去页面抓,但界面还是要自己组织,对我来说要花些成本。

所以我直接用CasperJS(基于PhantomJS(一个无界面的Webkit浏览器))对页面需要的部分截图,然后用Pygame直接显示图片便完事儿。

Raspbian已自带Python和Pygame,如果之前做过2D贴图,Pygame是很易用的。一步一步来:

1.Hello World

import time,pygame,sys
from pygame.locals import *

def init():#初始化
pygame.init()
screen_size = (1280,720)
screen = pygame.display.set_mode(screen_size,0,32) #设置窗口
return screen

def update(screen):#显示
p = pygame.image.load(sys.path[0]+"/img/p1.png").convert()#加载图片
screen.blit(p,(0,0))#贴到显示屏(从左上角开始)
pygame.display.update()#这时才更新到窗口

def eventCheck():#非必要
for event in pygame.event.get():
if event.type in [QUIT ,KEYDOWN]:#退出及键按下事件时
pygame.quit()#退出
sys.exit()

screen=init()
update(screen)
#以下非必要,加上是为了方便退出
while True:
eventCheck()
time.sleep(1)


2.获取信息后再显示
与上一版相比有修改的地方用 '##' 表示,删除的忽略。下同。

本例增加一个信息类,新开子进程用CasperJS截图。

开头import的subprocess32来自python3下的subprocess,可以限制进程的timeout,不然可能会等到世界末日。

在python2中需安装,只用内建的subprocess也可以,自己写定时检查的代码。

import time,pygame,sys
from pygame.locals import *
import subprocess32 as subprocess ##

class Info():##获取信息类
def get(self):
try:
subprocess.check_output(["casperjs",sys.path[0]+"/weather.js"],timeout=60)
except Exception,e:
return False#timeout的话可能要把子进程杀掉
return True

def init():
pygame.init()
screen_size = (1280,720)
screen = pygame.display.set_mode(screen_size,0,32)
return screen

def update(screen):
p = pygame.image.load(sys.path[0]+"/img/p3.png").convert()
screen.blit(p,(0,0))
pygame.display.update()

def eventCheck():
for event in pygame.event.get():
if event.type in [QUIT ,KEYDOWN]:
pygame.quit()
sys.exit()

screen=init()
if Info().get():##获取信息
update(screen)
while True:
eventCheck()
time.sleep(1)


3.定时获取信息

用循环的话程序不能往下走,不能响应。改为用新线程运行。

import time,pygame,sys,threading##
from pygame.locals import *
import subprocess32 as subprocess

class Info():
def __init__(self): ##
self.nextTime=0

def get(self):
try:
#以子进程方式运行命令,返回代码不为0或超时都视为失败
subprocess.check_output(["casperjs",sys.path[0]+"/weather.js"],timeout=60)
except Exception,e:
return False
return True

def runPlan(self,update,screen): ##
while True:
if self.nextTime<time.time():
isOK=self.get()
if isOK:
update(screen)
self.nextTime=time.time()+3*60*60# 成功后下次运行时间设在3小时后
else:
self.nextTime=time.time()+180# 失败则3分钟后重试
time.sleep(60)

def init():
pygame.init()
screen_size = (1280,720)
screen = pygame.display.set_mode(screen_size,0,32)
return screen

def update(screen):
p = pygame.image.load(sys.path[0]+"/img/p1.png").convert()
screen.blit(p,(0,0))
pygame.display.update()

def eventCheck():
for event in pygame.event.get():
if event.type in [QUIT ,KEYDOWN]:
pygame.quit()
sys.exit()
time.sleep(1)

screen=init()
th=threading.Thread(target=Info().runPlan,args=(update,screen))##把获取信息后的更新图片的回调方法和参数传给定时获取方法
th.setDaemon(True)
th.start()

while True:
eventCheck()


4.轮流显示多张图片

加个图片类来管理,显示部分也单独分出来,加个计数器类用于触发图片切换。

import time,pygame,sys,threading
from pygame.locals import *
import subprocess32 as subprocess

class Info():
def __init__(self):
self.nextTime=0

def get(self):
try:
<span style="white-space:pre">	</span>    subprocess.check_output(["casperjs",sys.path[0]+"/weather.js"],timeout=60)
except Exception,e:
return False#need manual stop
return True

def runPlan(self,updateImg):
while True:
if self.nextTime<time.time():
isOK=self.get()
if isOK:
updateImg()
self.nextTime=time.time()+3*60*60
else:
self.nextTime=time.time()+180#retry
time.sleep(60)
######################################################################
class Imgs(): ##图片类
def __init__(self):
self.curPos=-1 #当前位置,即哪张图片
self.list=[] #图片列表
self.isGetImg=False #是否已获取图片
def getCur(self):#得到这次要显示的图片
self.curPos+=1
if self.curPos>=len(self.list):
self.curPos=0
return self.list[self.curPos]
def update(self):#图片更新到列表
list=[]
p = pygame.image.load(sys.path[0]+"/img/p1.png").convert()
list.append(p)
p = pygame.image.load(sys.path[0]+"/img/p2.png").convert()
list.append(p)
#......
self.list=list
self.isGetImg=True
#####################################################################
class Counter(): ## 计数器,设定计数到多少时触发,以返回True为标志
def __init__(self,trigCount):
self.count=0
self.trigCount=trigCount

def reachTrig(self):
self.count+=1
if self.count>=self.trigCount:
self.count=0
return True
return False
####################################################################
def init():
pygame.init()
screenSize = (1280,720)
screen = pygame.display.set_mode(screenSize,0,32)
return screen

def eventCheck():
for event in pygame.event.get():
if event.type in [QUIT ,KEYDOWN]:
pygame.quit()
sys.exit()

def playboard(screen,imgs):##显示部分放这里
cnt=Counter(10)#计数到10时
while True:
if cnt.reachTrig():#达到触发条件
p=imgs.getCur()
screen.fill((0,0,0))
screen.blit(p,(0,0))
pygame.display.update()
eventCheck()
time.sleep(1)

###################main##########################
screen=init()
imgs=Imgs()
th=threading.Thread(target=Info().runPlan,args=(imgs.update,))##
th.setDaemon(True)
th.start()

while True:
if imgs.isGetImg:
playboard(screen,imgs)
time.sleep(1)


5.加上效果类 实现淡入淡出等各种效果。

import time,pygame,sys,threading
from pygame.locals import *
import subprocess32 as subprocess

class Info():
def __init__(self):
self.nextTime=0

def get(self):
try:
subprocess.check_output(["casperjs",sys.path[0]+"/weather.js"],timeout=60)
except Exception,e:
return False#need manual stop
return True

def runPlan(self,updateImg):
while True:
if self.nextTime<time.time():
isOK=self.get()
if isOK:
updateImg()
self.nextTime=time.time()+3*60*60
else:
self.nextTime=time.time()+180#retry
time.sleep(60)
######################################################################
class Imgs():
def __init__(self):
self.curPos=-1
self.list=[]
self.isGetImg=False
def getLastCur(self):
lastImg=self.list[self.curPos]
self.curPos+=1
if self.curPos>=len(self.list):
self.curPos=0
curImg=self.list[self.curPos]
return  lastImg,curImg
def update(self):
list=[]
p = pygame.image.load(sys.path[0]+"/img/p1.png").convert()
list.append(p)
p = pygame.image.load(sys.path[0]+"/img/p2.png").convert()
list.append(p)
#......
self.list=list
self.isGetImg=True
#####################################################################
class Counter():
def __init__(self,trigCount):
self.count=0
self.trigCount=trigCount

def reachTrig(self):
self.count+=1
if self.count>=self.trigCount:
self.count=0
return True
return False
####################################################################
class Effect():##效果类
def fade(self,screen,p,rg):
for alpha in rg:
p.set_alpha(alpha) #改变透明度
screen.fill((0,0,0))
screen.blit(p,(0,0))
pygame.display.update()
time.sleep(0.01)

def fadeIn(self,screen,p):#淡入
rg=range(0,257,32) #透明度范围由0过渡到256,步长为32
self.fade(screen,p,rg)

def fadeOut(self,screen,p):#淡出
rg=range(255,0,-32)
self.fade(screen,p,rg)
###################################################################
def init():
pygame.init()
screenSize = (1280,720)
screen = pygame.display.set_mode(screenSize,FULLSCREEN,32) ##FULLSCREEN全屏独霸
return screen

def eventCheck():
for event in pygame.event.get():
if event.type in [QUIT ,KEYDOWN]:
pygame.quit()
sys.exit()

def playboard(screen,imgs):
cnt=Counter(4)
ef=Effect()
while True:
if cnt.reachTrig():
li,ci=imgs.getLastCur()
ef.fadeOut(screen,li)  ##上一张淡出
ef.fadeIn(screen,ci) ##这张淡入
eventCheck()
time.sleep(1)

###################main##########################
screen=init()
imgs=Imgs()
th=threading.Thread(target=Info().runPlan,args=(imgs.update,))
th.setDaemon(True)
th.start()

while True:
if imgs.isGetImg:
playboard(screen,imgs)
time.sleep(1)


可以用这东西显示各种信息,如新闻、股市、物价、备忘或者作为电子相册。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: