How to display text when Button is pressed on Kivy - python

I was wondering how I could make the button I've created on my platform using Kivy, display text when pressed. I want it to display text on the kivy window, not in my integrated terminal. So I was wondering if anyone could help me with that. I want it to display a random dare from my txt file that I have.
Here is my code:
Label:
text: "Truth or Dare?"
TextInput:
hint_text: "Two Things To Try: Truth or Dare"
Button:
text: "Generate"
on_press: #I dont know what to do here
ScrollView:
Label:
If anyone could help it would be greatly appreciated!

Actually i suggest you to use ScreenManager with kivy.So you can easily use Properties.
But for this solution you can use that:
from kivy.app import App
from kivy.lang import Builder
kv_string = """
#:import choice random.choice
BoxLayout:
orientation: 'vertical'
Label:
id: mylabel
text: "Truth or Dare?"
TextInput:
id: myinput
hint_text: "Two Things To Try: Truth or Dare"
Button:
text: "Generate"
on_release: root.ids.mylabel.text = choice(app.my_list)
"""
class MyApp(App):
def build(self):
with open('asd.txt', 'r') as mytxt:
self.my_list = mytxt.readlines()
return Builder.load_string(kv_string)
if __name__ == '__main__':
MyApp().run()

Related

Kivy: Function Call to Update Label Text in Another Class Not Working

