In Kivy Text Input, cursor moves to the text end every time when changing font_size:
from kivy.app import App
from kivy.lang import Builder
KV = """
TextInput
on_touch_down: self.font_size+=1
"""
class MyApp(App):
def build(self):
self.root = Builder.load_string(KV)
MyApp().run()
Is there a way how to fix or workaround this behavior of TextInput?
Declare a class attribute, prev_cursor in class MyApp
Implement a method reset_cursor() to restore prev_cursor to TextInput's cursor
on_touch_down event, save current cursor position
on_touch_up event, use Kivy Clock.schedule_once() to invoke method reset_cursor()
Example
main.py
from kivy.app import App
from kivy.lang import Builder
KV = """
#:import Clock kivy.clock.Clock
TextInput:
on_touch_down:
app.prev_cursor = self.cursor
self.font_size += 1
on_touch_up:
Clock.schedule_once(lambda dt: app.reset_cursor(), 0.1)
"""
class MyApp(App):
prev_cursor = ()
def build(self):
self.root = Builder.load_string(KV)
def reset_cursor(self):
self.root.cursor = self.prev_cursor
MyApp().run()
Related
I am using Kivy to create a GUI.
If I go back to the Kivy operation after I activate another window, the Kivy button operation is ignored once.
This is a video of the operation.
I tried the following code
#-*- coding: utf-8 -*-
from kivy.lang import Builder
Builder.load_string("""
<TextWidget>:
BoxLayout:
orientation: 'vertical'
size: root.size
TextInput:
text: root.text
Button:
id: button1
text: "Test"
font_size: 48
on_press: root.buttonClicked()
""")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
class TextWidget(Widget):
text = StringProperty()
def __init__(self, **kwargs):
super(TextWidget, self).__init__(**kwargs)
self.text = ''
def buttonClicked(self):
self.text += "test\n"
class TestApp(App):
def __init__(self, **kwargs):
super(TestApp, self).__init__(**kwargs)
self.title = 'greeting'
def build(self):
return TextWidget()
if __name__ == '__main__':
TestApp().run()
Is there a solution to this problem?
I've asked in past questions how to add and remove buttons dynamically.
I want to know how to dynamically delete BoxLayout with Python's Kivy.
Here is my code.
#-*- coding: utf-8 -*-
from kivy.config import Config
from kivy.uix.button import Button
Config.set('graphics', 'width', 300)
Config.set('graphics', 'height', 300)
Config.set('input', 'mouse', 'mouse,multitouch_on_demand') # eliminate annoying circle drawing on right click
from kivy.lang import Builder
Builder.load_string("""
<AddItemWidget>:
BoxLayout:
size: root.size
orientation: 'vertical'
RecycleView:
size_hint: 1.0,1.0
BoxLayout:
id: box
orientation: 'vertical'
Button:
id: addButton
text: "Add Item"
on_press: root.buttonClicked()
""")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class RemovableButton(Button):
def on_touch_down(self, touch):
if touch.button == 'right':
if self.collide_point(touch.x, touch.y):
self.parent.remove_widget(self)
return True
return super(RemovableButton, self).on_touch_down(touch)
class AddItemWidget(Widget):
def __init__(self, **kwargs):
super(AddItemWidget, self).__init__(**kwargs)
self.count = 0
def buttonClicked(self):
self.count += 1
boxLayout = BoxLayout()
textinput = TextInput(text='Hello world'+str(self.count),size_hint_x=0.8)
deleteButton = RemovableButton(text='×',size_hint_x=0.2)
boxLayout.add_widget(deleteButton, index=1)
boxLayout.add_widget(textinput, index=1)
self.ids.box.add_widget(boxLayout, index=1)
deleteButton.bind(on_release=boxLayout.remove_widget)
class TestApp(App):
def __init__(self, **kwargs):
super(TestApp, self).__init__(**kwargs)
def build(self):
return AddItemWidget()
if __name__ == '__main__':
TestApp().run()
When the above code is executed, GUI will be launched and a line will be added by pressing the "Add Item" button.
I want to remove the line, so with the "x" button, as in the image below.
Its a little different than your other example.
For this, you need to use a different function to do the removing.
You also have to import partial like this: from functools import partial
And here is the changed AddItemWidget class:
class AddItemWidget(Widget):
def __init__(self, **kwargs):
super(AddItemWidget, self).__init__(**kwargs)
self.count = 0
def buttonClicked(self):
self.count += 1
boxLayout = BoxLayout()
textinput = TextInput(text='Hello world'+str(self.count),size_hint_x=0.8)
deleteButton = RemovableButton(text='×',size_hint_x=0.2)
boxLayout.add_widget(deleteButton, index=1)
boxLayout.add_widget(textinput, index=1)
self.ids.box.add_widget(boxLayout, index=1)
deleteButton.bind(on_release=partial(self.remove_btn, boxLayout)) # change this
def remove_btn(self, boxLayout, *args): # and add this
self.ids.box.remove_widget(boxLayout)
I am trying to get a kivy app to open a dropdown. I am following the example here.
When I run the app I can click on the button, but no dropdown appears.
I am missing something simple, but I just can't see it. Can someone help please.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.lang import Builder
root = Builder.load_string('''
<MainFrame>:
BoxLayout:
orientation: 'vertical'
Label:
text: 'Hello'
Button:
text: 'open dropdown'
on_press: root.on_menu_button_click()
''')
class MainFrame(Screen):
def __init__(self, **kwargs):
super(MainFrame, self).__init__(**kwargs)
self.dropdown = self._create_dropdown()
def _create_dropdown(self):
dropdown = DropDown()
for index in range(5):
btn = Button(text='Value %d' % index, size_hint_y=None, height=44)
btn.bind(on_release=lambda btn: dropdown.select(btn.text))
dropdown.add_widget(btn)
return dropdown
def on_menu_button_click(self):
self.dropdown.open
class BasicApp(App):
def build(self):
return MainFrame()
if __name__ == '__main__':
BasicApp().run()
You have to use the open() method and pass the button, you must also use on_release instead of on_press.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.lang import Builder
root = Builder.load_string('''
<MainFrame>:
BoxLayout:
orientation: 'vertical'
Label:
text: 'Hello'
Button:
id: btn # <---
text: 'open dropdown'
on_release: root.on_menu_button_click(btn) # <---
''')
class MainFrame(Screen):
def __init__(self, **kwargs):
super(MainFrame, self).__init__(**kwargs)
self.dropdown = self._create_dropdown()
def _create_dropdown(self):
dropdown = DropDown()
for index in range(5):
btn = Button(text='Value %d' % index, size_hint_y=None, height=44)
btn.bind(on_release=lambda btn: dropdown.select(btn.text))
dropdown.add_widget(btn)
return dropdown
def on_menu_button_click(self, widget): # <---
self.dropdown.open(widget) # <---
class BasicApp(App):
def build(self):
return MainFrame()
if __name__ == '__main__':
BasicApp().run()
The above is clearly mentioned in the example as it indicates:
...
# show the dropdown menu when the main button is released
# note: all the bind() calls pass the instance of the caller (here, the
# mainbutton instance) as the first argument of the callback (here,
# dropdown.open.).
mainbutton.bind(on_release=dropdown.open)
...
Can someone tell me how to show highlight switch widget when I set focus on Switch?It should be look like focused.
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.core.window import Window
from kivy.properties import StringProperty, ObjectProperty
from kivy.clock import Clock
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (200, 150)
class User(Screen):
swtch = ObjectProperty(None)
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
Clock.schedule_once(self.swtch_focus, 1)
def swtch_focus(self, *args):
self.swtch.focus = True
class Test(App):
def build(self):
return self.root
if __name__ == '__main__':
Test().run()
test.kv
User:
swtch: swtch
BoxLayout:
orientation: "vertical"
GridLayout:
cols: 2
padding: 20, 20
spacing: 10, 10
Switch:
id:swtch
There is hoverableBehaviour in github here is the link https://gist.github.com/KeyWeeUsr/3166f13d363d5558f481d538c6a5d2aa copy the code and create a module to your current directory and import it to use it which you can add to your Widget to have the on focus or highlight feature. This is how to do.
class Highlight(HoverBehavior,Screen):
def on_enter(self):
print('Focus on')
def on_leave(self):
print('Focus off')
I`m trying to make a simple GUI with Kivy(1.9) using a popup to change some options from a list and save it to a db, for example. When i call popup(), Python(3.4.5) crash..
main.py:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.properties import ListProperty
from kivy.lang import Builder
Builder.load_string('''
<PopView>:
title: 'Popup'
size_hint: (.8, .8)
Button:
text: 'Save'
''')
class MainApp(App):
def build(self):
b = Button(text='click to open popup')
b.bind(on_click=self.view_popup())
return b
def view_popup(self):
a=PopView()
a.data=[1,2,3,4] #e.g.
a.open()
class PopView(Popup):
def __init__(self):
self.data = ListProperty()
def save_data(self):
#db.query(self.data)
pass
if __name__ in ('__main__', '__android__'):
MainApp().run()
Here are a couple of things.
First, if you are going to overite __init__ remember to call super
But in this simple case you dont need __init__
Then, there is no on_click event on Button. Use on_press or on_release
And last but not least: You dont need to call the method in the bind function. Only pass it (without ())
So now your example looks like this.
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.properties import ListProperty
from kivy.lang import Builder
Builder.load_string('''
<PopView>:
title: 'Popup'
size_hint: (.8, .8)
Button:
text: 'Save'
''')
class MainApp(App):
def build(self):
b = Button(text='click to open popup')
b.bind(on_release=self.view_popup)
return b
def view_popup(self,*args):
a = PopView()
a.data=[1,2,3,4] #e.g.
a.open()
class PopView(Popup):
data = ListProperty()
def save_data(self):
#db.query(self.data)
pass
if __name__ in ('__main__', '__android__'):
MainApp().run()