在RaspberryPi中用Pygame做信息显示屏

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

关注的信息数据可以用相应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)


可以用这东西显示各种信息,如新闻、股市、物价、备忘或者作为电子相册。



  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值