I know this question may have been asked already, but I am a beginner to Kivy, so I would like for someone to explain how to put two buttons on the same screen.
The problem is I try to return the button variable, and it works. However, when I try to return two at the same time, it will give me an error.
here is my code:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from functools import partial
class App(App):
def com1(self, instance, *args):
label1 = Label(text = "Hi")
return label1
def com2(self, instance, *args):
label = Label(text= "Bye")
def build(self):
button1 = Button(text = "Hi", size_hint = (0.25, 0.18), pos = (350, 100))
button1.bind(on_press=partial(self.com1, button1))
button2 = Button(text = "Bye", size_hint = (0.25, 0.18), pos = (350, 200))
button2.bind(on_press=partial(self.com2, button2))
return button1, button2
App().run()
The build method must return a single widget, so depending on how you want the buttons to be arranged you have several options such as BoxLayout, RelativeLayout, FloatLayout, etc. In this case for simplicity I will use a BoxLayout:
# ...
from kivy.uix.boxlayout import BoxLayout
# ...
class App(App):
# ...
def build(self):
button1 = Button(text="Hi", size_hint=(0.25, 0.18), pos=(350, 100))
button1.bind(on_press=partial(self.com1, button1))
button2 = Button(text="Bye", size_hint=(0.25, 0.18), pos=(350, 200))
button2.bind(on_press=partial(self.com2, button2))
boxlayout = BoxLayout()
boxlayout.add_widget(button1)
boxlayout.add_widget(button2)
return boxlayout
# ...
Related
I am new to Kivy and I am sort of stuck. I am using GridLayout to make my app and I am having some trouble putting a video in my background. The code I will post makes an app with a black background. How do I replace the black background with a video, particularly mp4. I would also like to make the video darker if possible. I wanted to use AnchorPoint but I am not quite sure how to put both in there. Any help will be appreciated.
from kivy.app import App
from kivy.uix.video import Video
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class MZ_Invest(App):
def build(self):
self.root_layout = FloatLayout()
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.6,0.7)
self.window.pos_hint = {"center_x":0.5, "center_y":0.5}
#add widgets
#Video
video = Video(source='birds.mp4', state='play')
video.opacity = 0.5
#Image
self.window.add_widget(Image(
source="mzi.png",
size_hint = (1.5,1.5)
))
#Label
self.greeting = Label(
text="How much would you like to invest?",
font_size = 18,
color='90EE90'
)
self.window.add_widget(self.greeting)
#User Input
self.user = TextInput(
multiline=False,
padding_y= (20,20),
size_hint = (1, 0.5)
)
self.window.add_widget(self.user)
#Button
self.button = Button(
text="Submit",
size_hint = (1,0.5),
bold = True,
background_color = '90EE90',
)
self.button.bind(on_press=self.callback)
self.window.add_widget(self.button)
#self.root_layout.add_widget(video)
self.root_layout.add_widget(self.window)
return self.root_layout
def callback(self, instance):
if self.user.text.isnumeric() and int(self.user.text) >= 10000:
self.greeting.text = "Calculating: $" + self.user.text
self.greeting.color = '90EE90'
else:
self.greeting.text = "Invalid"
self.greeting.color = "#FF0000"
if __name__ == "__main__":
MZ_Invest().run()
Most Kivy widgets have a transparent background, so you can just display a video and then display your GUI over that. Try adding something like this at the end of your build() method:
self.root_layout = FloatLayout()
video = Video(source='BigBuckBunny.mp4', state='play')
video.opacity = 0.5 # adjust to make the video lighter/darker
self.root_layout.add_widget(video) # add the video first
self.root_layout.add_widget(self.window) # now add the GUI window so it will be drawn over the video
return self.root_layout # return the root_layout instead of the window
I wanted to remove the 'bl' widget by clicking the 'horny mode' button, but it is not initially on the screen. How can I make the widget be removing by clicking on the button?
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.image import Image
from kivy.uix.widget import Widget
class ScraperApp(App, FloatLayout):
def PhotGif(self):
wentil = Image(source='img.gif', size_hint = (.5, .5), anim_loop = 99999)
photo = AnchorLayout(anchor_x='center', anchor_y='top', padding = [0, 75, 0, 0])
photo.add_widget(wentil)
return photo
def build(self):
bl = BoxLayout(orientation='horizontal', padding = [50, 100, 50, 150], spacing = 5)
bl.add_widget( Button(text = '1', on_press = self.first, font_size = 20, size_hint = (.3, .1)))
bl.add_widget( Button(text = '2', on_press = self.second, font_size = 20, size_hint = (.3, .1)))
#bl.add_widget( Button(text = 'Wallpaper mode', on_press = self.wallpaper, font_size = 20, size_hint = (.3, .1)))
wid = FloatLayout()
wid.add_widget(ScraperApp().PhotGif())
wid.add_widget(bl)
return wid
def first(self, instance):
print('Horny mode')
instance.text = 'кнопка нажата'
ScraperApp().build().remove_widget(bl)
stop()
def stop():
ScraperApp().build().remove_widget(bl)
def second(self, instance):
print('Soft mode')
instance.text = 'кнопка нажата'
if __name__ == '__main__':
ScraperApp().run()
Can you help me make so that when you click on any button, the widget with the buttons removed?
First, save a reference to the widget that you want to remove:
def build(self):
self.bl = BoxLayout(orientation='horizontal', padding=[50, 100, 50, 150], spacing=5)
self.bl.add_widget(Button(text='1', on_press=self.first, font_size=20, size_hint=(.3, .1)))
self.bl.add_widget(Button(text='2', on_press=self.second, font_size=20, size_hint=(.3, .1)))
# self.bl.add_widget( Button(text = 'Wallpaper mode', on_press = self.wallpaper, font_size = 20, size_hint = (.3, .1)))
wid = FloatLayout()
wid.add_widget(ScraperApp().PhotGif())
wid.add_widget(self.bl)
return wid
Then modify the first() method to remove it:
def first(self, instance):
print('Horny mode')
instance.text = 'кнопка нажата'
self.root.remove_widget(self.bl)
self.stop()
Note that the code:
ScraperApp().build().remove_widget(bl)
creates a new instance of the ScaperApp and tried to remove bl from that instance. Aside from other problems, nothing you do to that new instance will affect the instance that is currntly running.
I have a question that i can't seem to find an anwser.
I have this label:
l = Label(text='Some Text', font_size=100)
I have also binded text input to 'l' that looks like this:
t = TextInput(font_size=80, size_hint_y=None, height=200, text='Time', halign='right')
t.bind(text=l.setter('text'))
So when i type something to my text input box, it instantly updates the label and shows result on screen.
But i want to update that text only when user presses 'Add' button.
I am new to kivy and i am still experiment with it.
Any help would be great.
Thanks!
#edit here is my code:
https://gist.githubusercontent.com/Gacut/d765231c2696831af8c8a3315fdabbfd/raw/e1bdcdd8aca588b1c9268e76f7a47fa7576d54cb/gistfile1.txt
and what i am trying to do, is this kind of app, but for android:
https://wumpa.app/
The
t.bind(text=l.setter('text'))
will do exactly what you describe, so that is not what you want. Instead, use the Button on_release property to call a method that does what you want. The simplest way to do that is to save references to the Widgets involved (t and lista), and use those references in the new method. Like this:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
class WumpaTime(App):
def build(self):
layout = BoxLayout(orientation='vertical')
title = Label(text='Wumpa Time Countdown', size_hint_y=None, height=100, )
self.t = TextInput(font_size=80, size_hint_y=None, height=200, halign='right')
self.lista = Label(font_size=100)
box = BoxLayout()
box2 = BoxLayout()
bremove = Button(text="Remove", size_hint=(None, None), size=(100, 100))
badd = Button(text="Add", size_hint=(None, None), size=(100, 200), on_release=self.update_label)
#t.bind(text=lista.setter('text'))
box.add_widget(self.t)
box.add_widget(badd)
layout.add_widget(title)
layout.add_widget(self.lista)
layout.add_widget(box)
return layout
def update_label(self, button_instance):
self.lista.text = self.t.text
WumpaTime().run()
I'm trying to output text from button presses and add it to a textbox each time it's pressed as well as delete the text when the delete button is pressed - in normal python.
I've been trying to use kivy.uix.textinput, but I'm not sure on how to output the value from the buttons as well as delete it.
This is what I've done so far.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name='code_screen')
main_grid_lay = GridLayout(cols=2,cols_minimum={0:640, 1:175})
self.add_widget(main_grid_lay)
#Code ouput display
display_code = TextInput(text='Code!', readonly = True, id=output)
main_grid_lay.add_widget(display_code)
#Options Buttons
box_lay = BoxLayout(orientation='vertical')
main_grid_lay.add_widget(box_lay)
delete_button = Button(
text='Delete',
size_hint_x= None,
width=160,
id='' #unsure on how to delete
)
box_lay.add_widget(delete_button)
base_left = Button(
text='Base Left',
#on_release= b_left(),
#id='left',
)
base_right = Button(
text='Base Right',
on_release=self.degree_popup,
#on_release= b_right(),
)
#b_left = self.ids.output.text='left'
#b_left = self.ids.output.text='right'
box_lay.add_widget(base_left)
box_lay.add_widget(base_right)
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == '__main__':
MyMain().run()
It currently sends an error and is probably because of the ids. Not fully sure how ids work without using kv language. Any help is appreciated.
The id only makes sense in .kv, in python they are useless. In this case the solution is to access the objects in the methods connected to on_release but for this they must be class attributes.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name="code_screen")
self.display_code = TextInput(text="Code!", readonly=True)
self.delete_button = Button(
text="Delete", size_hint_x=None, width=160, on_release=self.delete_clicked
)
self.base_left = Button(text="Base Left", on_release=self.left_clicked)
self.base_right = Button(text="Base Right", on_release=self.right_clicked)
main_grid_lay = GridLayout(cols=2, cols_minimum={0: 640, 1: 175})
main_grid_lay.add_widget(self.display_code)
self.add_widget(main_grid_lay)
box_lay = BoxLayout(orientation="vertical")
box_lay.add_widget(self.delete_button)
main_grid_lay.add_widget(box_lay)
box_lay.add_widget(self.base_left)
box_lay.add_widget(self.base_right)
def delete_clicked(self, instance):
self.display_code.text = ""
def left_clicked(self, instance):
self.display_code.text += "left"
def right_clicked(self, instance):
self.display_code.text += "right"
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == "__main__":
MyMain().run()
Following code opens window with label on top and label turns to textinput once you click on it.
But, once you start typing and insert first key (any key), text gets shortened, and you lose part of the text suddenly. For example: you click on label > textinput appears > you type '1' > text becomes 'Press here and then try 1'.
How to change below code to stop text disappearing?
import kivy
kivy.require('1.10.1')
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.base import runTouchApp
from kivy.properties import BooleanProperty, ObjectProperty
#https://github.com/kivy/kivy/wiki/Editable-Label
class EditableLabel(Label):
edit = BooleanProperty(False)
textinput = ObjectProperty(None, allownone=True)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos) and not self.edit:
self.edit = True
return super(EditableLabel, self).on_touch_down(touch)
def on_edit(self, instance, value):
if not value:
if self.textinput:
self.remove_widget(self.textinput)
return
self.textinput = t = TextInput(
text=self.text, size_hint=(None, None),
font_size=self.font_size, font_name=self.font_name,
pos=self.pos, size=self.size, multiline=False)
self.bind(pos=t.setter('pos'), size=t.setter('size'))
self.add_widget(self.textinput)
t.bind(on_text_validate=self.on_text_validate, focus=self.on_text_focus)
def on_text_validate(self, instance):
self.text = instance.text
self.edit = False
def on_text_focus(self, instance, focus):
if focus is False:
self.text = instance.text
self.edit = False
if __name__ == '__main__':
root = FloatLayout()
lbl = 'Press here and then try to edit (type a character), but text gets shortened suddenly.'
label = EditableLabel(text=lbl, size_hint_y=None, height=50, pos_hint={'top': 1})
root.add_widget(label)
runTouchApp(root)
According to the docs:
The selection is automatically updated when the cursor position changes. You can get the currently selected text from the TextInput.selection_text property.
and in your case when you click on the Label and appear in TextInput the cursor changes position so a text is selected. And when a text is selected and you write something it is replaced, that's why the text disappears.
The solution is to clean the selection:
from kivy.clock import Clock
class EditableLabel(Label):
[...]
def on_edit(self, instance, value):
if not value:
if self.textinput:
self.remove_widget(self.textinput)
return
self.textinput = t = TextInput(
text=self.text, size_hint=(None, None),
font_size=self.font_size, font_name=self.font_name,
pos=self.pos, size=self.size, multiline=False)
self.bind(pos=t.setter('pos'), size=t.setter('size'))
self.add_widget(self.textinput)
t.bind(on_text_validate=self.on_text_validate, focus=self.on_text_focus)
Clock.schedule_once(lambda dt: self.textinput.cancel_selection())