How can i customise mapview's map marker popup like the image below in kivy? - kivy

MapMarker Popup
I am trying to customise a MapMarker Popup without using the regular 'source' property in kivy MapView class. I have tried creating the circle with the button effect and elevation effect, but I can't seem to remove the white box background behind the red circle, and adding text in the circle also eludes me. Any idea would really help. I have included my simple test code sample.
Here is my py code:
from kivymd.app import MDApp
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.behaviors import (CircularRippleBehavior, FakeCircularElevationBehavior, BackgroundColorBehavior)
from kivy.garden.mapview import MapMarkerPopup, MapMarker
from kivy.lang import Builder
from kivy.uix.behaviors import ButtonBehavior
class RoundedMarker(MDFloatLayout,
MapMarkerPopup,
CircularRippleBehavior,
FakeCircularElevationBehavior,
BackgroundColorBehavior,
ButtonBehavior):
pass
class TestApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "BlueGray"
return Builder.load_file('test.kv')
TestApp().run()
And my kv code:
<RoundedMarker>:
size_hint: None,None
size: "20dp","20dp"
radius: self.size[0] / 2
md_bg_color: 1, 0, 0, 1
MapView:
lat: 10
lon: 10
zoom: 5
RoundedMarker:
lat: 12
lon: 12
elevation: 5

Related

Since the rectangle is not a button, then how can I create a callback function to print('something') after clicking on that rectangle?

I have a rectangle in a canvas. Since the rectangle is not a button, then how can I create a callback function to print('something') after clicking on that rectangle?
In a button I can use on_release to call a function, but in rectangle how should I call a function after clicking on that rectangle?
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
#from kivy.graphics import *
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.animation import Animation
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock
Builder.load_string('''
<main>:
RelativeLayout :
size: root.width,root.height
canvas:
Color:
rgba:196/255, 195/255, 49/255,1
Rectangle:
size:470,root.height
''')
class main(Screen):
pass
class test(App):
def build(self):
sm = sm = ScreenManager()
sm.add_widget(main(name='main'))
Window.clearcolor=(55/255, 77/255, 33/255)
return sm
if __name__=='__main__':
test().run()

Not able to remove Widgets which were dynamically added to screen in Kivy

I am trying to add buttons dynamically when some text is typed on a text input. In order to achieve search select combo box in KIvy.
Even though i am able to add widgets when some text is typed , not able to remove those added widgets when the text typed is removed.
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix import dropdown
from kivy.uix.textinput import TextInput
# from kivymd.app import MDApp
kivy.require('1.9.0')
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.base import runTouchApp
from kivy.uix.screenmanager import ScreenManager,Screen
class ScreenOne(Screen):
def change_text(self,root,val):
pass
def create_dropdown(self,root,value):
print("value is :" + value)
if value == "":
result = ""
print(root.ids)
else:
lang = ["aa","aaa", "bsa","cds","dds", "ddyus"]
result = list(filter(lambda x: x.startswith(value), lang))
for i in range (0,len(result)):
self.textinput = Button()
self.textinput.id = 'textinput'+ str(i)
self.textinput.text = result[i]
self.textinput.size_hint= (.3, .06)
self.textinput.font_size= '14sp'
self.textinput.pos_hint= {'center_x': 0.5, 'center_y': 0.8-(i+1)/10, }
root.ids.screen1.add_widget(self.textinput)
sm = Builder.load_string("""
ScreenManager:
ScreenOne:
id: screen1
name: "screen_one"
TextInput:
id: input1
hint_text:'Select input Language'
size_hint: (.3,.06)
font_size: '14sp'
pos_hint:{'center_x':0.5,'center_y':0.8,}
on_text: root.ids.screen1.create_dropdown(root,input1.text)
""")
class demo(App):
def build(self):
return sm
app=demo()
# app.run()
runTouchApp(sm)
in UI when a is typed cahn see the below image
but when i clear the input text , i am still able to see the widgets added previously
I neet some logic to remove the added widgets when the text typed in input box is cleared.
Try adding this:
result = list(filter(lambda x: x.startswith(value), #from your cod
lang)) #from your code
if result == [] :
for widget in root.ids.screen1.children:
root.ids.screen1.remove_widget(widget)

Design where image is centered in the left half of the screen with scale and move possibility

I have this design of the UI:
The hardest part is to center the image in the left half of the screen, with scale and move possibility. I'm trying to do it with FloatLayout and somehow combine the behavior of Scatter and Image.
I have this code sofar:
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.config import Config
from kivy.uix.button import Button
from kivy.uix.scatter import Scatter
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
class Tedegraph(App):
def build(self):
mainbox = FloatLayout()
mainbox.add_widget(Button(text="Prev",
font_size="17dp",
size_hint=(.15, .15),
pos_hint={"left":1,
"center_y":0.5},
))
#sp = Scatter(scale=1, do_scale = True, do_rotation = False, pos_hint={"center_x":0.5, "center_y":0.5})
self.img = Image(source='img.png')
#sp.add_widget(self.img)
mainbox.add_widget(self.img) # images will change during execution
self.text_label = Label(text="HELLO", size_hint=(1, None), pos_hint={"center_x":0.5, "center_y":0.5}) # text will change during execution
self.text_label.bind(
width=lambda *x: self.text_label.setter('text_size')(self.text_label, (self.text_label.width, None))) # only wrapping functionality
mainbox.add_widget(self.text_label)
mainbox.add_widget(Button(text="Next",
font_size="17dp",
size_hint=(.15, .15),
pos_hint={"right":1,
"center_y":0.5},
))
return mainbox
if __name__ == "__main__":
Tedegraph().run()
I hope it is possible with keeping the ratio of the image. Thanks for suggestions
You can set the size and position of the Image widget when you create it:
self.img = Image(source='img.png', size_hint=(0.33,0.33), pos_hint={'center_x':0.33, 'center_y':0.5}, allow_stretch=True, keep_ratio=True)
And similarly, with the Label:
self.text_label = Label(text="HELLO\nThis is a Test", halign='center', size_hint=(0.33, None), pos_hint={"center_x":0.67, "center_y":0.5})

