i want to print all user text inputs when i press the button. the problem when i press the button to print the inputs appear the error TypeError: p() takes 1 positional argument but 2 were given. just to know the number to text inputs may vary from user to other
from kivy.uix.textinput import TextInput
from kivy.app import App
from kivy.uix.button import Button
from kivy.lang.builder import Builder
kv=Builder.load_string('''
ScrollView:
GridLayout:
id:inputs
cols:1
row_force_default:True
row_default_height:30
size_hint_y:None
height:self.minimum_height
''')
class Accounting(App):
def build(self):return kv
def on_start(self):
self.return_list = [] #print this list
w = Button(text='print all the text inputs',on_press=self.p)
self.return_list.append(w)
self.root.ids.inputs.add_widget(w)
for i in range(5):
w = TextInput()
self.return_list.append(w)
self.root.ids.inputs.add_widget(w)
return self.return_list
def p(self):print(self.return_list)#here
Accounting().run()
When you click button then Kivy runs it with extra argument p(widget) so you can assign function to many buttons and you will see which button was clicked.
But it means you have to get this value in function
def p(self, widget):
Minimal working code.
If you want text only from TextInput then removed Button from return_list.
from kivy.uix.textinput import TextInput
from kivy.app import App
from kivy.uix.button import Button
from kivy.lang.builder import Builder
kv = Builder.load_string('''
ScrollView:
GridLayout:
id:inputs
cols:1
row_force_default:True
row_default_height:30
size_hint_y:None
height:self.minimum_height
''')
class Accounting(App):
def build(self):
return kv
def on_start(self):
self.return_list = [] #print this list
w = Button(text='print all the text inputs', on_press=self.p)
self.return_list.append(w)
self.root.ids.inputs.add_widget(w)
for i in range(5):
w = TextInput()
self.return_list.append(w)
self.root.ids.inputs.add_widget(w)
return self.return_list
def p(self, widget):
print('widget:', widget)
print('text :', widget.text)
for item in self.return_list:
print(item.text)
Accounting().run()
Related
i have problem when i use loop in kivy app to show update value for loop, so when i run app and press toggle button to start showing last value of loop i program crash.
this is code:
*.py
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from random import randint
class ShowLoopValueInterface(BoxLayout):
ToggleButton_label = StringProperty("normal")
Label_text_value = StringProperty("normal")
def togglebutton_on_state(self, widget):
if widget.state == "down":
self.ToggleButton_label = "down"
# self.to_text_value()
Clock.schedule_interval(self.to_text_value, 0.5)
else:
self.ToggleButton_label = "normal"
def to_text_value(self, _):
# def to_text_value(self):
while True:
self.Label_text_value = str(randint(0, 100))
class ShowLoopValueApp(App):
pass
ShowLoopValueApp().run()
*.kv
ShowLoopValueInterface:
<ShowLoopValueInterface>:
orientation: "vertical"
ToggleButton:
text: root.ToggleButton_label
on_state: root.togglebutton_on_state(self)
Label:
text: root.Label_text_value
In my Kivy-App, i generate Buttons via a python-class based on a dictionary (in the following example i use a list but that's just an example for the underlying problem).
Within the App, the dictionary gets changed and i want to display that change (obviously) in my App (by adding/ removing/ rearranging the Buttons).
To achieve this, my approach is to either restart the entire App or only reload that particular BoxLayout. Unfortunately, non of my attempts worked out so far and i could not find any (working) solution on the internet.
This is my code example:
Python Code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
buttonlist = []
counter = 0
class MainWindow(BoxLayout):
def addbutton(self):
global buttonlist
global counter
buttonlist.append(counter)
counter += 1
class ButtonBox(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
global buttonlist
for button in buttonlist:
b = Button(text=str(button))
self.add_widget(b)
class KivyApp(App):
def build(self):
return MainWindow()
KivyApp().run()
KV Code:
<MainWindow>:
BoxLayout:
ButtonBox:
Button:
text: "add Button"
on_press: root.addbutton()
My closest attempt was something containing a restart-Method like:
def restart(self):
self.stop()
return KivyApp().run()
and calling:
App.get_running_app().restart()
But for some reason, this does not stop the App but opens a second instance of the App within the first one (resulting in App in App in App in App if pressed often)
You can rebuild the ButtonBox by first calling clear_widgets() on the ButtonBox instance. Here is a modified version of your code that does that:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
kv = '''
<MainWindow>:
BoxLayout:
ButtonBox:
id: box
Button:
text: "add Button"
on_press: root.addbutton()
'''
buttonlist = ['Abba', 'Dabba', 'Doo']
counter = 3
class MainWindow(BoxLayout):
def addbutton(self):
global buttonlist
global counter
buttonlist.append(str(counter))
counter += 1
self.ids.box.reload()
class ButtonBox(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
self.reload()
def reload(self):
# method to rebuild the ButtonBox contents
global buttonlist
self.clear_widgets()
for button in buttonlist:
b = Button(text=str(button))
self.add_widget(b)
class KivyApp(App):
def build(self):
Builder.load_string(kv)
return MainWindow()
KivyApp().run()
I used your kv as a string, just for my own convenience.
What I want to do is take input from kivy.uix.textinput.TextInput() and show it on the screen.
I am new to gui Programming and I think it is an easy task.
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
class MyWindowApp(App):
def __init__(self):
super(MyWindowApp, self).__init__()
self.lbl = Label(text='Read Me!')
self.inp = TextInput(multiline=False,
size_hint =(1, 0.05),
pos_hint = {"x":0, "y":0.05})
def build(self):
self.inp.bind(on_text_validate=self.on_enter)
#self.bt1.bind(on_press=self.clk)
layout = FloatLayout()
layout.orientation = 'vertical'
layout.add_widget(self.lbl)
layout.add_widget(self.inp)
return layout
def on_enter(self,value):
print(value)
def clk(self, obj):
print ('input')
x = input()
self.lbl.text = x
window = MyWindowApp()
window.run()
when i run the code, I get the regular output output.
when I type say "hello world" in the textbox, this is the output:
<kivy.uix.textinput.TextInput object at 0x03F5AE30>
I do not get what I typed.
please suggest what should I do
Modify the following ...
def on_enter(self, value):
print(value.text)
I need to add a series of labels to my screen layout - the number of the labels are defined at runtime - and update the label texts with runtime data.
Hence, I need to add the labels programatically.
I have created a little test programme to investigate the behaviour:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import StringProperty
import random
Builder.load_string('''
<YourWidget>:
BoxLayout:
size: root.size
Button:
id: button1
text: "Change text"
on_release: root.change_text()
# Label:
# id: label1
# text: root.random_number
''')
class YourWidget(Widget):
random_number = StringProperty()
def __init__(self, **kwargs):
super(YourWidget, self).__init__(**kwargs)
label = Label(
id= 'label1',
text = root.random_number
)
self.add_widget(label)
self.random_number = str(random.randint(1, 100))
def change_text(self):
self.random_number = str(random.randint(1, 100))
class updatetest(App):
def build(self):
return YourWidget()
#if __name__ == '__main__':
if (True):
updatetest().run()
If I uncomment the three lines relating to Label in the Builder.load_string, and remove the label = & self.add_widget lines from the python code, then the label gets updated as expected.
However, I have been unsuccessful in adding the label with the code as it stands.
What am I missing?
All assistance gratefully received!
I am working on a random dice roller project, Im new to python (I started learning it on my own about 2 months ago) and thought that it would be a good beginner project to work on. But I keep having trouble binding my functions to my buttons. I keep getting an AttributeError: 'Dice' object has no attribute 'displaybox'. Which I dont really understand because my Dice class clearly has a displaybox object inside of it. Thanks for any help!
Here is my Python code:
from random import randint
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
class Dice(GridLayout):
def __init__(self, **kwargs):
super(Dice, self).__init__(**kwargs)
# Define Buttons and labels
d4btn = Button(text='D4',
bold = True,
on_press = self.rolld4)
d6btn = Button(text='D6',
bold = True)
d8btn = Button(text='D8',
bold = True)
d10btn = Button(text='D10',
bold = True)
d12btn = Button(text='D12',
bold = True)
d20btn = Button(text='D20',
bold = True)
displaybox = (Label(text=('You have not rolled, \n please select a number to roll.')))
infobox = (Label(text='Random Dice Project \nJoshua \n10/17/2017'))
# Create Buttons and Labels
self.add_widget(d4btn)
self.add_widget(d6btn)
self.add_widget(d8btn)
self.add_widget(d10btn)
self.add_widget(d12btn)
self.add_widget(d20btn)
self.add_widget(displaybox)
self.add_widget(infobox)
# Button Behavior
def rolld4(self, obj):
self.displaybox.text = print(str(randint(1,4)))
class DiceRollerApp(App):
def build(self):
return Dice()
if __name__ == '__main__':
DiceRollerApp().run()
And here is my Kivy code:
#:kivy 1.10.0
<Dice>:
cols: 2
rows: 4
Edit: I got a working version completed. Thanks for your help!
My recommendation is to define all your widgets in your kv file, and use ObjectProperty to hook up to your display box. Please refer to the example below for details.
Example
main.py
from random import randint
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class Dice(GridLayout):
displaybox = ObjectProperty(None)
# Button Behavior
def rolld4(self):
self.displaybox.text = str(randint(1, 4))
class DiceRollerApp(App):
def build(self):
return Dice()
if __name__ == '__main__':
DiceRollerApp().run()
diceroller.kv
#:kivy 1.10.0
<MyButton#Button>:
bold: True
<Dice>:
displaybox: displaybox
cols: 2
rows: 4
MyButton:
text: "D4"
on_press: root.rolld4()
MyButton:
text: "D6"
MyButton:
text: "D8"
MyButton:
text: "D10"
MyButton:
text: "D12"
MyButton:
text: "D20"
Label:
id: displaybox
text: 'You have not rolled, \nplease select a number to roll.'
Label:
id: infobox
text: 'Random Dice Project \nJoshua \n10/17/2017'
Output
in the init() of your dice you need to instanciate the displaybox as an attribute of the dice then you can manipulate it in the button behaviour, so your code is correct just add the self parameter and everything would work fine
here is the code:
-kv:
<Dice>:
cols: 2
rows: 4
-py:
from kivy.app import App
from random import randint
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
class Dice(GridLayout):
def __init__(self, **kwargs):
super(Dice, self).__init__(**kwargs)
# Define Buttons and labels
d4btn = Button(text='D4',
bold = True,
on_press = self.rolld4)
d6btn = Button(text='D6',
bold = True)
d8btn = Button(text='D8',
bold = True)
d10btn = Button(text='D10',
bold = True)
d12btn = Button(text='D12',
bold = True)
d20btn = Button(text='D20',
bold = True)
#Here you instantiate it ass an attribute of the dice
self.displaybox = (Label(text=('You have not rolled, \n please select a number to roll.')))
infobox = (Label(text='Random Dice Project \nJoshua \n10/17/2017'))
# Create Buttons and Labels
self.add_widget(d4btn)
self.add_widget(d6btn)
self.add_widget(d8btn)
self.add_widget(d10btn)
self.add_widget(d12btn)
self.add_widget(d20btn)
#Then you add it to the layout
self.add_widget(self.displaybox)
self.add_widget(infobox)
# Button Behavior
def rolld4(self, obj):
self.displaybox.text = str(randint(1,4))
print(str(randint(1, 4)))
class DiceRollerApp(App):
def build(self):
return Dice()
if __name__ == '__main__':
DiceRollerApp().run()
proof:
I hope I helped !