how to Change colour of a particular button in gridLayout in kivy - python

I am trying to make tambola coin picker with Python and Kivy and I am new to kivy.
Here, I created gridlayout buttons from 1 to 90. I want to change the color of particular button in gridlayout when its number is picked. I am facing issues to update gridlayout with new colored button. Here I am attaching my code. screenshot
#!/usr/bin/python
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color
import random
coins = random.sample(range(1,91), 90)
#print(coins)
picked_coins=[]
current_coin=0
#print(picked_coins)
class Housie(FloatLayout):
def __init__(self,**kwargs):
super(Housie,self).__init__(**kwargs)
self.title = Label(text="Housie Coin Picker",font_size = 50,size_hint=(1, .55),pos_hint={'x':0, 'y':.45})
self.main_label = Label(text = "Click PICK NUMBER", size_hint=(1, .60),pos_hint={'x':0, 'y':.35})
self.picked_ones = Label(text = "picked_coins", size_hint=(1, .40),pos_hint={'x':0, 'y':.40})
self.help_button = Button(text = "PICK NUMBER", size_hint=(.3, .1),pos_hint={'x':.65, 'y':.1},on_press = self.update)
self.add_widget(self.title)
self.add_widget(self.main_label)
self.add_widget(self.picked_ones)
self.add_widget(self.help_button)
self.add_widget(self.userinterface())
def userinterface(self):
self.layout = GridLayout(cols = 10,size_hint=(.50, .50))
for i in range(1,91):
self.layout.add_widget(Button(background_color=(1,0,0,1),text =str(i)))
return self.layout
def update(self,event):
for coin in coins:
if coin not in picked_coins:
current_coin=coin
picked_coins.append(coin)
self.main_label.text = str(coin)
for i in self.layout.children:
if i.text == str(coin):
#What to do Here?
break
self.picked_ones.text = "Picked coins = {}".format(" ".join(str(sorted(picked_coins))))
class app1(App):
def build(self):
return Housie()
if __name__=="__main__":
app1().run()

You can bind a method to each Button like this:
def userinterface(self):
self.layout = GridLayout(cols = 10,size_hint=(.50, .50))
for i in range(1,91):
self.layout.add_widget(Button(background_color=(1,0,0,1),text=str(i), on_release=self.butt_pressed))
return self.layout
def butt_pressed(self, button):
button.background_normal = ''
button.background_color = (1,0,0,1)
Th butt_pressed() method changes the background color of the pessed Button.

Related

The Screen Manager is not returning Desired Output in Kivy Python

