Hallo zusammen,
ich habe mir als Projekt vorgenommen eine Steuerung für mein Aquarium zu entwickeln.
Angezeigt werden sollen später verschiedene Temeraturwerte, PH Wert, Wasserdurchfluss, etc.
Außerdem soll man Auswählen können wann der letzte Wasserwechsel gemacht wurde und wann die PH Sonde das letzte mal kalibriert wurde.
Erstmal will ich aber den groben Aufbau der pygame Anwendung entwickeln.
Hier hab ich jetzt die Ersten bedenken.
Ich habe mal angefangen mit python und pygame halbwissen eine Anwendung zu schreiben.
Ein Bestandteil ist ein Numpad um den KH Wert zu einzugeben.
An dieser Stelle (geöffnetes Numpad) brechen die FPS zusammen, sodass eine kleine Verzögerung bei der Eingabe entsteht. Bisher ist die Verzögerung nur ein bruchteil einer Sekunde.. Habe aber sorgen, dass die Verzögerung mit wachsendem Code noch deutlich länger wird.
Das ganze wurde getestet auf meinem Raspberry Pi 2 B.
Vielleicht kann jemand mal meinen "wurstel Code" anschauen und mir evtl ein paar Tipps geben wo bzw wie Performanceoptiomierungen drin sind, ober ob ich mangels Performance es am besten gleich vergessen soll!?
Ich bin für jeden Rat in jede Richtung dankbar!
So und jetzt zum code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame, time, datetime, sys, os, random, threading, socket
import xml.etree.cElementTree as ET
from pygame.locals import *
import os.path
#import RPi.GPIO as GPIO
#os.putenv('SDL_FBDEV', '/dev/tty0')
pygame.init()
if(socket.gethostname() == "RealPi"):
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN)
savefile = "/home/pi/save.xml"
img_path = "/home/pi/img/"
else:
screen = pygame.display.set_mode([800, 480])
os.chdir('C:\\Users\\Napster\\Documents')
savefile = "C:\\Users\\Napster\\Documents\\save.xml"
img_path = "C:\\Users\\Napster\\Documents\\img\\"
pygame.mouse.set_visible(True)
def set_font(size=20,bold=False):
global font
font = pygame.font.SysFont("Courier New", size)
font.set_bold(bold)
# Define some variables
main_w = pygame.display.Info().current_w
main_h = pygame.display.Info().current_h
c_white = (255, 255, 255)
c_black = (0, 0, 0)
c_red = (255, 0, 0)
c_btn_green = (150, 255, 150)
c_btn_grey = (150, 150, 150)
font = pygame.font.SysFont("Comic Sans MS", 20)
degree = u'\xb0'+"C"
popup = ""
set_font(30)
numpad_text = ""
set_font()
menu = 0
#Menu buttons
pos_btn = [[0, 420, 267, 60],[0, 420, 267, 60],[0, 420, 266, 60]]
pos_btn[1][0] = pos_btn[0][2]
pos_btn[2][0] = pos_btn[0][2]+pos_btn[1][2]
#Menu 0
txt_temp1 = "10"
txt_temp2 = "10"
#Menu 1
txt_durchfluss = "400"
txt_wasserwechsel = datetime.datetime.now().strftime('%d.%m.%Y')
# Load and set up graphics.
#background_image = pygame.image.load("test1.jpg").convert()
#img_temperature_ok = pygame.image.load(img_path+"temperature_ok.png").convert_alpha()
#img_temperature_nok = pygame.image.load(img_path+"temperature_nok.png").convert_alpha()
#img_flow = pygame.image.load(img_path+"flow.png").convert_alpha()
#img_water = pygame.image.load(img_path+"water.png").convert_alpha()
#player_image.set_colorkey(c_black)
def save_xml(root, attr, value):
global savefile
root = ET.Element(root)
ET.SubElement(root, attr).text = value
tree = ET.ElementTree(root)
tree.write(savefile)
def read_xml(attr):
global savefile
if (os.path.isfile(savefile)):
tree = ET.parse(savefile)
root = tree.getroot()
return root.find(attr).text
else:
return ""
def timer_refresh():
global running
global menu
if running:
if menu == 0:
global txt_temp1
global txt_temp2
txt_temp1 = str(int(txt_temp1)+3)
txt_temp2 = str(int(txt_temp2)+10)
threading.Timer(1, timer_refresh).start()
def change_value(label, value, pos, color):
global font
text = font.render(fill_spaces(label+":")+value, 1, color)
return screen.blit(text, pos)
def fill_spaces(text, length=13):
while len(text) < length:
text += " "
return text
def show_menu():
global font
global menu
global pos_btn
txt_btn = ["Werte", "Wartung", "Setup"]
set_font(45, True)
for i in xrange(0,len(txt_btn)):
if(menu == i):
pygame.draw.rect(screen, c_btn_green, pos_btn[i], 0)
text = font.render(txt_btn[i], 1, c_black)
screen.blit(text, [pos_btn[i][0]+25,pos_btn[i][1]+5])
else:
pygame.draw.rect(screen, c_btn_grey, pos_btn[i], 0)
text = font.render(txt_btn[i], 1, c_white)
screen.blit(text, [pos_btn[i][0]+25,pos_btn[i][1]+5])
#Strich über den Buttons
pygame.draw.line(screen, c_black, [0, pos_btn[0][1]-2], [pos_btn[0][2]+pos_btn[1][2]+pos_btn[2][2], pos_btn[0][1]-2], 2)
#Trennstriche zwischen den Buttons
pygame.draw.line(screen, c_black, [pos_btn[1][0]-1, pos_btn[1][1]], [pos_btn[1][0]-1, pos_btn[1][1]+pos_btn[1][3]], 2)
pygame.draw.line(screen, c_black, [pos_btn[2][0]-1, pos_btn[2][1]], [pos_btn[2][0]-1, pos_btn[2][1]+pos_btn[2][3]], 2)
set_font()
def numpad_click(mouse_pos):
global main_w
global main_h
global numpad_text
global popup
w = 280
h = 440
x = (main_w/2)-(w/2)
y = (main_h/2)-(h/2)
margin = 40
padding = 10
top = 80
size = 60
if ((x+margin <= mouse_pos[0] <= x+margin+size) & (y+top <= mouse_pos[1] <= y+top+size)):
numpad_text += "1"
elif ((x+margin+padding+size <= mouse_pos[0] <= x+margin+size+padding+size) & (y+top <= mouse_pos[1] <= y+top+size)):
numpad_text += "2"
elif ((x+margin+(2*(padding+size)) <= mouse_pos[0] <= x+margin+size+(2*(padding+size))) & (y+top <= mouse_pos[1] <= y+top+size)):
numpad_text += "3"
elif ((x+margin <= mouse_pos[0] <= x+margin+size) & (y+top+(size+padding) <= mouse_pos[1] <= y+top+(size+padding)+size)):
numpad_text += "4"
elif ((x+margin+padding+size <= mouse_pos[0] <= x+margin+size+padding+size) & (y+top+(size+padding) <= mouse_pos[1] <= y+top+(size+padding)+size)):
numpad_text += "5"
elif ((x+margin+(2*(padding+size)) <= mouse_pos[0] <= x+margin+size+(2*(padding+size))) & (y+top+(size+padding) <= mouse_pos[1] <= y+top+(size+padding)+size)):
numpad_text += "6"
elif ((x+margin <= mouse_pos[0] <= x+margin+size) & (y+top+(2*(size+padding)) <= mouse_pos[1] <= y+top+(2*(size+padding))+size)):
numpad_text += "7"
elif ((x+margin+padding+size <= mouse_pos[0] <= x+margin+size+padding+size) & (y+top+(2*(size+padding)) <= mouse_pos[1] <= y+top+(2*(size+padding))+size)):
numpad_text += "8"
elif ((x+margin+(2*(padding+size)) <= mouse_pos[0] <= x+margin+size+(2*(padding+size))) & (y+top+(2*(size+padding)) <= mouse_pos[1] <= y+top+(2*(size+padding))+size)):
numpad_text += "9"
elif ((x+margin <= mouse_pos[0] <= x+margin+size) & (y+top+(3*(size+padding)) <= mouse_pos[1] <= y+top+(3*(size+padding))+size) & (numpad_text.find(",")==-1)):
numpad_text += ","
elif ((x+margin+padding+size <= mouse_pos[0] <= x+margin+size+padding+size) & (y+top+(3*(size+padding)) <= mouse_pos[1] <= y+top+(3*(size+padding))+size)):
numpad_text += "0"
elif ((x+margin+(2*(padding+size)) <= mouse_pos[0] <= x+margin+size+(2*(padding+size))) & (y+top+(3*(size+padding)) <= mouse_pos[1] <= y+top+(3*(size+padding))+size)):
numpad_text = numpad_text[:-1]
elif ((x+margin <= mouse_pos[0] <= x+margin+size+(3*(padding+size))) & (y+top+(4*(size+padding)) <= mouse_pos[1] <= y+top+(4*(size+padding))+size)):
save_xml("settings","kh",numpad_text)
popup = ""
elif ((x+w-40 <= mouse_pos[0] <= x+w) & (y <= mouse_pos[1] <= y+40)):
popup = ""
def main():
global running
global menu
global popup
global numpad_text
clock = pygame.time.Clock()
while running:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#GPIO.cleanup()
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if (popup == "numpad"):
numpad_click(mouse_pos)
else:
if (pos_btn[0][1] <= mouse_pos[1] <=pos_btn[0][1]+pos_btn[0][3]):
if (mouse_pos[0] <= pos_btn[0][2]):
menu = 0
elif (pos_btn[1][0] <= mouse_pos[0] <= (pos_btn[0][2]+pos_btn[1][2])):
menu = 1
elif (pos_btn[2][0] <= mouse_pos[0]):
menu = 2
if(mouse_pos[1] <= 40):
numpad_text = read_xml("kh")
popup = "numpad"
if (menu == 0):
global txt_temp1
global txt_temp2
screen.fill((100,100,100))
set_font(40)
#screen.blit(pygame.transform.scale(img_temperature_ok,(64,64)),(0,0))
change_value("Temperatur1", txt_temp1+degree, [60,10], c_white)
#screen.blit(pygame.transform.scale(img_temperature_nok,(64,64)),(0,65))
change_value("Temp2", txt_temp2+degree, [60,75], c_white)
set_font()
elif (menu == 1):
global txt_durchfluss
global txt_wasserwechsel
screen.fill((200,50,50))
set_font(40)
#screen.blit(pygame.transform.scale(img_flow,(64,64)),(0,0))
change_value("Durchfluss", txt_durchfluss, [60,10], c_white)
#screen.blit(pygame.transform.scale(img_water,(64,64)),(0,65))
change_value("Wasserwechsel", txt_wasserwechsel, [60,75], c_white)
set_font()
elif (menu == 2):
screen.fill((50,200,50))
set_font(40)
change_value("none", "NaN", [0,0], c_white)
set_font()
show_menu()
if(popup != ""):
if(popup == "numpad"):
num = numpad()
num.show("KH Wert")
pygame.display.update()
clock.tick(30)
class numpad(object):
def __init__(self):
self.w = 280
self.h = 440
self.x = (pygame.display.Info().current_w/2)-(self.w/2)
self.y = (pygame.display.Info().current_h/2)-(self.h/2)
self.draw_box([0,0])
def draw_box(self, size, color=c_white):
self.key = pygame.Surface((size[0],size[1]))
self.key.fill(color)
for j in [0, 1, size[1]-2, size[1]-1]:
for i in xrange(0, size[0]):
self.key.set_at((i, j), c_black)
for j in [0, 1, size[0]-2, size[0]-1]:
for i in xrange(0, size[1]):
self.key.set_at((j, i), c_black)
def background(self):
bg = pygame.Surface((pygame.display.Info().current_w,pygame.display.Info().current_h))
bg.set_alpha(170)
bg.fill((0,0,0))
screen.blit(bg, (0,0))
def touchkey(self, x, y, w, h, text, color=c_black, fontsize=50, text_offset=[0,0]):
if(self.key.get_size() != [w, h]):
self.draw_box([w, h])
screen.blit(self.key, (x,y))
set_font(fontsize,True)
text = font.render(text, 1, color)
set_font()
screen.blit(text, [x+13+text_offset[0],y+5+text_offset[1]])
def show(self, title):
global numpad_text
self.background()
num = 1
size = 60
padding = 10
margin = 40
pygame.draw.rect(screen, c_white, [self.x, self.y, self.w, self.h], 0)
pygame.draw.rect(screen, c_black, [self.x, self.y, self.w, self.h], 2)
pygame.draw.rect(screen, c_btn_grey, [self.x, self.y, self.w, 40], 0)
pygame.draw.rect(screen, c_black, [self.x, self.y, self.w, 40], 2)
set_font(35, True)
text = font.render(title, 1, c_black)
set_font()
screen.blit(text, [self.x+padding,self.y])
pygame.draw.rect(screen, c_red, [(self.x+self.w-40),self.y,40,40], 0)
pygame.draw.rect(screen, c_black, [(self.x+self.w-40),self.y,40,40], 2)
set_font(40,True)
screen.blit(font.render("X", 1, c_black), [(self.x+self.w-40+5),self.y])
set_font(30,False)
screen.blit(font.render(numpad_text, 1, c_black), [self.x+margin,self.y+45])
set_font()
key_y = 30
for i in xrange(1,4):
key_x = self.x
key_y += size+padding
for j in xrange(1,4):
if(j == 1):
key_x += +margin
else:
key_x += size+padding
self.touchkey(key_x, key_y, size,size, str(num))
num +=1
key_y += size+padding
self.touchkey(self.x+margin, key_y, size,size, ",")
self.touchkey(self.x+margin+size+padding, key_y, size,size, "0")
self.touchkey(self.x+margin+(2*(size+padding)), key_y, size,size, "<", c_red)
self.touchkey(self.x+margin, self.y+(5*(size+padding)+padding), size+(2*(size+padding)),size, "Speichern", c_black, 28, [0,8])
if __name__ == '__main__':
running = True
try:
threading.Timer(1, timer_refresh).start()
main()
except KeyboardInterrupt:
running = False
threading.Timer(0, timer_refresh).cancel()
pygame.quit()
sys.exit()
finally:
print "exit"
#GPIO.cleanup()
Display More
Achja.. ein paar wenige Bilder habe ich auskommentiert, die waren aber mehr oder weniger erstmal nur zum Testen für mich, spielen an der Stelle also eigentlich keine wichtige Rolle.
Viele Grüße
EDIT:
Ganz vergessen! Das Numpad geht beim aktuellen Stand auf wenn man in den oberen 40 pixeln klickt - soll natürlich später einen Button bekommen, aber so erstmal zum testen-