I have a class called StatSummary that has labels and a button at the bottom called "Reset". When I press this button, a popup appears with a button that also says "Reset". When I press the popup "Reset" button, I want to update the labels' text of the class StatSummary. I created a method inside StatSummary called resetStatSummary which updates the labels' text using IDs.
However, when I call Factory.StatSummary().resetStatSummary() from ResetPopup, the labels on the screen do not update. This is especially confusing because I added a print statement in my Python file to see if the function runs and it does, but the labels' text does not update.
Python File:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.config import Config
from kivy.uix.popup import Popup
class StatSummary(Screen):
def resetStatSummary(self): # resets StatSummary text when "Reset" button is pressed
self.ids.summaryShotFractionLabel.text = "0/0"
self.ids.summaryShotPercentLabel.text = "0.0%"
self.ids.summaryLongStreakLabel.text = "Longest Streak: 0"
print("resetStatSummary ran")
class ResetPopup(Popup):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('basketball.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MainApp().run()
.kv File:
#:import Factory kivy.factory.Factory
WindowManager:
StatSummary
<StatSummary>
name: "statSummary"
GridLayout:
BoxLayout:
orientation: "vertical"
Label:
id: summaryShotFractionLabel
text: "0/0"
Label:
id: summaryShotPercentLabel
text: "0.0%"
BoxLayout:
orientation: "vertical"
Label:
id: summaryLongStreakLabel
text: "Longest Streak: 0"
BoxLayout:
orientation: "horizontal"
Button:
text: "Reset"
on_release:
Factory.ResetPopup().open()
<ResetPopup>:
title: "Wait..."
BoxLayout:
cols: 1
orientation: "vertical"
Label:
text: "Are you sure you want to reset?"
Button:
text: "Go back"
on_release:
root.dismiss()
Button:
text: "Reset"
on_release:
root.dismiss()
Factory.StatSummary().resetStatSummary()
app.root.current = "interact"
app.root.transition.direction = "right"
The label doesn't change because you call wrong object's resetStatSummary method.
Within reset's on_release button method you have:
Factory.StatSummary().resetStatSummary()
which means: create fresh new StatSummary object (StatSummary() will create and return new object - class StatSummary instance), then call it's method resetStatSummary(). So you call this method on brand new object, not this created by kv file. To access expected StatSummary class instance just replace line:
Factory.StatSummary().resetStatSummary()
with
app.root.get_screen('statSummary').resetStatSummary()

Kivy updating label when using function via button fails

I'm trying to build an App thats uses certain input Parameters and when hitting a submit button it uses a logic to generate output paramters. I managed to build the app and the input and the triggering via a submit button. Now i want to generate the output, for beginning with an easy logic. I looked up several similar solutions, but somehow they don't work for me.
For some reason my .kv file doen't get the updated value for the label text with the error: "ValueError: Label.text accept only str" Eventough everything is declared as a string in the .py. If i change it in the kv to str("...") I get some code line which i guess is the intern id of the attribute but not the assigned value i want to get.
I hope you can help. Pls don't be too harsh, I#M new to python and kivy...
main .py, shuldn't be part of the problem
Peenomat.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import LabelBase
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
#Layout
class Peenomat(AnchorLayout):
pass
class PeenomatApp(App):
def build(self):
return Peenomat()
if __name__=="__main__":
PeenomatApp().run()
.py with the classes and methods for the logic
StatusBar.py
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.app import App
class InputParameters(GridLayout):
verfahren = ObjectProperty(None)
def on_state(self, togglebutton):
tb = togglebutton
if tb.state == 'down':
self.verfahren = tb.text
self.verfahren = tb.text
print(self.verfahren)
return self.verfahren
class StatusBar(BoxLayout):
#InputGrößen
group_mode = False
prozess = ObjectProperty(None)
vorbehandlung = ObjectProperty(None)
material = ObjectProperty(None)
haerte = ObjectProperty(None)
rauheit = ObjectProperty(None)
#OutputGrößen
frequenz = StringProperty(None)
def btn_submit(self):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text, "Vorbehandlung:", ip.vorbehandlung.text)
if ip.haerte.value < 50:
self.frequency = str(180)
elif ip.haerte.value < 60:
self.frequency = str(200)
else:
self.frequency = str(220)
#control to see if right value is taken
print(self.frequency, "Hz")
def btn_clear(self):
np = App.get_running_app().root.ids._input_parameters
np.pro1.state = "normal"
np.pro2.state = "normal"
np.pro3.state = "normal"
np.material.text = "Auswahl treffen"
np.haerte.value = 55
np.rauheit.value = 5.5
the .kv file that can't get the label text:
outputparameters.kv
#: import statusbar StatusBar
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
Label:
text:'Frequenz:'
font_size:
Label:
id: _frequenz
text: root.frequenz
font_size: 20
the .kv file with the submit button, shouldn't be part of the problem either, worked perfectly fine before implementing the part ehre i try to update the text
statusbar.kv
#: import statusbar StatusBar
<StatusBar#BoxLayout>
orientation:'horizontal'
Button:
text: 'Clear'
on_press: root.btn_clear()
Button:
text: 'Submit'
on_press: root.btn_submit()
the file where i put in all the inputparameters, rather important:
Inputparameters.kv
#: import statusbar StatusBar
<InputParameters#GridLayout>
#Initialisierung .py zu .kv Ids
prozess: _prozess
pro1: _prozess1
pro2: _prozess2
pro3: _prozess3
vorbehandlung: _vorbehandlung
material: _material
haerte: _haerte
rauheit: _rauheit
#Prozess
Label:
text:'Prozess:
BoxLayout:
orientation: 'horizontal'
id: _prozess
ToggleButton:
id:_prozess1
text:'P-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess2
text:'E-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess3
text:'PE-MOH'
group: "proc_group"
on_state: root.on_state(self)
#Material
Label:
text: 'Material:'
Spinner:
id: _material
text: ""
values:
# Herstellschritte
Label:
text:'Fertigungsschritte:'
Spinner:
id: _vorbehandlung
text:
values:
# Haerte
Label:
text:'Haerte:'
BoxLayout:
orientation: 'vertical'
Label:
text: str(_haerte.value)
Slider:
id: _haerte
# Rauheit
Label:
text:'Rauheit:
BoxLayout:
orientation: 'vertical'
Label:
text:
Slider:
id: _rauheit
and the file where my layout is embedded (also rather necessary)
peenomat.kv
<Peenomat>
AnchorLayout:
anchor_x: 'left'
anchor_y: 'bottom'
GridLayout:
cols: 1
canvas.before:
Color:
Rectangle:
pos: self.pos
size: self.size
InputParameters:
id:_input_parameters
StatusBar:
id:_status_bar
OutputParameters:
id:_output_parameters
I really hope you can help, have been struggeling with this for a while and it should rather be easy...thanks in advance!
In your kv rule for <OutputParameters#GridLayout> you have a line:
frequenz: _frequenz
which sets frequenz to be a reference to the Label with the id of _frequenz. Then in that Label you are setting text using:
text: root.frequenz
So, you are trying to set the text of the Label to a reference to that Label
I suggest trying something like this:
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
frequency: ''
And change the Label to:
Label:
id: _frequenz
text: root.frequency
font_size: 20
But to actually change the value shown in the label, you will need a reference to the instance of OutputParameters, using something like:
App.get_running_app().root.ids._output_parameters.frequency = str(500)

use of random.choice with kivy buttons