There is no such error shown in the Python output shell.
What I want is that , the first page should be the Login page or as here, the "ConnectingPage" then Welcome Should Be shown, and then at last a Set of buttons named from 0 to 99 be shown.
Here is the code :
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen, FallOutTransition
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.core.window import Window
class ConnectingPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text = "Usename:"))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text = "Password:"))
self.password = TextInput(multiline=False,password = True)
self.add_widget(self.password)
self.joinbutton = Button(text="Join")
self.joinbutton.bind(on_release = self.click_join_button)
self.add_widget(Label())
self.add_widget(self.joinbutton)
def click_join_button(self, instance):
username = self.username.text
password = self.password.text
#if username == "venu gopal" and password == "venjar":
MyApp.screen_manager.current = "Info"
MyApp.screen_manager.current = "Chat"
class InfoPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.message = Label(text = "welcome",halign="center", valign="middle", font_size=30)
self.add_widget(self.message)
class SomeApp(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
# Make sure the height is such that there is something to scroll.
layout.bind(minimum_height=layout.setter('height'))
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
root = ScrollView(size_hint=(1, None), size=(Window.width, Window.height))
root.add_widget(layout)
if __name__ == "__main__":
runTouchApp(root)
class MyApp(App):
screen_manager = ScreenManager(transition=FallOutTransition(duration=2)) # this make screen_manager a class vaiable
def build(self):
# self.screen_manager = ScreenManager()
self.connecting_page = ConnectingPage()
screen = Screen(name='Connect')
screen.add_widget(self.connecting_page)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# Info page
self.info_page = InfoPage()
screen = Screen(name='Info')
screen.add_widget(self.info_page)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# Chat App
self.chat_app = SomeApp()
screen = Screen(name='Chat')
screen.add_widget(self.chat_app)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# return ConnectingPage()
return self.screen_manager
if __name__ == "__main__":
MyApp().run()
The Problem is that: the set of Buttons are getting shown in the start. When the Cross is pressed to close the kivy window, then the Login page is shown and then "welcome" and then the buttons again.
I want It to show from the second Step.
What I believe is that the "line 61" in the code is making a problem. When the code is run it first shows the buttons and so on.
Please Help me find the solution for the above Problem.
Your __init__() method of the SomeApp class starts an App running with the lines:
if __name__ == "__main__":
runTouchApp(root)
and that runTouchApp() does not return until that App completes. So when you run your code, it stops a the line:
self.chat_app = SomeApp()
To fix that, just replace:
if __name__ == "__main__":
runTouchApp(root)
with:
self.add_widget(root)

Kivy - Cannot keep focus in TextInput after submiting, Enter key does not confirm it

So i manage to get focus in the TextInput > tracknumb. at start of the app, but still when i confirm the input, finally i can do it with enter now too, but it looses the focus from textinput once i submit it.
Can you please advice what am I missing?
Whole Code here
import kivy
import kivy
import mysql.connector
from datetime import datetime
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.image import Image
from kivy.core.audio import SoundLoader
from kivy.core.window import Window
from kivy.clock import Clock
Window.size = (480, 800)
class MyGrid(GridLayout):
def __init__(self, **kwargs):
super(MyGrid, self).__init__(**kwargs)
self.cols = 1 # Set columns for main layout
self.inside = GridLayout(cols=2, row_force_default=True,
row_default_height=50, padding=20,
spacing=10) # Create a new grid layout
self.add_widget(Label(text="Tracking Number \n Checker", halign="center", font_size=40)) # Top Label
self.inside.add_widget(Label(text="Work Number:", halign="center", font_size=20)) # Add a label widget
self.worknumb = TextInput(text_validate_unfocus=True, multiline=False, font_size=20, halign="center")
self.inside.add_widget(self.worknumb)
self.inside.add_widget(Label(text="Tracking \nNO. Scan:", halign="center", font_size=20))
self.tracknumb = TextInput(multiline=False, font_size=15, halign="center") # Create a Text input box stored in the name variable
self.inside.add_widget(self.tracknumb) # Add the text input widget to the GUI
self.add_widget(self.inside) # Add the interior layout to the main
self.submit = Button(text="Submit", font_size=40, size_hint =(.5, .5)) # Submit button
self.add_widget(self.submit)
self.submit.bind(on_press=self.send_tracknumb)
self.resultbox = Image(source="status.png") #image box on bottom
self.add_widget(self.resultbox)
Window.bind(on_key_down=self.pressed)
Clock.schedule_once(self.focus_tracknumb, 1)
def pressed(self, instance, keyboard, keycode, text, modifiers):
if keycode == 40 or keycode == 13:
self.send_tracknumb(None)
def focus_tracknumb(self, _):
self.tracknumb.focus = True
def send_tracknumb(self, _):
tracknumb = self.tracknumb.text
worknumb = self.worknumb.text
errorsound = SoundLoader.load("incorrect.mp3") # add sound to the scanning
correctsound = SoundLoader.load("correct.ogg")
self.tracknumb.text = "" # Reset text to blank in each text input
I think you can change focus back to the TextInput in the pressed() method:
def pressed(self, instance):
tracknumb = self.tracknumb.text
worknumb = self.worknumb.text
errorsound = SoundLoader.load("incorrect.mp3") #add sound to the scanning
correctsound = SoundLoader.load("correct.ogg")
self.tracknumb.text = "" # Reset text to blank in each text input
self.tracknumb.focus = True # Change focus back to tracknumb
Och dong, I missed it :D it was so simple, I had to put the function to that part
def send_tracknumb(self, _):
I missed that one in all the text :{
Clock.schedule_once(self.focus_tracknumb, 0.1)

I can't get Kivy's button function to work

This is what it looks like when i run it, which is what i want except the flip button does nothingI have tried many fixes for other people but none worked so I am uploading my work in hopes that someone can help me. If you can please comment but you will likely have to put things in the simplest way possible as I don't have a lot of knowledge.
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.button import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
class Shark(App):
def build(self):
self.max_food = 50
self.food = self.max_food
self.respect = 0
self.layout = BoxLayout(orientation="vertical")
area1 = BoxLayout(orientation="horizontal")
area2 = BoxLayout(orientation="horizontal")
area3 = BoxLayout(orientation="horizontal")
self.layout.add_widget(area1)
self.layout.add_widget(area2)
self.layout.add_widget(area3)
self.lbl1 = Label(text="{}/{} Food".format(self.food, self.max_food))
self.lbl2 = Label(text="{} Respect".format(self.respect))
area1.add_widget(self.lbl1)
area1.add_widget(self.lbl2)
btn1 = Button(text="Area 1")
btn2 = Button(text="Area 2")
area2.add_widget(btn1)
area2.add_widget(btn2)
btn3 = Button(text="Eat")
btn4 = Button(text="Flip")
btn4.bind(on_press=self.flip)
area3.add_widget(btn3)
area3.add_widget(btn4)
return self.layout
def eat(self):
pass
def flip(self, obj):
self.food -= 10
self.respect += 10
self.lbl1.text="{}/{} Food".format(self.food, self.max_food)
self.lbl2.text="{} Respect".format(self.respect)
Shark().run()
Change:
btn4.bind(on_push=self.flip)
To:
btn4.bind(on_press=self.flip)
I don't think on_push is a valid action.

Python Kivy - Adding a GridLayout to a BoxLayout

I want to create an UI with Buttons on top and a few Labels on bottom and if the labels exceeds the height it should be scrollable.
Something like this:
So far this is my code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
class MyApp(App):
main_layout = BoxLayout(orientation='vertical')
top_layout = BoxLayout(orientation='horizontal')
scrollView = ScrollView()
gridLayout = GridLayout()
gridLayout.cols = 1
gridLayout.minimum_height = 10
gridLayout.padding = [0, 0, 0, 0]
scrollView.add_widget(gridLayout)
main_layout.add_widget(top_layout)
main_layout.add_widget(scrollView)
def btn_create(self, instance):
self.gridLayout.add_widget(Label(text='test'))
def btn_edit(self, instance):
pass
def btn_delete(self, instance):
pass
def build(self):
self.top_layout.size_hint=(1, .1)
# Button 'Erstellen'
btnCreate = Button()
btnCreate.text = 'Erstellen'
btnCreate.bind(on_press=self.btn_create)
# Button 'Bearbeiten'
btnEdit = Button()
btnEdit.text = 'Bearbeiten'
btnEdit.bind(on_press=self.btn_edit)
# Button 'Löschen'
btnDelete = Button()
btnDelete.text = 'Löschen'
btnDelete.bind(on_press=self.btn_delete)
self.top_layout.add_widget(btnCreate)
self.top_layout.add_widget(btnEdit)
self.top_layout.add_widget(btnDelete)
return self.main_layout
if __name__ == '__main__':
MyApp().run()
I added a GridLayout to a ScrollView, but this doesn't seem to work.
How can i make a scrollable list?
You have to set the size_hint_y of the GridLayout to None so that the height does not depend on the ScrollView and the size is minimum equal to the size of the GridLayout. On the other hand the Label must have size_hint_y to None so that the height does not depend on the GridLayout.
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
class MyApp(App):
main_layout = BoxLayout(orientation='vertical')
top_layout = BoxLayout(orientation='horizontal')
scrollView = ScrollView()
gridLayout = GridLayout(size_hint_y=None)
gridLayout.cols = 1
gridLayout.padding = [0, 0, 0, 0]
gridLayout.bind(minimum_height=gridLayout.setter('height'))
scrollView.add_widget(gridLayout)
main_layout.add_widget(top_layout)
main_layout.add_widget(scrollView)
def btn_create(self, instance):
self.gridLayout.add_widget(Label(text='test', size_hint_y=None))
def btn_edit(self, instance):
pass
def btn_delete(self, instance):
pass
def build(self):
self.top_layout.size_hint=(1, .1)
# Button 'Erstellen'
btnCreate = Button()
btnCreate.text = 'Erstellen'
btnCreate.bind(on_press=self.btn_create)
# Button 'Bearbeiten'
btnEdit = Button()
btnEdit.text = 'Bearbeiten'
btnEdit.bind(on_press=self.btn_edit)
# Button 'Löschen'
btnDelete = Button()
btnDelete.text = 'Löschen'
btnDelete.bind(on_press=self.btn_delete)
self.top_layout.add_widget(btnCreate)
self.top_layout.add_widget(btnEdit)
self.top_layout.add_widget(btnDelete)
return self.main_layout
if __name__ == '__main__':
MyApp().run()

Get textinput value in Kivy app

New to Python/Kivy trying to build a test app with an input box, an ok button and a label that should change text when the ok button is clicked. But instead I get 'NameError: global name 'txt1' is not defined'. What am I doing wrong?
# import Kivy
import kivy
import random
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
# my app
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
lbl1 = Label(text="test")
layout.add_widget(lbl1)
txt1 = TextInput(text='', multiline=False)
layout.add_widget(txt1)
return layout
# button click function
def buttonClicked(self,btn):
lbl1.text = "You wrote " + txt1.text
# run app
if __name__ == "__main__":
MyApp().run()
Use self.txt1, self.lbl1 etc..
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
self.lbl1 = Label(text="test")
layout.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
layout.add_widget(self.txt1)
return layout
# button click function
def buttonClicked(self,btn):
self.lbl1.text = "You wrote " + self.txt1.text
# run app
if __name__ == "__main__":
MyApp().run()
# join all items in a list into 1 big string
Using:
def buttonClicked(self,btn):
lbl1.text = "You wrote " + txt1.text <- only exists in the build method

Categories