I have recently learned a bit of matplotlib and would like to use it within kivy. I have read a little documentation on the garden here and there but don't really understand it.
I have installed kivy garden and matplotlib but don't know how to proceed from here. I simply want to add a already completed matplotlib graph into kivy.
I would appreciate a step by step simplified set of instructions of how to get what I already coded into kivy and get it to display.
Thanks
Here is the simplest example possible for kivy-garden matplotlib and kivy. If you would like to do more advanced things, check out their examples: https://github.com/kivy-garden/garden.matplotlib/tree/master/examples
I think it should be enough to get you started with your plot.
Below I am adding it to a BoxLayout, you can add more widgets to this BoxLayout or add this BoxLayout somewhere else.
python code example.py:
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import matplotlib.pyplot as plt
plt.plot([1, 23, 2, 4])
plt.ylabel('some numbers')
class MyApp(App):
def build(self):
box = BoxLayout()
box.add_widget(FigureCanvasKivyAgg(plt.gcf()))
return box
MyApp().run()
Related
I cant seem to find any examples of interfacing kivy mapview with python for things like moving the map or adding markers from the python side of things.
What I mean is I would like to eventually pull data from a CSV file and have it control the information on screen. This is straightforward with labels and buttons. But I'm not able to make the same methides work with mapview.
All references I find on line controlled all logic inside the .KV files. None of the examples I find use python to reach in and change things inside the .KV file.
This is the best example I have tested so far. but as you can see all logic is inside the .KV file. https://github.com/kivy-garden/mapview/blob/develop/examples/map_browser.py
I want to be able to send data from the python side to the .kv side and have it update the screen as its being sent. Like Lat and lon positions, markers and so on.
What I am use to doing something like this.
Python side
from kivy_garden.mapview import MapView
from kivy.lang import Builder
from kivymd.app import MDApp
class MainApp(MDApp):
def build(self):
return Builder.load_file('MapViewApp.kv')
MainApp().run()
MapViewApp.kv
MapView:
id: map
lat: 36
lon: -115
zoom: 10
When I try to import ObjectProperties from kivy.properties, I get an error:
"No name 'ObjectProperty' in module 'kivy.properties'pylint(no-name-in-module)"
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.config import Config
from kivy.event import EventDispatcher
from kivy.properties import ObjectProperty
Config.set('graphics', 'width', 1000)
Config.set('graphics', 'height', 1000)
Config.set('graphics', 'resizable', False)
class GridContainer(GridLayout):
text_input1 = ObjectProperty()
label1 = ObjectProperty()
def count_sum(self):
self.label1.text = int(self.text_input1.text[0]) + int(self.text_input1.text[1])
class MyApp(App):
def build(self):
GridContainer()
return GridContainer()
Are there any ways to solve this problem?
I found myself in the same situation simply because I thought python only accepts libraries written in python. Python codes/libraries can be made to run faster by compiling them into a mixture of C and Python codes as observed with the properties library located in the kivy directory of site-packages of your python installation folder. Using this method, the compiled python codes can be imported without any troubles just as prior to compilation.
Myself, I have not seen any extension that lints cython codes and they are all built to work with libraries developed with python not cython. Thus, they tend to have problems linting those that have been written/compiled to cython.
As inclement clearly stated, this is not an issue you should worry about if the program runs fine. It is a problem with IDE linting extensions, they cant lint cython codes. You can go with Jayden solution if you dont want to be seeing the squiggy red lines all the time.
I hope this clearifies things..?
I found a workaround:
replace from kivy.properties import ObjectProperty with import kivy.properties as kyprops
type kyprops anytime you need to declare ObjectProperty
Let me know if that helps!
If the code runs fine, this is just a bug in your linter. As already linked by others, it is probably not capable of properly understanding imports from cython-built libraries.
I am trying to pack an app that requires several imports, among those matplotlib.pyplot
The kivy app (simplified, but still working) is:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
import matplotlib.pyplot
Builder.load_string("""
<MyWidget>:
id: my_widget
FileChooserIconView:
id: filechooser
on_selection: my_widget.selected(filechooser.selection)
Image:
id: image
source: ""
""")
class MyWidget(BoxLayout):
def selected(self,filename):
self.ids.image.source = filename[0]
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
This app works perfectly in python using spyder.
However, when I try to pack it as an independent kivy app it gives me error maximum recursion depth exceeded.
I am surprised and I do not know what the problem is because:
1.There are no recursive functions in the app.
2.Works perfectly in python spyder while developing it and testing it, the only problem is during packaging.
3.I have tried multiple options, including commenting out several portions and, most surprising, when I comment out the import matplotlib.pyplot the app packages well. However I need matplotlib.pyplot for this app so taking it out is not an option.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
#import matplotlib.pyplot
Builder.load_string("""
<MyWidget>:
id: my_widget
FileChooserIconView:
id: filechooser
on_selection: my_widget.selected(filechooser.selection)
Image:
id: image
source: ""
""")
class MyWidget(BoxLayout):
def selected(self,filename):
self.ids.image.source = filename[0]
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
The above code works and packages well.
Is it that there is some limit of the size of the files one can import to a kivy app? I have already tried to increase the recursion limit with sys.setrecursionlimit(high numbers) but it is not a solution to this problem.
I am really lost. Any insight appreciated.
Thank you
Edit 2/4/2019:
It has been suggested that the question: pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object is a duplicate and answers this question. Although this is definitively a related question and is helpful, my error occurs in the first stage of the creation of the kivy package:
python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py
Thank you so MUCH to everybody who tried to help.
I found an answer and I hope it helps other people who tries to create a kivy package and there is a problem importing python module(s).
Once you have your main.py script ready to package:
1.Start with the instructions at
https://kivy.org/doc/stable/guide/packaging-windows.html
and do the first step:
python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py
This will give you the error of maximum recursion depth exceeded or whatever error this gives to you originally. No worries. The purpose of this step is to create an initial spec file.
2.Open the spec file and add all the extras that the kivy instructions give you at
https://kivy.org/doc/stable/guide/packaging-windows.html
that is:
from kivy.deps import sdl2, glew
Tree('examples-path\\demo\\touchtracer\\'),
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
3.In addition to that, add at the beginning of the spec file the following:
import sys
sys.setrecursionlimit(5000) # (or some big number)
4.Also add any imports in the hidden imports that you might need.
hiddenimports=[] # change to (example importing pandas and matplotlib) hiddenimports=['pandas', 'matplotlib']
5.Just follow the last step at
https://kivy.org/doc/stable/guide/packaging-windows.html
that is:
python -m PyInstaller touchtracer.spec
and get your app built
When we go into a recursion, there is a risk of stack overflow and the Cpython working under the hood does not take it upon itself to optimize tail recursion, so if you go too deep, you will move closer towards a stack overflow. Generally different Cpython/python flavors have different recursion permit depth, The version of python you have running locally has a more liberal depth limit (Generally because it is assumed developers have good enough computers that this can take place). But when you use tools to package your application they generally override the sys.setrecursionlimit to a more conservative value as they try to make sure you don't cause an stack overflow on systems with lower hardware.
Sadly there is no silver bullet for this problem, you can try to look into your specific manager and change the limit (Not recommended) or you can try to convert your recursive blocks into iterative blocks.
How to create Kivy widgets without using kv language and .kv files? I am new to kivy. I usually use Tkinter, but i found out that Kivy is good for creating Android apps, so I am learning how to use it.
I know that Kivy widgets are made using .kv files, but i would like to create them like widgets in Tkinter.
# Creating widgets in tkinter:
# We'll assume tkinter is imported as tk
label_1 = tk.Label(text='Hello World', bg='white')
label_1.pack()
# Creating widgets using Kivy in .py file
label_1 = Label(text='Hello World') # eg. Not able to set color!
add_widget(label_1)
# Creating widgets using kv language
Label:
text: "Hello World"
color: 1,0,0,1
So, is there any way to make Kivy widgets completely in python? How could i set Kivy label color directly in python?
Thanks.
Here's an example of Kivy application without using kv lang:
from kivy.app import App
from kivy.uix.label import Label
class TestApp(App):
def build(self):
return Label(
text='Hello, world',
color=(1, 0, 0, 1)
)
TestApp().run()
Basically build method of kivy.app.App instance has return a main widget object, in this case a kivy.uix.Label instance. To have more complex widget you should create a subclass of some layout class and then add widgets using add_widget method.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
class TestWidget(BoxLayout):
def __init__(self, **args):
super(TestWidget, self).__init__(**args)
label = Label(
text='Hello, world',
color=(1, 0, 0, 1))
self.add_widget(label)
class TestApp(App):
def build(self):
return TestWidget()
TestApp().run()
I'd like to encourage you to use kv lang anyway, since it makes the code simplier.
It is completely possible to use python exclusively to write apps with kivy. I began using kivy about 6 month ago and quickly abandoned the kv files. I do not like "magical" code in the background making bindings. I know this is a preference thing and now that I know how the widgets and layouts work, it may be actually quicker to use the kv language. Things you need to do manually are keep handles between widgets throughout the widget tree and setup bindings using the kivy properties. There is a lot to learn but once you start getting it, the possibilities are endless. Most examples you find are very simple and I feel the documentation is very limited. I feel that if you are comfortable with python, you will actually learn more about how kivy works if you stay in python.
I'm marking Nykakin's answer as correct, but I just thought I'd share some details.
How do I use the kivy module garden.graph inside the kv file? I only found documentation that explained how to use it in the main python script.
I imported the kivy.garden.graph in the python file, and I can add the Graph inside the kv file, but I didn't find any documentation how to set the size, plots etc.
Graph:
id: graph_test
plot: MeshLinePlot
this gives an error since MeshLinePlot is not defined, though I imported it on the python side.
any help would be highly appreciated, maybe we could then add this info to the graph's github readme as well.
Building on the answer from piwnk:
I added this to the .kv file:
#:import MeshLinePlot kivy.garden.graph.MeshLinePlot
<SetGraph>:
graph_test : graph_test
Graph:
id: graph_test
plot: MeshLinePlot
xlabel:'X'
ylabel:'Y'
x_ticks_minor:5
x_tics_major:25
y_ticks_major:1
y_grid_label:True
x_grid_label:True
padding:5
x_grid:True
y_grid:True
xmin:-0
xmax:100
ymin:-1
ymax:1
pos: 0, root.height / 6
size: root.width * 2 / 3 , root.height * 18 / 24
In main.py, I added:
from math import sin
from kivy.garden.graph import Graph, MeshLinePlot
class SetGraph(Widget):
graph_test = ObjectProperty(None)
update_graph(self):
plot = MeshLinePlot(color=[1, 0, 0, 1])
plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
self.graph_test.add_plot(plot)
class graphLayoutApp(App):
def build(self):
disp = SetGraph()
disp.update_graph()
return disp
if __name__ == '__main__':
graphLayoutApp().run()
I have changed my original tested solution to more descriptive names. Hopefully, I have not made any mistakes. Let me know if the solution is not complete.
The answer from Mattis Asp was very helpful but didn't quite work for me. I am new to this, so maybe these things are too obvious to need stating. But in case it helps someone else at my level, I had to:
Indent the properties under the Graph: declaration in the kv file (to get around an "invalid data after declaration" exception from the kv parser.
Add these includes:
language: lang-py
from kivy.properties import ObjectProperty
from kivy.app import App
from kivy.uix.widget import Widget
to the top of the python file.
Name the kv file to match the app class definition, so: graphLayout.kv (I had called it graph.kv so it was just ignored -- newbie mistake!)
I was getting "invalid property name" for graph_test : graph_test. So I commented that out and used the id instead, changing the line
self.graph_test.add_plot(plot)
to:
self.ids["graph_test"].add_plot(plot)
I bet at least some of these changes have to do with version differences in kivy so, for clarity, I am using kivy 1.9.1 and python 2.7.13.
Had the same problem. Here's the solution:
Generally, according to kivy documentation, in kv file:
#:import name x.y.z
is equivalent to:
from x.y import z as name
So you should use the following:
#:import MeshLinePlot kivy.garden.graph.MeshLinePlot
Worked in my case with Graph class but, to be honest, I didn't managed to add this plot to the graph yet.
I think inclement was on the right track. Using #:import should be able to import the file.
write this in the kv file:
#:import MeshLinePlot
it should be able to import the module, as the kv documentation shows, also