Need help on kivy mapview, works on windows, but just do not work on android, app just doesn't start

Below kivymapview works on windows, but doesnt work on Android. Please help
import sys
from kivy.base import runTouchApp
from kivy.lang import Builder
if __name__ == '__main__' and __package__ is None:
from os import sys, path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
import mapview
root = Builder.load_string("""
#:import sys sys
#:import MapSource mapview.MapSource
MapView:
lat: 50.6394
lon: 3.057
zoom: 13
map_source: MapSource(sys.argv[1], attribution="") if len(sys.argv) > 1 else "osm"
MapMarkerPopup:
lat: 50.6394
lon: 3.057
popup_size: dp(230), dp(130)
Bubble:
BoxLayout:
orientation: "horizontal"
padding: "5dp"
AsyncImage:
source: "http://upload.wikimedia.org/wikipedia/commons/9/9d/France-Lille-VieilleBourse-FacadeGrandPlace.jpg"
mipmap: True
Label:
text: "[b]Lille[/b]\\n1 154 861 hab\\n5 759 hab./km2"
markup: True
halign: "center"
""")
runTouchApp(root)
Finally, i had this fixed, looks like i had to start fresh to build it and had to amend requirements..These examples at https://github.com/kivy-garden/garden.mapview/tree/master/examples are really good to have the mapview work on Android. Also follow this link carefully https://github.com/kivy-garden/garden.mapview for better ideas :)

Kivy property observer objects left behind after ModalView is dismissed

I display in a popup (ModalView) a dynamically changing value. I use a method in my main widget class to open/dismiss the popup, and bind a Kivy StringProperty to a Label in the popup. There is a problem - each time the popup is dismissed, something is left behind. Listing all observers of the StringProperty shows how with each cycle of open/dismiss the number of objects accumulates. See the example code below. When I run this on Raspberry Pi 2 under Raspbian Jessie (Pixel) with 128M allocated for VRAM, within about a minute the progam stops functioning correctly - popup starts to show a black screen. Am I doing something silly in my code?
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.modalview import ModalView
from kivy.clock import Clock
from kivy.properties import StringProperty
from random import randint
Builder.load_string('''
#:kivy 1.9.2
<MainWidget>:
BoxLayout:
Button:
''')
class MainWidget(BoxLayout):
value_str = StringProperty()
def show_popup(self, even=True):
if even:
popup = ModalView(size_hint=(None, None), auto_dismiss=False, size=(700,480))
popup_label = Label(font_size = 200, text_size=self.size, halign='center', valign='center')
self.bind(value_str=popup_label.setter('text')) # value_str must be a Kivy StringProperty
popup.add_widget(popup_label)
self.value_str = str(randint(0,100))
popup.open()
else: # find all instances of ModalView and dismiss them
for widget in App.get_running_app().root_window.children:
if isinstance(widget, ModalView):
print "observers of value_str property:"
observers = self.get_property_observers('value_str')
for observer in observers:
print observer
widget.dismiss(force=True, animation=False)
Clock.schedule_once(lambda dt: self.show_popup(not even), 0.25)
class MyApp(App):
def build(self):
mw=MainWidget()
Clock.schedule_once(lambda dt: mw.show_popup(),0)
return mw
if __name__ == '__main__':
MyApp().run()
I found a workaround, inspired by this How to unbind a property automatically binded in Kivy language?
I now preserve the Label child by removing it from the ModalView and adding it to the MainWidget before ModalView is dismissed, then reversing this for the next popup. This way the property binding takes place only once so no new observers are created. The label can be made invisible by assigning an empty string to the bound property.
I think this may be a bug - ModalView dismiss() method should not leave behind observers, but cannot test with latest Kivy version (1.10.1.dev0).
Here's the code:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.modalview import ModalView
from kivy.clock import Clock
from kivy.properties import StringProperty
from random import randint
Builder.load_string('''
#:kivy 1.9.2
<MyLabel>:
font_size: 100
text_size: self.size
halign: 'center'
valign: 'center'
<MainWidget>:
Button:
background_color: 0.5, 0.5, 1, 1
''')
class MyLabel(Label):
pass
class MainWidget(FloatLayout):
value_str = StringProperty()
popup_label = MyLabel()
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
self.bind(value_str=self.popup_label.setter('text')) # value_str must be a Kivy StringProperty
self.add_widget(self.popup_label)
def show_popup(self, even=True):
if even:
popup = ModalView(size_hint=(None, None), auto_dismiss=False, size=(500,380))
self.remove_widget(self.popup_label)
popup.add_widget(self.popup_label)
self.value_str = str(randint(0,100))
popup.open()
else: # find all instances of ModalView and dismiss them
for widget in App.get_running_app().root_window.children:
if isinstance(widget, ModalView):
print "observers of value_str property:"
observers = self.get_property_observers('value_str')
for observer in observers:
print observer
widget.remove_widget(self.popup_label)
self.add_widget(self.popup_label)
self.value_str =''
widget.dismiss(force=True, animation=False)
Clock.schedule_once(lambda dt: self.show_popup(not even), 0.25)
class MyApp(App):
def build(self):
mw=MainWidget()
Clock.schedule_once(lambda dt: mw.show_popup(),0)
return mw
if __name__ == '__main__':
MyApp().run()

Resources