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.
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()
i want to b able to draw only in the white area (the recangle area) for example if your trying to draw behind the buttons or over the label it wont draw. is it possible? i need it for my project in school, i need to be able to draw only in the white area so the paint wont cover the label for example or not to be able drawing under the buttons
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Rectangle, Line
from kivy.uix.stencilview import StencilView
from kivy.core.window import Window
import socket
import sys
import os
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from functools import partial
class MyPaintWidget(Widget):
lineSize = 5
def on_touch_down(self, touch):
with self.canvas:
touch.ud['Line'] = Line(points=(touch.x, touch.y), width=self.lineSize)
def on_touch_move(self, touch):
touch.ud['Line'].points += [touch.x, touch.y]
class MyPaintApp(App):
def build(self):
self.parent = Widget()
self.painter=MyPaintWidget(size=(695,510),pos=(100,50))
with self.painter.canvas:
Rectangle(pos=(100,50), size=(695,510))
with open("Send_word.txt",'r') as fr:
word_lable = Label(text = "Your word is " + fr.read(),font_size='30sp',pos = (400,530))
self.parent.add_widget(word_lable)
finishbtn = Button(text='finish',pos=(0, 0),size = (100,150))#finish button position and text
finishbtn.bind(on_release=self.finish)#finish button onclick
erasebtn = Button(text = "Erasor",pos=(0,150),size =(100,150))#erasor button position and text
erasebtn.bind(on_release=self.black)
redbtn = Button(text = "Red",background_color=(255,0,0,1.0),pos=(100, 0), size=(100,50))
redbtn.bind(on_release=self.red)
bluebtn = Button(text = "Blue",background_color=(0,0,255,1.0),pos=(200, 0), size=(100,50))
bluebtn.bind(on_release=self.blue)
greenbtn = Button(text = "Green",background_color=(0,255,0,1.0),pos=(300, 0), size=(100,50))
greenbtn.bind(on_release=self.green)
whitebtn = Button(text = "Black",pos=(400, 0), size=(100,50))
whitebtn.bind(on_release=self.white)
yellowbtn = Button(text = "Yellow",background_color=(255,255,0,1.0),pos=(500, 0), size=(100,50))
yellowbtn.bind(on_release=self.yellow)
lightbluebtn = Button(text = "L.Blue",background_color=(0,255,255,1.0),pos=(600, 0), size=(100,50))
lightbluebtn.bind(on_release=self.lightblue)
purplebtn = Button(text = "Purple", size=(100,50),background_color=(148,0,211,1.0),pos=(700,0))
purplebtn.bind(on_release=self.purple)
sizeupbtn = Button(text = "SizeUp",pos=(0, 300),size = (100,150))
sizeupbtn.bind(on_release=self.SizeUp)
sizedowmbtn = Button(text = "SizeDown",pos=(0, 450),size = (100,150))
sizedowmbtn.bind(on_release=self.SizeDown)
self.parent.add_widget(self.painter)
#self.parent.add_widget(word_lable())
self.parent.add_widget(finishbtn)
self.parent.add_widget(redbtn)
self.parent.add_widget(bluebtn)
self.parent.add_widget(greenbtn)
self.parent.add_widget(whitebtn)
self.parent.add_widget(yellowbtn)
self.parent.add_widget(erasebtn)
self.parent.add_widget(lightbluebtn)
self.parent.add_widget(purplebtn)
self.parent.add_widget(sizeupbtn)
self.parent.add_widget(sizedowmbtn)
return self.parent
def finish(self,obj):
self.painter.export_to_png("screenshot.png")
sexi = open("Send_word.txt",'r').read()
print repr(sexi)
send_file(sexi)
def red(self,obj):
with self.painter.canvas:
Color(1,0,0)
def blue(self,obj):
with self.painter.canvas:
Color(0,0,1)
def green(self,obj):
with self.painter.canvas:
Color(0,1,0)
def white(self,obj):
with self.painter.canvas:
Color(0,0,0)
def yellow(self,obj):
with self.painter.canvas:
Color(1,1,0)
def black(self,obj):
with self.painter.canvas:
Color(1,1,1)
def lightblue(self,obj):
with self.painter.canvas:
Color(0,1,1)
def purple(self,obj):
with self.painter.canvas:
Color(1,0,1)
def SizeUp(self,obj):
if(self.painter.lineSize <100):
self.painter.lineSize += 5
def SizeDown(self,obj):
if(self.painter.lineSize >1):
self.painter.lineSize -= 5
if __name__ == '__main__':
MyPaintApp().run()
You can do that the easy way and the hard way. The easy way is using StencilView as a widget, which has a nice demo.
The harder way is using the Stencil directly and target only specific areas of the widget's canvas.
I want to use kivy scatter in order to resize the widgets which scatter contains. So, I created box_total contained in scatter, contained in floatlayout.
This is the code:
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class TutorialApp(App):
def build(self):
b = BoxLayout(orientation='vertical')
button = Button(text = 'something')
b.add_widget(button)
box_labels = BoxLayout(orientation = 'horizontal')
label1 = Label(text = 'hello')
box_labels.add_widget(label1)
label2 = Label(text = 'world')
box_labels.add_widget(label2)
box_buttons = BoxLayout(orientation = 'horizontal')
button1 = Button(text = 'hello')
box_buttons.add_widget(button1)
button2 = Button(text = 'world')
box_buttons.add_widget(button2)
box_total = BoxLayout(orientation = 'vertical')
box_total.add_widget(box_labels)
box_total.add_widget(box_buttons)
f = FloatLayout()
s = Scatter()
f.add_widget(s)
s.add_widget(box_total)
b.add_widget(f)
return b
if __name__ == "__main__":
TutorialApp().run()
and this is what I get:
How can I resize the inner widget box_total in order to occupy the whole FloatLayout area? (the bottom half of the window)
Scatter isn't a layout, therefore the automatical setting of the position won't work here. Use ScatterLayout to behava like both a Scatter and a FloatLayout.
from kivy.uix.scatterlayout import ScatterLayout
ScatterLayout()
Or do that manually with setting the positions of the widgets inside the FloatLayout, but remember you'll need to do size_hint=(None, None) first.
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