So, I am creating a program with kivy that is dependant on being able to randomly choose a location from an already created dictionary by using buttons. I want the choice to display on the window the button takes you too rather than in the command line. Is there a way to do that? I have attached a snippet of .py code and my kivy code. I want the output displayed on the window (picture also attached) where it says "Go to:"
.py code:
import kivy
import random
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
FoodPlaces={'Asian': ['joy yee','strings','ramen san','chi cafe']}
class MainWindow(Screen):
pass
class FoodWindow(Screen):
def asianBtn(self):
print(random.choice(FoodPlaces['Asian']))
class AsianWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv=Builder.load_file("picker.kv")
class pickerApp(App):
def build(self):
return kv
if __name__=="__main__":
pickerApp().run()
kivy code:
WindowManager:
MainWindow:
FoodWindow:
AsianWindow:
<MainWindow>:
name:"main"
GridLayout:
cols:1
Label:
text:"Pick a Category"
Button:
text:"Food"
on_release:
app.root.current="food"
root.manager.transition.direction="left"
<FoodWindow>:
name: "food"
GridLayout:
cols:1
Label:
text:"Pick a Food Type"
Button:
text: "Asian"
on_release:
app.root.current="asian"
root.manager.transition.direction="left"
root.asianBtn()
Button:
text: "Go Back"
on_release:
app.root.current="main"
root.manager.transition.direction="right"
<AsianWindow>
name:"asian"
GridLayout:
cols:1
Label:
text: "Go to:"
Button:
text: "Go Back"
on_release:
app.root.current="food"
root.manager.transition.direction="right"
One way to do that is to add an id to the Label:
<AsianWindow>
name:"asian"
GridLayout:
cols:1
Label:
id: goto # Use this id to access the Label
text: "Go to:"
Button:
text: "Go Back"
on_release:
app.root.current="food"
root.manager.transition.direction="right"
To keep it simpler, put the asianBtn() method in the AsianWindow class:
class AsianWindow(Screen):
def asianBtn(self):
self.ids.goto.text = random.choice(FoodPlaces['Asian'])
And change its call in the kv to:
<FoodWindow>:
name: "food"
GridLayout:
cols:1
Label:
text:"Pick a Food Type"
Button:
text: "Asian"
on_release:
app.root.current="asian"
root.manager.transition.direction="left"
app.root.current_screen.asianBtn()
Button:
text: "Go Back"
on_release:
app.root.current="main"
root.manager.transition.direction="right"
With the asianBtn() method in the AsianWindow class, the path to the goto Label is simpler and the path to the asianBtn() method itself is simpler (since the current_screen is the AsianWindow at that point).
An even simpler way is to just use the on_enter() method of AsianWindow, so that a random choice is displayed whenever the AsianWindow is displayed. to do this, just replace the asianBtn() method with an on_enter() method:
class AsianWindow(Screen):
def on_enter(self, *args):
self.ids.goto.text = random.choice(FoodPlaces['Asian'])
And now you don't even need to call asianBtn() from the Button:
<FoodWindow>:
name: "food"
GridLayout:
cols:1
Label:
text:"Pick a Food Type"
Button:
text: "Asian"
on_release:
app.root.current="asian"
root.manager.transition.direction="left"
Button:
text: "Go Back"
on_release:
app.root.current="main"
root.manager.transition.direction="right"
So you are using print which won't help you display within the UI. I'm not 100% sure how/where you want to display, but I would advise you to add a label wherever you want to display the output. You would want this label to have an id property so you can change its text value dynamically to whatever the random function chooses from the dict.
The lable will look something like this in kv:
Label:
id: output
And to set its value you need a line like this in the py file:
self.ids.output.text = "name of restaurant"
Hope this helps!

Retrieve the value of the checkbox in Kivy

I am trying to retrieve the value of the checkbox on kivy to write some logic. Could someone please help me and tell me where i can find such information in kivy's documentation as i was left with little luck.
here is the code.
Python file:
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
from kivy.uix.checkbox import CheckBox
from kivy.properties import ObjectProperty
class Tab(TabbedPanel):
check = ObjectProperty(False)
def btn(self):
print(self.check)
class Checkbox(CheckBox):
pass
filekv = Builder.load_file("GUI.kv")
class TabbedPanelApp(App):
def build(self):
return filekv
if __name__ == '__main__':
TabbedPanelApp().run()
Kv file:
<TextInput>:
multiline:False
Tab:
do_default_tab: False
check:checked
TabbedPanelItem:
text: 'Test Request'
GridLayout:
cols:2
spacing: 20
padding: 20
Label:
text: "Sample ID: "
TextInput:
id: id_sample
Checkbox:
#how do i retrieve the value of the checkbox here??
Label:
text: ""
Button:
text: "Submit"
on_press: root.btn()
I tried using:
id: checked
active: checked
value: checked
But nothing worked.
First you have to give an id to the Checkbox:
Checkbox:
id: check_box
... and then you have its state like this:
print(self.ids.check_box.state)

Displaying an image over multiple buttons - kivy

I want to display a single image over multiple different buttons (as shown in the picture: https://i.stack.imgur.com/BQ99R.jpg)
When I try to do so, the image gets covered by the buttons and hidden in the background.
What I want to know is that is this even possible in kivy? If yes, where do I define the image, in the label or button?
This code:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Base>:
GridLayout:
cols: 2
size_hint: 1, 1
Button:
text: "Button 1"
on_press: print(self.text)
Button:
text: "Button 2"
on_press: print(self.text)
Button:
text: "Button 3"
on_press: print(self.text)
Button:
text: "Button 4"
on_press: print(self.text)
Image:
source: 'wolf.png'
""")
class Base(FloatLayout):
def __init__(self, **kwargs):
super(Base, self).__init__(**kwargs)
class SampleApp(App):
def build(self):
return Base()
if __name__ == "__main__":
SampleApp().run()
produces this:
Of course you have to provide an image yourself ;o)

Categories