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.
Related
For example we created with kivy language simple BoxLayout1 that contains button1 and another BoxLayout2. When you click button1 it adds a new button in BoxLayout2 but it's written in python.
Is it possible to acces existing layout in kv language, in python code? Or only solution is writting whole window in python?
I couldn't find any info in kivy docs, maybe I've just missed something.
EDIT:
I've something like this
Kv:
<CreateWindow>:
BoxLayout:
Button:
text: "test"
on_release: root.press()
BoxLayout:
Label:
text: "Label"
Python:
class CreateWindow(Screen):
def press(self):
I want to add a new button near Label by activating press function
in python will be like this
class CreateWindow(Screen):
def press(self):
# the first box is the first child in the children list of the CreateWindow widget so
box1=self.children[0]
box2=self.children[1]
# and now you can decide which box you want to use add_widget method with
# in your case it should be
box2.add_widget(Button())
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)
I've made a rule in my kv for the Button class to have a specific background (provided in an image). When I created an ActionBar that contains ActionPrevious and ActionButton widgets, they both seemed to get the same background.
And I would understand that ActionButton instance got that background, since it inherits from Button and ActionItem classes, but why did the ActionPrevious get the same background? It inherits from BoxLayout and ActionItem, neither of which have anything to do with the Button class. What's the reason behind it?
Also, a side question
The ActionPrevious has a property with_previous which, when set to True, adds a clickable arrow. However, the title of the widget remains unclickable. But the docs say that this property would make the whole widget clickable. While it's not a big deal, I'd rather want the entire ActionPrevious widget background to change on press. Is it possible to achieve this?
So what I mean is that when you press the Back arrow, only the space around it and the app icon turns blue, but the text doesn't, as if it's part of a different widget.
Here is the code to visualize the question:
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.actionbar import ActionBar
Builder.load_string('''
<Button>:
background_normal: 'some_file.png'
<MenuBar>:
ActionView:
ActionPrevious:
title: "Log out"
with_previous: True
ActionButton:
text: "Settings"
''')
class MenuBar(ActionBar):
pass
runTouchApp(MenuBar())
Okay, so the truth was in the style.kv file. Basically, ActionPrevious widget has the following structure:
<ActionPrevious>:
GridLayout:
ActionPreviousButton:
GridLayout:
ActionPreviousImage:
id: prev_icon_image # the "back" arrow
ActionPreviousImage:
id: app_icon_image # the app icon
Widget:
# perhaps something to split the title from the GridLayout
Label:
id: title # the title
And the ActionPreviousButton inherits from Button, so that's why the ActionPrevious arrow part was getting that background.
Here also lies the answer to the side question. Since the clickable part is the ActionPreviousButton, and the title is kept in a Label, that is not a child of it, the text is unclickable. So to fix that, one has to create a custom class and put the Label as a child of the ActionPreviousButton.
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.