9804

Is it a bug in Kivy? DropDown + ScreenManager not working as expected

Question:

I've reproducable difficulties using ScreenManager and DropDown, if there are screens before the screen with the DropDown. I'm struggling with this for days now, since I'm a beginner, I assumed it's my fault here.<br /> I melted the code down to the core of the problem, so that my intended functionality is lost. Intended is an incremental search field, such that only appropriate options show up in the dropdown list. That's why I need an input widget bound to the dropdown-buttons. I've a solution for that, it's just not working as expected with the screenmanager.<br /> Consider this code, please:

from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.dropdown import DropDown from kivy.uix.button import Button from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.textinput import TextInput from kivy.properties import ListProperty, StringProperty import re from kivy.lang import Builder Builder.load_string(''' <Intro>: BoxLayout: Button: text: 'Press to go to SecondScreen' font_size: '20px' on_release: root.manager.current = 'SecondScreen' <SecondScreen>: ComboLayout: Label: text: "Dropdown on SecondScreen \\n\\n if ComboEdit.text doesn't have \\n a non-empty string assigned \\n code is broken!" font_size: '20px' ComboEdit: size_hint: .5, .5 pos_hint: {'center':(.5, .5)} on_text: self.parent.on_text(self, args[1]) text: 'X' ## <<<=== THIS IS NECESSARY, REALLY!?! font_size: '100px' multiline: False ''') class ComboEdit(TextInput): options = ListProperty(('',)) def __init__(self, **kw): ddn = self.drop_down = DropDown() ddn.bind(on_select=self.on_select) super(ComboEdit, self).__init__(**kw) def on_options(self, instance, value): ddn = self.drop_down ddn.clear_widgets() for option in value: but = Button(text=option, size_hint_y=None, height='36sp', on_release=lambda btn: ddn.select(btn.text)) ddn.add_widget(but) def on_select(self, instance, value): self.text = value class ComboLayout(BoxLayout): def on_text(self, instance, value): instance.options = [str(i) for i in range(0,8)] instance.drop_down.open(instance) class Intro(Screen): pass class SecondScreen(Screen): pass class BugDemoApp(App): def build(self): sm = ScreenManager() sm.add_widget(Intro(name='Intro')) sm.add_widget(SecondScreen(name='SecondScreen')) return sm if __name__ == '__main__': BugDemoApp().run()

By accident I found: I need to assign some non-empty string to ComboEdit.text, if not - making it a comment or assigning "" - I get this traceback:

File "C:/Users/ORANG/PycharmProjects/waldi/playground/widgets.py", line 56, in on_text instance.drop_down.open(instance) File "C:\Kivy-1.9.0-py2.7-win32-x64\kivy27\kivy\uix\dropdown.py", line 215, in open 'Cannot open a dropdown list on a hidden widget') kivy.uix.dropdown.DropDownException: Cannot open a dropdown list on a hidden widget

My questions are:

1) is it maybe a bug or am I doing something wrong here?

2) if it is a bug, where is the right place to announce it?

3) at the moment most important for me actually: now the user has to delete that given string in ComboEdit.text from the editfield by hand to replace it with his own input. This is so ugly. Do you have an idea for a workaround? Is it possible to make the dummy-text selected, so that if the user starts an input it will immediately be overridden?

I tried to do it like so

ComboEdit: ... focus: True select_all: True

but without effect?

Any acknowledment for the bug, any hint to get around it, any explanation what I'm doing wrong here would be very very very welcome!

Answer1:

Can be done in many (better?) ways, but this works.

from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.dropdown import DropDown from kivy.uix.button import Button from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.textinput import TextInput from kivy.properties import ListProperty, StringProperty import re from kivy.lang import Builder Builder.load_string(''' <Intro>: BoxLayout: Button: text: 'Press to go to SecondScreen' font_size: '20px' on_release: root.manager.current = 'SecondScreen' <SecondScreen>: ComboLayout: Label: text: "working?" font_size: '20px' ComboEdit: size_hint: .5, .5 pos_hint: {'center':(.5, .5)} font_size: '100px' multiline: False ''') class ComboEdit(TextInput): options = ListProperty([]) def __init__(self, **kw): super(ComboEdit, self).__init__(**kw) self.ddn = DropDown() self.ddn.bind(on_select=self.on_select) def on_options(self, instance, value): for option in value: but = Button(text=option, size_hint_y=None, height='36sp', on_release=lambda btn: self.ddn.select(btn.text)) self.ddn.add_widget(but) def on_select(self, instance, value): self.text = value def on_text(self, instance, value): self.options = [str(i) for i in range(0,8)] if not self.get_root_window(): return # do proceed if I'm not displayed <=> If have no parent self.ddn.open(self) class ComboLayout(BoxLayout): pass class Intro(Screen): pass class SecondScreen(Screen): pass class BugDemoApp(App): def build(self): sm = ScreenManager() sm.add_widget(Intro(name='Intro')) sm.add_widget(SecondScreen(name='SecondScreen')) return sm if __name__ == '__main__': BugDemoApp().run()

Hope it helps.

Recommend

  • Is it a bug in Kivy? DropDown + ScreenManager not working as expected
  • Kivy - My ScrollView doesn't scroll
  • Setting global font size in kivy
  • Custom Closable Tab in Kivy
  • How to animate the movement of a UILabel
  • Android OS back button takes me back to Expo projects screen
  • How to add an animated layer at a specific index
  • Pyglet not running properly on AMD HD4250
  • matplotlib Event Listeners Not Funcitoning In PyQT Widget
  • Wrapping the text of a Kivy Label
  • Custom signal from widget to widget
  • Java AWT GUI container to hold a top and a bottom half?
  • Kivy Update Dynamic Label Text
  • Inserting Boxes in Netbeans designer
  • Watermark text using imagettftext
  • I have a JApplet which has to display 3 Components. (2 JPanels and 1 Paint Method)
  • SAP Where-used list Standard programs
  • Android How to disabled predictive text programatically in samsung tab 2
  • Visual studio 2015 keystroke with mouse button
  • Kivy, TypeError: 'NoneType' object has no attribute '__getitem__'
  • Trying to get the char code of ENTER key
  • Saving Changes After In-App Purchase Has Been Purchased
  • Android fill_parent issue
  • How to install a .deb file on a jailbroken iphone programmatically?
  • Why value captured by reference in lambda is broken? [duplicate]
  • Jenkins: How To Build multiple projects from a TFS repository?
  • MySQL WHERE-condition in procedure ignored
  • jquery mobile loadPage not working
  • Web-crawler for facebook in python
  • Properly structure and highlight a GtkPopoverMenu using PyGObject
  • ExecuteAsync RestSharp to allow backgroundWorker CancellationPending c#
  • trying to dynamically update Highchart column chart but series undefined
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • Observable and ngFor in Angular 2
  • How can i traverse a binary tree from right to left in java?
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?
  • java string with new operator and a literal