leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

problem with buttons :(

Sat Dec 13, 2014 9:51 pm

hey guys i have had a go at trying to create a simple gui. two buttons on one screen, one triggers a relay called( pin 7) and the other button is surpose to select the next screenmode.

Where am i going wrong lol :(, thanks for any interest into my headache lol :D

Code: Select all

#! /usr/bin/env python
import pygame, sys
import time, sys
from pygame.locals import *
import RPi.GPIO as GPIO

pygame.init()

global screenMode
screenMode = 0

white = (255,255,255)
screen = pygame.display.set_mode((320,240)) #screen size

pygame.display.flip()

GPIO.setmode( GPIO.BOARD ) ; GPIO.setup( 7 , GPIO.OUT)

buttons = [
		({'id':'override', 'rect':(165,10,60,60), 'icon':override})
		({'id':'users', 'rect':(165,10,60,60), 'icon':users})
		({'id':'changepin', 'rect':(165,10,60,60), 
	]
	def drawbuttons():
		screen.blit(b['icon'], (b['rect'][0], b['rect'][1]))

def selected(rect, pos):
  x1 = rect[0]
  y1 = rect[1]
  x2 = x1 + rect[2] - 1
  y2 = y1 + rect[3] - 1
  if ((pos[0] >= x1) and (pos[0] <= x2) and
      (pos[1] >= y1) and (pos[1] <= y2)):
    return True
  return False

def drawbuttons(sm):
    for b in buttons[sm]:
        screen.blit(b['icon'], (b['rect'][0], b['rect'][1]))

	
def Screen3():		# Main Screen
	screen.fill(white)
	override = pygame.image.load("icons/override.png")# button images
	users = pygame.image.load("icons/users.png")
	screen.blit(override,(5,10))# button position
	screen.blit(users,(165,10))
	

def Screen32():		# Users page
	screen.fill(white)
	add = pygame.image.load("icons/add.png")
	back = pygame.image.load("icons/back.png")
	delete2 = pygame.image.load("icons/delete2.png")
	screen.blit(add,(5,190)) # button position
	screen.blit(back,(210,5))
	screen.blit(delete2,(210,190))
	screen.blit(label,(10,5))
	screen.blit(no1,(22,70))
	screen.blit(no2,(170,70))
	screen.blit(no3,(10,140))
	screen.blit(no4,(170,140))


while True : #main loop
	
	if screenMode == 3:
		Screen3()
		if(event.type is MOUSEBUTTONDOWN):
			pos = pygame.mouse.get_pos()
			for b in buttons[screenMode]:
				if b['id'] == 'users': screenMode = 32
				if b['id'] == 'override': GPIO.output( 7, 	True)
		screenMode = 32
			

	for event in pygame.event.get() :
		if event.type == QUIT :
			pygame.quit()
			sys.exit()
	pygame.display.update()

gordon77
Posts: 5036
Joined: Sun Aug 05, 2012 3:12 pm

Re: problem with buttons :(

Sat Dec 13, 2014 10:02 pm

Don't the def sections need to have a 'return()' to close()

DirkS
Posts: 10362
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: problem with buttons :(

Sat Dec 13, 2014 11:26 pm

gordon77 wrote:Don't the def sections need to have a 'return()' to close()
No

DirkS
Posts: 10362
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: problem with buttons :(

Sat Dec 13, 2014 11:30 pm

Where am i going wrong lol
So what is not working as expected?

BTW: I don't think the first 'def' should be indented.

Gr.
Dirk.

DirkS
Posts: 10362
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: problem with buttons :(

Sat Dec 13, 2014 11:53 pm

I think you're not drawing a screen to start with.
At startup the you're setting screenmode to 0, but the only time you draw the screen is in the 'if screenmode == 3' block.

gordon77
Posts: 5036
Joined: Sun Aug 05, 2012 3:12 pm

Re: problem with buttons :(

Sun Dec 14, 2014 10:14 am

DirkS wrote:
gordon77 wrote:Don't the def sections need to have a 'return()' to close()
No
Cheers :D

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Sun Dec 14, 2014 1:44 pm

before i added the button function to the script both screens worked and layout well in the 320 x 240 on a white back ground with my icons on there just had to change the screen mode == to what ever one. but when i add the button function i get loads of syntax errors, even Dirks version did not work.

why is this so hard to create a button to go to the next screen!!!!!

can someone please help me over come this challenge which others find so simple. makes me feel thick lol

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Mon Dec 15, 2014 7:20 am

Hey guys just to make sure i understand there are three sections to a button.

1. You define what a button is using the same script ive seen on a couple using x and y pos. this goes in the top part where you describe what things are?

2. In each def screen() the button is layout and told where the active section is if clicked. This would be under the def screen() for each screen?

3. The buttons action, " if users button mouse click down = screen32". I would assume this goes in the main loop??

Can you tell me where im going wrong or not adding in something. Ill attached latest script when im in work

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: problem with buttons :(

Mon Dec 15, 2014 9:52 am

There does look something odd about buttons. It seems to have an extra, unnecessary dimension by having a dict inside a tuple inside a list. The third tuple's dict isn't closed, also later on you set the index to buttons to 32 but filter issues out by having a condition if screenMode == 3 which seems to prevent that bit of code ever executing, fortunately as 3 or 32 would be illegal index values. Is there a large chunk of code missing that would explain this.

PS also I notice you use global in an odd place. This is usually put in a function to ensure that a global is used rather than creating a local variable with the same name.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Mon Dec 15, 2014 11:01 am

yes there is, i have cut out alot of the code as i thought it might be easier for you guys to link just 2 screens on 1 or two buttons rather than the rest. it is quite a big piece.

so is my understanding of a button inncorect then? or would people prefer me to post my working code to date?

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: problem with buttons :(

Mon Dec 15, 2014 11:52 am

Quite hard to tell with only bits of the code but I would have a Button class which had a method to return true or false given mouse click position see here http://stackoverflow.com/questions/1016 ... hon-pygame. I would have a list of Buttons in each screen (again I would make these instances of a class rather than functions). I would only check buttons on the list of the currently displayed screen. Ideally the functionality of each button would not have to be done in the main loop but would be held in functions that you could pass to the Button.__init__()
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Mon Dec 15, 2014 2:32 pm

yes excalty what im after list of buttons in each screen, similar to how the icon and screen blit for each icon is.

how would you write it out, code below is main screen two icons and two icon positions

Code: Select all

def Screen3():      # Main Screen
   screen.fill(white)
   override = pygame.image.load("icons/override.png")# button images
   users = pygame.image.load("icons/users.png")
   screen.blit(override,(5,10))# button position
   screen.blit(users,(165,10))

gordon77
Posts: 5036
Joined: Sun Aug 05, 2012 3:12 pm

Re: problem with buttons :(

Mon Dec 15, 2014 5:22 pm

It may not be what you want but in my program l use a different method to draw buttons , rather than loading images, and then detect if the mouse is over them when you press the mouse button.

You can get the program to see it at

http://www.raspberrypi.org/forums/viewt ... 79#p641279
near the end.

Gordon77

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: problem with buttons :(

Mon Dec 15, 2014 6:24 pm

a kind of skeleton version

Code: Select all

class Button(object):
  def __init__(self, location, icon, func=None):
    ...#load icon, set properties, x, y, w, h 
  def check(self, pos):
    ...# pos c.f. x,y etc, run func if exist, return True or False

class Screen(object):
  def __init__(self, screen, background, buttons=None):
    self.screen = screen
    self.background = background
    self.buttons = []
    if buttons:
      self.add_buttons(buttons)

  def activate(self):
    self.screen.fill(white)

  def add_buttons(self, buttons):
    self.buttons.extend(buttons)

  def check(self, pos):
    for b in self.buttons:
      if b.check(pos):
        return b

  def draw(self):
    for b in self.buttons:
      self.screen.blit(b.icon,(b.x, b.y))
...
override = Button((165,10,60,60), 'icons/override.png', my_override_func)
users = Button((123,123,123,123), 'icons/users.png')
etc
...
screen_list = [Screen(screen, white, [override, users]), #screen_list[0]
           Screen(screen, white, [otherbutton, otherbutton etc]), #screen_list[1]
           Screen(etc

...
while True : #main loop
...
  if(event.type is MOUSEBUTTONDOWN):
     pos = pygame.mouse.get_pos()
     b = screen_list[screenMode].check(pos)
     # depending on what you want to do, or whether you can just get buttons to run functions
  ...
  screen_list[screenMode].draw()
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Thu Dec 18, 2014 8:56 am

cool, ill have to crack (i wana get this sorted before xmas) then i can spend a few days in front of computer. How would you add that to multi screen like my screen 3 and screen 32?

or are you saying create a main screen and then lay over the mainscreen?

i have uploaded i recent verison of my code that works but no clickable button.

thank you for your time and patients with me hopefully its starting to sink in lol

Code: Select all

#! /usr/bin/env python
import pygame, sys
import time, sys
from pygame.locals import *
import RPi.GPIO as GPIO

pygame.init()

global screenMode
screenMode = 3

white = (255,255,255)
screen = pygame.display.set_mode((320,240)) # screen size

pygame.display.flip()

GPIO.setmode( GPIO.BCM )
GPIO.setup( 4 , GPIO.OUT)
GPIO.setup( 18 , GPIO.OUT)


def Screen3():      # Main Screen
  screen.fill(white)
  override = pygame.image.load("icons/override.png") #### override icon
  users = pygame.image.load("icons/users.png")   #### users icon
  screen.blit(override,(5,10))       #### override position
  screen.blit(users,(165,10))       #### users position


def Screen32():      # Users page
  screen.fill(white)
  add = pygame.image.load("icons/add.png")
  back = pygame.image.load("icons/back.png")          ##### back icon
  delete2 = pygame.image.load("icons/delete2.png")
  screen.blit(add,(5,190)) # button position
  screen.blit(back,(210,5))                             ###### back position
  screen.blit(delete2,(210,190))
  screen.blit(label,(10,5))
  screen.blit(no1,(22,70))
  screen.blit(no2,(170,70))
  screen.blit(no3,(10,140))
  screen.blit(no4,(170,140))


while True : #main loop

  if screenMode == 3:
    Screen3()
    if(event.type is MOUSEBUTTONDOWN):
     pos = pygame.mouse.get_pos()
        if button == 'users': screenMode = 32   
                                 # if users button pressed goes to screenMode 32

        if button == 'override': GPIO.output( 4 ,True) and (18, true)   
                               # if override button pressed turns on gpio 4 and 18


   if screenMode ==32
    Screen32()
     if (event.type is MOUSEBUTTONDOWN):
      pos = pygame.mouse.get_pos()
      if button == 'back': screenMode  = 3               
                              # if back button pressed go to screenMode 3


for event in pygame.event.get() :
  if event.type == QUIT :
     pygame.quit()
     sys.exit()
pygame.display.update()

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: problem with buttons :(

Thu Dec 18, 2014 9:27 am

er.. How familiar are you with object oriented style of programming? This is where a 'class' is defined and then objects are created as 'instances' of this class. I think this is the best approach in your case, however if these are new ideas to you I would suggest you run through a few tutorials first. google around but http://en.wikibooks.org/wiki/A_Beginner ... al/Classes http://www.tutorialspoint.com/python/py ... bjects.htm

In my sketch I use a list of screens accessed later as screen_list[0] screen_list[1] etc. If you want to give them more meaningful indices then you could use a dict.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Wed Jan 14, 2015 7:08 pm

Hey guys i was massively ill over xmas so didnt get much done, and reading and trying to learn code while drinking cough med aint good for you.

this is my latest code but still not clicking over to 32, which screen 3 is mainscreen and screen 32 is a users screen.

any chance of some help guys please.

Code: Select all

#! /usr/bin/env python
import pygame, sys
import time, sys
from pygame.locals import *

pygame.init()

global screenMode
screenMode = 1

white = (255,255,255)
screen = pygame.display.set_mode((320,240)) #screen size

pygame.display.flip()

def selected(rect, pos): # button reaction
  x1 = rect[0]
  y1 = rect[1]
  x2 = x1 + rect[2] - 1
  y2 = y1 + rect[3] - 1
  if ((pos[0] >= x1) and (pos[0] <= x2) and
      (pos[1] >= y1) and (pos[1] <= y2)):
    return True
  return False

def Screen1():		# Logo
	screen.fill(white)
	logo = pygame.image.load("icons/logo.png")
	screen.blit(logo,(25,75)) # button position
	pygame.display.update()
	time.sleep(5)

def Screen3():		# Main Screen
	screen.fill(white)
	override = pygame.image.load("icons/override.png")# button images
	users = pygame.image.load("icons/users.png")
	changepin = pygame.image.load("icons/changepin.png")
	settings = pygame.image.load("icons/settings.png")
	screen.blit(override,(5,10))# button position
	screen.blit(users,(165,10))
	screen.blit(changepin,(5,120))
	screen.blit(settings,(165,120))

def Screen32():		# Users
	screen.fill(white)
	add = pygame.image.load("icons/add.png")
	back = pygame.image.load("icons/back.png")
	delete2 = pygame.image.load("icons/delete2.png")
	screen.blit(add,(5,190)) # button position
	screen.blit(back,(210,5))
	screen.blit(delete2,(210,190))
	screen.blit(label,(10,5))
	screen.blit(no1,(22,70))
	screen.blit(no2,(170,70))
	screen.blit(no3,(10,140))
	screen.blit(no4,(170,140))

while True : #main loop
	if screenMode == 1:
		Screen1()
		screenMode = 3

	elif screenMode == 3:
		Screen3()
		if event.type == pygame.MOUSEBUTTONDOWN:
			screenMode = 32 

	for event in pygame.event.get() :
		if event.type == QUIT :
			pygame.quit()
			sys.exit()
	pygame.display.update()

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: problem with buttons :(

Wed Jan 14, 2015 8:01 pm

Hi, sorry to hear you were so poorly, hope you're much better.

Not an entirely helpful comment (in the short term) but I have to reiterate my suggestion about getting to grips with classes etc. It might be frustrating not to get to grips with the project but it will pay dividends in the long run.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

gordon77
Posts: 5036
Joined: Sun Aug 05, 2012 3:12 pm

Re: problem with buttons :(

Wed Jan 14, 2015 8:12 pm

You don't appear to be calling def screen32()

Code: Select all

elif screenMode == 3:
      Screen3()
      if event.type == pygame.MOUSEBUTTONDOWN:
         screenMode = 32
         Screen32() 

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Wed Jan 14, 2015 8:22 pm

hey i found this code on the net basic button function, button 2 and 3 only print. but i managed to get screen 3 up for a split second how do i get it to change to screen3() and stay there

code is the same but using basic buttons but ideally want to use images instead

Code: Select all

#! /usr/bin/env python
import pygame, sys
import time, sys
from pygame.locals import *

pygame.init()

global screenMode
screenMode = 3

white = (255,255,255)
Screen3 = pygame.display.set_mode((320,240)) #screen size

def Screen3():		# Main Screen
	screen.fill(white)
	override = pygame.image.load("icons/override.png")# button images
	users = pygame.image.load("icons/users.png")
	changepin = pygame.image.load("icons/changepin.png")
	settings = pygame.image.load("icons/settings.png")
	screen.blit(override,(5,10))# button position
	screen.blit(users,(165,10))
	screen.blit(changepin,(5,120))
	screen.blit(settings,(165,120))
	pygame.display.update()

class Button:
   def __init__(self, text):
      self.text = text
      self.is_hover = False
      self.default_color = (100,100,100)
      self.hover_color = (255,255,255)
      self.font_color = (0,0,0)
      self.obj = None
      
   def label(self):
      '''button label font'''
      font = pygame.font.Font(None, 20)
      return font.render(self.text, 1, self.font_color)
      
   def color(self):
      '''change color when hovering'''
      if self.is_hover:
         return self.hover_color
      else:
         return self.default_color
         
   def draw(self, screen, mouse, rectcoord, labelcoord):
      '''create rect obj, draw, and change color based on input'''
      self.obj  = pygame.draw.rect(screen, self.color(), rectcoord)
      screen.blit(self.label(), labelcoord)
      
      #change color if mouse over button
      self.check_hover(mouse)
      
   def check_hover(self, mouse):
      '''adjust is_hover value based on mouse over button - to change hover color'''
      if self.obj.collidepoint(mouse):
         self.is_hover = True 
      else:
         self.is_hover = False
         
if __name__ == '__main__':

         
   btn = Button('Button 1')
   btn2 = Button('Button 2')
   btn3 = Button('Button 3')
   screen = pygame.display.set_mode((600,400))
   
   run = True
   while run:
      screen.fill((0,0,0))
      mouse = pygame.mouse.get_pos()
      
      btn.draw(screen, mouse, (100,100,100,20), (125,103))
      btn2.draw(screen, mouse, (100,130,100,20), (125,133))
      btn3.draw(screen, mouse, (100,160,100,20), (125,163))
      #btn.check_hover(mouse)

      for event in pygame.event.get():
         if event.type == pygame.QUIT:
            run = False
         elif event.type == pygame.MOUSEBUTTONDOWN:
            if btn.obj.collidepoint(mouse):
               Screen3()
            elif btn2.obj.collidepoint(mouse):
               print('button 2 clicked')
            elif btn3.obj.collidepoint(mouse):
               print('button 3 clicked')
      
      pygame.display.update()
      

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Wed Jan 14, 2015 8:25 pm

gordon yes i only want screen32 to be called when "users button" is pressed, but only seems to be a icon with no function.

btw thank to gordon and paddy for being patient with me

leejohnson
Posts: 43
Joined: Sun Sep 28, 2014 7:01 pm

Re: problem with buttons :(

Sat Jan 17, 2015 8:14 am

just an update, i took and worked on that last piece and classed a button, then overlaid the screen with my images and it works :) so happy thank you for yourhelp.

next challenge i need to over come is when button 1 is pressed show number 1 in a box, like a pin code. so will have 4 numbers in totals selection from 10 numbers 0,1,2,3,4,5,6,7,8,9. and 4 will show in the box. any clues ? im still yet to google it

Return to “Python”