Hopefully this will be an easy question for some of you. So I am working on some code to interface with a heater controller. The GUI is written mostly in Kivy language (to compartmentalize the various screens), but I have a .py file that ties all the Kivy files together. Within one my Kivy files, there are a few TextInput fields that are for a user to define a few numerical values. Once the text fields are filled, the user clicks on the "Start" button to begin the heater test.
Now, my question is when using the "Start" button as my flag, how can I get Python to read the numerical values that are in the fields? I've looked online and posts about using the .get and raw_input methods, but nothing that has Python retrieving and interpreting values from Kivy code. Any help would be much appreciated!
This is part pf my .py file, which where I need the user-input values to be evaluated...
class ControllerScreen(Screen):
def build(self):
return ControllerScreen()
def CreateExcelFile(self):
wb = Workbook()
ws = wb.active
ws.cell('A1').value = 'Timestamp'
ws.cell('B1').value = 'Temperature'
ws.cell('C1').value = 'Batch 1'
ws.cell(row=2, column=1).value = 000
wb.save("Spreadsheet1.xlsx")
This is an excerpt from the Kivy file, containing the code for a single text field that a user types a number into...
<ControllerScreen>:
TextInput: #Ramp time increment field
id: ramp_time
font_size: 25
size_hint: 0.1,0.06
pos_hint: {"right":0.575, 'y':0.67}
Button: #Start analysis button
on_release: app.root.current = "home"
text: "Start"
font_size: 25
color: 0,1,0.5,1
size_hint: 0.29,0.075
pos_hint: {'x':0.35, 'y':0.1}
And lastly, here is a picture of the GUI to give some reference to the text fields I am regarding (the one circled in red is the one I reference in the code above)...
To access value of TextInput you need to use TextInput's property text, therefore to get a number you need to:
n = int(self.ids.ramp_time.text) #or float or whatever you need
However if you won't access the text in your ControllerScreen, then you need to manage a communication between your classes, so that you could use variables between them. You can achieve it with these answers: 1, 2 for example.
There's an option for you to set a filtering for your input so your user won't screw something up(e.g. inputs letter/s)
I've looked online and posts about using the .get and raw_input methods, but nothing that has Python retrieving and interpreting values from Kivy code.
I think the problem is that you looked for getting user's input directly from python and not from Kivy. I'd say Kivy is quite new, so there will be no mention in old tutorials/websites. There are tutorials and docs directly for kivy either on official website or youtube.
Related
I'm working on a Kivy app which should generate plots when the user clicks on an item from a menu. When the user clicks the item, it opens a new screen which should generate the plot. My problem is that I can't seem to get Kivy to show the plot. My code executes without errors so I'm not sure where I'm going wrong.
I've looked for questions on this issue and the best I could find is here (Real-time plotting using matplotlib and kivy in Python) but that didn't work for me.
I also have a secondary question about re-defining the on_enter method of the Screen class so that it can use the App method for creating the plot. Is this possible?
Python code (function defined as part of the App class)
def grp_enter(self):
grid = GridLayout(rows = 1, cols = 1)
#grid.add_widget(FigureCanvasKivyAgg(plt.gcf())) should have prepared a canvas but one didn't appear
self.track_instance.associations() # generates the plot
KV code
<GroupScreen>:
on_enter: app.grp_enter()
name: 'groups_screen'
Button:
on_release:
app.root.transition = SlideTransition(direction = "right")
app.root.current = 'main'
text: 'back to the home screen'
font_size: 50
I could be wrong as I haven't been able to test your code but I believe that your screen doesn't get updated when you try to display your plot. You should try to use the schedule function:
clock.schedule_once(function_showing_plot).
So in your grp_enter function, you would call your track_instance.associations() function as such:
clock.schedule_once(track_instance.associations)
Hope this helps.
I'm building a simple gui it's a "bank account manager" and I need to add the value that the user inputs in a textinput in a deposit screen then add it to a balance which the user inputs in the sign up screen .... The sign up screen's info is saved into a dictionary.. each key has a value of a list and that list has 9 values ...the name, the last name the balance etc...but the balance is a string and I can't even get to it to run any operations on it.
I would recommend showing code in an attempt at solving the issue. However to answer your question with the information provided, I would recommend using a button widget and in it's properties in a .kv file use. on_press:/on_release: root.myfunction()
then in that screen/application class below use something like this:
.kv/Builder_loadstring:
TextInput:
id: mywidget
text: 'mywidget'
Button:
text: 'Run a Function'
on_release: root.myfunction()
python:
class MyApp(App):
def myfunction(self):
*whatever you want it to do*
value = self.ids.mywidget.text
*value = self.ids.mywidget.data* #For when you are using lists for recycleview/spinners#
*value = self.ids.mywidget.some_type_of_widget_property*
*whatever you want it to do*
I'm new to Python and Kivy, and I'm trying to create multipage display of letters of the braille alphabet, with the corresponding braille's letter picture present in every page. I really want to learn more about creating Kivy desktop apps. I really hope you can help me. What I'm trying to do is have a page look like this:
I know how images and buttons are placed and customized in terms of size and position in the KV file. However what I need to learn is how add_widget() and clear_widget() will factor in this. I have read the Kivy docs but they barely explain how I could achieve what I need. What I thought of doing is using the from kivy.uix.screenmanager import ScreenManager, Screen feature, and then just create 26 screens and route them via on_click in the kv file. But that's tedious and too manual. Here's my code so far:
class LetterAScreen(Screen):
pass
class LetterBScreen(Screen):
pass
class LetterCScreen(Screen):
pass
class LetterDScreen(Screen):
pass
class LetterEScreen(Screen):
pass
class LetterFScreen(Screen):
pass
class LetterGScreen(Screen):
pass
#.... so and so until Letter Z
sm = ScreenManager(transition=SwapTransition())
#LearnScreen - Alphabet
sm.add_widget(LetterAScreen(name='lettera'))
sm.add_widget(LetterBScreen(name='letterb'))
sm.add_widget(LetterCScreen(name='letterc'))
sm.add_widget(LetterDScreen(name='letterd'))
sm.add_widget(LetterEScreen(name='lettere'))
sm.add_widget(LetterFScreen(name='letterf'))
sm.add_widget(LetterGScreen(name='letterg'))
sm.add_widget(LetterHScreen(name='letterh'))
sm.add_widget(LetterIScreen(name='letteri'))
sm.add_widget(LetterJScreen(name='letterj'))
sm.add_widget(LetterKScreen(name='letterk'))
sm.add_widget(LetterLScreen(name='letterl'))
sm.add_widget(LetterMScreen(name='letterm'))
sm.add_widget(LetterNScreen(name='lettern'))
sm.add_widget(LetterOScreen(name='lettero'))
sm.add_widget(LetterPScreen(name='letterp'))
sm.add_widget(LetterQScreen(name='letterq'))
sm.add_widget(LetterRScreen(name='letterr'))
sm.add_widget(LetterSScreen(name='letters'))
sm.add_widget(LetterTScreen(name='lettert'))
sm.add_widget(LetterUScreen(name='letteru'))
sm.add_widget(LetterVScreen(name='letterv'))
sm.add_widget(LetterWScreen(name='letterw'))
sm.add_widget(LetterXScreen(name='letterx'))
sm.add_widget(LetterYScreen(name='lettery'))
sm.add_widget(LetterZScreen(name='letterz'))
I haven't gotten around the kv file because i'm clueless how this will pan out. What I need to do is create widgets or a function that will swap out the images of the current letter and display those of the next or previous ones when the next/button is clicked, without having to switch screens every single time. I'm really unfamiliar with how functions work in Kivy and Python. I hope you could help me. Thank you.
Here is a simple solution to your problem. I'll leave it to you to modify and make it look and work exactly how you want :)
Learning the kv language is INCREDIBLY helpful, easy, and it can be picked up quite quickly.
main.py
from kivy.app import App
class MainApp(App):
alphabet = 'abcdefghijklmnopqrstuvwxyz'
def next_letter(self):
# Get a reference to the widget that shows the letters
# self.root refers to the root widget of the kv file -- in this case,
# the GridLayout
current_letter_widget = self.root.ids['the_letter_label']
# Get the letter currently shown
current_letter = current_letter_widget.text
# Find the next letter in the alphabet
next_letter_index = self.alphabet.find(current_letter) + 1
next_letter = self.alphabet[next_letter_index]
# Set the new letter in the widget that shows the letters
current_letter_widget.text = next_letter
MainApp().run()
main.kv
GridLayout: # This is the `root` widget of the main app class
cols: 1
Label:
text: "g"
id: the_letter_label # Setting an id for a widget lets you refer to it later
Button:
text: "Previous"
Button:
text: "Next"
on_release:
# the keyword `app` references the main app class, so we can call
# the `next_letter` function
app.next_letter()
I'm happy to address specific questions if you have them.
I am working on a doorbell project using a raspberry pi 3 and the 7inch touchscreen display. I am using kivy to power the GUI however have run into the following issue I cannot seem to solve.
The kivy app loads on a button press and gives the user options for authentication (e.g rfid, keypad etc) On selecting an option it takes the user to another screen telling them to input their pin in the case of the keypad option.
This is just the snippet for the keypad screen:
class KeypadScreen(Screen):
keypadTextTest = StringProperty("Please Input 4 Digit Passcode")
def Decision(self, *args):
keypadOutput = FourDigitCodeCheck()
if keypadOutput == True:
self.change_text()
Clock.schedule_interval(self.change_text, 0.1)
self.change_text()
doorOpen()
return
def change_text(self, *args):
self.keypadTextTest = "Door Open"
When the user inputs their pin and the code returns True (Ie it is the correct pin) I wish for the label to change to say "Door Open" and then run the doorOpen function (seen below) which for now just turns an LED on and off.
def doorOpen():
print ("Door Open : Please Enter")
GreenLED("ON")
sleep(5)
GreenLED("OFF")
return
Currently however the doorOpen function is called before the label changes meaning that the LED turns on, then off 5 seconds later and then the label changes.
I have tried various different methods of updating the label text and have even tried adding in different alterations afterwards to try and force an update before the doorOpen function is ran however to no avail.
Any input would be greatly appreciated as has been a tedious afternoon. Below is the kivy lang snippet for the keypad screen encase something is wrong there:
<KeypadScreen>:
on_enter: root.Decision()
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
Label:
id: keypadtext
text: root.keypadTextTest
font_size: 50
Pastebin of full python script: https://pastebin.com/K2CnnmVB
Pastebin of full Kivy script: https://pastebin.com/9mgZFxyx
I have a kivy program that has a ‘sqlite’ database containing details of a golf competition which displays information & warning messages via a standard Pop-up function - pop_mess()
For testing purposes I open an alternative ‘testing’ database in a function – set_test_db(). When this is done I would like to change the background colour of the pop-up to warn the user that the main database is not being used.
I have tried to do this (code at end of 'set_test_db'). However although the routine retrieves the current background colour correctly it will not change it.
Can someone point me in the direction of a solution. The coding method works fine for changing the text properties of a widget. (similar questions usually refer to text properties). I have used both list & tuple for colour values.
In .ky file
<CustomPopup>:
popup_message: popup_message
size_hint: .98, .75
id: popup_id
title: "Casual and Ancient"
title_align: 'center'
title_color: 1,.5,.3,1
BoxLayout:
id: contentbox
orientation: 'vertical'
TextInput:
id: popup_message
color: .3,.4,1.0,1
background_color: [.7,1.0,.2,1]
text: "text message goes here"
font_size: 16
font_name: 'RobotoMono-Regular'
…..
CaaRoot:
<CaaRoot>:
orientation: 'lr-tb'
padding: 10
etc
...
in main.py
(self = CaaRoot)
...
def pop_mess(self,message):
p_up=CustomPopup()
lab=p_up.ids['popup_message']
lab.text=message
p_up.open()
...
def set_test_db(self):
# on button in CaaRoot
# open test data base instead of real
if self.db != None:
print 'Cannot Open Test Data Base - already running'
else:
# open ‘test’ database
# set background colour of popup to warn user.
fn='/home/.... caatestdb.db
self.op_db(fn)
self.testing='TEST database'
p_up=CustomPopup()
lab=p_up.ids['popup_message']
x=lab.background_color
new_col=[.9,.3,.3,1]
lab.background_color=new_col
self.pop_mess('color set to : '+str(new_col)+ ' was : '+str(x))
the popup displays
color set to : [0.9, 0.3, 0.3, 1] was : [0.7, 1.0, 0.2, 1]
(with background still set to [0.7, 1.0, 0.2, 1])
Have a look at kivymd, which solves issues like that very well. It is basically a very elegant template for kivy based on Google's Material Design.
For me it makes all the coloring stuff and appearance in general much easier, especially as I am not a designer but a programmer.
The Demo has also a very complete sets of examples including popups.
On further investigation of my problem I came across the similar question (Changing Background of Kivy Popup )
The fact that the solution given to that was “non-intuitive” involving the properties of the ‘inherited’ Canvas element(?) made me realise (remember ?) than some widgets do not have the full range of modifiable properties.
The 'background_color' property that I was retrieving was a property inherited from the Canvas which cannot be easily changed.
I have avoided the problem by creating a ‘popup’ widget whenever I wish to use it rather than modifying an existing widget. I still cannot (simply) change the background_color of the popup but I can change the background color of the parent element so that the user’s eye immeditely sees something different. I can also change the text color when calling the popup message function.
def pop_mess(self,message,colour=(.9,.6,.9,1)):
#
# text color can ve overridden by the 'colour' parameter
# self.backc can be set as required to set the color behind the
# popup depending on circumstances
popup=Popup(title='Casual & Ancient', \
content=Label(text=message,color=colour,\
font_name = 'RobotoMono-Regular'),\
size_hint=(.98,.75),background_color=self.backc)
popup.open()
I'm not completely sure that the analysis is correct or that there may be some side-effects but it seems to work ok (and was somewhat simpler to code)