【问题标题】:Kivy Multiselect Spinner: 2nd time adding an item, spinner behaves oddlyKivy 多选微调器:第二次添加一个项目,微调器的行为很奇怪
【发布时间】:2017-07-23 16:28:34
【问题描述】:

Kivy 1.10.0 并为我的 Kivy 语言使用 kv 文件。

Python 3.6

我有一个适用于 mysql3 的应用程序。该应用程序的一页允许我将“闪存卡”添加到数据库中。添加闪存卡时的表单元素之一使用 Multiselect Spinner 添加一个或多个标签,然后将此数据保存到数据库中。第一次访问此页面时,我可以使用微调器并按预期添加所有内容。然后,如果我回去尝试添加第二张闪存卡,即使表单已清除并且一切看起来都与我第一次添加闪存卡时完全一样,微调器的行为也很奇怪。数据似乎存储在某个地方,如第三个 gif 所示,并以某种方式加载回微调器数据。 (“甲板”微调器的问题是相同的。)

这个 gif 显示它在我第一次添加新卡时正常工作:

这个 gif 显示了我第二次添加新卡(无论我在添加两张卡之间做什么,都会发生这种情况,除了完全退出应用程序):

这个 gif 显示数据似乎被保留了:

由于代码很长,我只会添加我认为相关的内容。如有遗漏,请告诉我,我会立即补充。

class NewFlashCardScreen(Screen):
    data = DictProperty({})
    data_fc_tag_ids = DictProperty({})
    data_fc_deck_ids = DictProperty({})
    __events__ = ('on_submit',)
    fc_tag_spinner_list = ListProperty(None)
    fc_deck_spinner_list = ListProperty(None)

    def on_parent(self, widget, parent):
        gd = App.get_running_app()
        self.fc_tag_spinner_list = []
        fc_tag_list = Queries.get_fc_tag_list()
        if len(fc_tag_list) > 0:
            for fc_tag in fc_tag_list:
                self.fc_tag_spinner_list.append(fc_tag[1])
                self.data_fc_tag_ids[fc_tag[1]] = fc_tag[0]
        else:
            self.fc_tag_spinner_list.append("")
        self.fc_deck_spinner_list = []
        fc_deck_list = Queries.get_fc_deck_list()
        if len(fc_deck_list) > 0:
            for fc_deck in fc_deck_list:
                self.fc_deck_spinner_list.append(fc_deck[1])
                self.data_fc_deck_ids[fc_deck[1]] = fc_deck[0]
        else:
            self.fc_deck_spinner_list.append("")

    def get_spinner_lists(self):
        pass

    def on_submit(self, data):
        gd = App.get_running_app()
        self.data['orig'] = gd.glob_dict['orig']
        title = data['fc_title'] if data['fc_title'] else " "
        front = data['fc_front'] if data['fc_front'] else " "
        back = data['fc_back'] if data['fc_back'] else " "
        difficulty = data['fc_difficulty'] if data['fc_difficulty'] else 0
        self.fc_id = MiscFuns.get_id(16)
        try:
            c.execute("""
                        INSERT INTO `tbl_learning_flash_cards` (`fc_id`,`fc_title`,`fc_front`,`fc_back`,`fc_difficulty`)
                        VALUES (?,?,?,?,?)
                    """, (self.fc_id, title, front, back, difficulty))
            conn.commit()
        except sqlite3.Error as e:
            print("An error occurred:", e.args[0])


class MultiSelectSpinner(Button):

    dropdown = ObjectProperty(None)
    values = ListProperty([])
    selected_values = ListProperty([])

    def __init__(self, **kwargs):
        self.values.clear()
        self.selected_values.clear()
        self.bind(dropdown=self.update_dropdown)
        self.bind(values=self.update_dropdown)
        super(MultiSelectSpinner, self).__init__(**kwargs)
        self.bind(on_release=self.toggle_dropdown)

    def toggle_dropdown(self, *args):
        if self.dropdown.parent:
            self.dropdown.dismiss()
        else:
            self.dropdown.open(self)

    def update_dropdown(self, *args):
        if not self.dropdown:
            self.dropdown = DropDown()
        values = self.values
        if values:
            if self.dropdown.children:
                self.dropdown.clear_widgets()
            for value in values:
                b = Factory.MultiSelectOption(text=value)
                b.bind(state=self.select_value)
                self.dropdown.add_widget(b)

    def select_value(self, instance, value):
        if value == 'down':
            if instance.text not in self.selected_values:
                self.selected_values.append(instance.text)
        else:
            if instance.text in self.selected_values:
                self.selected_values.remove(instance.text)

    def on_selected_values(self, instance, value):
        if value:
            self.text = ';'.join(value)
        else:
            self.text = ''

还有kv文件:

<NewFlashCardScreen>:
BoxLayout:
    orientation: "vertical"
    BoxLayout:
        size_hint_y: 0.1
        Label:
            size_hint_x: 0.2
            text: "Card Title"
            text_size: self.text_size
            valign: 'middle'
        TextInput:
            id: new_fc_title
            multiline: False
            padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
            text: root.data['fc_title'] if 'fc_title' in root.data else ""
            on_text: root.data['fc_title'] = self.text
        Label:
            size_hint_x: 0.2
            text: "Difficulty"
            text_size: self.text_size
            valign: 'middle'
    BoxLayout:
        size_hint_y: 0.1
        Label:
            size_hint_x: 0.2
            text: "Card Tag(s)"
            text_size: self.text_size
            valign: 'middle'
        BoxLayout:
            MultiSelectSpinner:
                id: new_fc_tag
                text: root.data['fc_tags'] if 'fc_tags' in root.data else "Select tag(s)"
                values: root.fc_tag_spinner_list
                on_text: root.data['fc_tags'] = self.text
            Button:
                size_hint_x: 0.3
                text: "New Tag"
                on_release: lib.Navigation.page_nav(dest='new_flash_card_tag', orig='new_flash_card', edit=False)
        BoxLayout:
            size_hint_x: 0.2
            TextInput:
                padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
                id: new_fc_difficulty
                text: root.data['fc_difficulty'] if 'fc_difficulty' in root.data else "0"
                on_text: root.data['fc_difficulty'] = self.text
    BoxLayout:
        size_hint_y: 0.1
        Label:
            size_hint_x: 0.2
            text: "Card Deck(s)"
            text_size: self.text_size
            valign: 'middle'
        BoxLayout:
            MultiSelectSpinner:
                id: new_fc_deck
                text: root.data['fc_decks'] if 'fc_decks' in root.data else "Select deck(s)"
                values: root.fc_deck_spinner_list
                on_text: root.data['fc_decks'] = self.text
            Button:
                size_hint_x: 0.3
                text: "New Deck"
                on_release: lib.Navigation.page_nav(dest='new_flash_card_deck', orig='new_flash_card', edit=False)
        BoxLayout:
            size_hint_x: 0.2
    BoxLayout:
        orientation: "vertical"
        Label:
            size_hint_y: 0.1
            text: "Card Front"
        BoxLayout:
            TextInput:
                id: new_fc_front
                multiline: True
                text: root.data['fc_front'] if 'fc_front' in root.data else ""
                on_text: root.data['fc_front'] = self.text
            RstDocument:
                text: new_fc_front.text
                show_errors: True
    BoxLayout:
        orientation: "vertical"
        Label:
            size_hint_y: 0.1
            text: "Card Back"
        BoxLayout:
            TextInput:
                id: new_fc_back
                multiline: True
                text: root.data['fc_back'] if 'fc_back' in root.data else ""
                on_text: root.data['fc_back'] = self.text
            RstDocument:
                text: new_fc_back.text
                show_errors: True
    BoxLayout:
        size_hint_y: 0.2
        Button:
            text: "Cancel"
            on_release: lib.Navigation.page_nav(dest='prev_page', orig='new_flash_card', edit=False)
        Button:
            text: "Submit"
            on_release: root.dispatch('on_submit', root.data)

我已尝试清除字典文件 self.data、self.data_fc_tag_ids 和 self.data_fc_deck_ids,但这无济于事。

我不知道保留了哪些数据以及如何删除它。谢谢。

【问题讨论】:

  • 你是如何定义MultiSelectSpinner的?您在下拉菜单中使用了哪些按钮?您可能只需要重置微调器的状态。但很难说代码发生了什么。
  • 由于 MultiSelectSpinner 是一个内置的 Kivy 类,而且我使用的是 kv 文件,我什至不必导入它。我用fc_tag_spinner_list = ListProperty(None) 设置它,设置它的值然后我所要做的就是从MultiSelectSpinner: 部分下的kv 文件中调用它。仅此而已。
  • 很抱歉,但似乎找不到。我搜索了文档,没有任何返回。这比 1.10.0 更新吗?你能分享一个链接吗?谢谢。
  • 感谢您关注 Mox。我目前在 GitHub 上没有该应用程序,因此我无法共享链接,但是我遇到问题的部分没有什么比我在问题中提出的更多了。它使用的是 Kivy 1.10.0。
  • 我想你误会了。我在 Kivy 的源代码中寻找 MultiSelectSpinner。你说它是 kivy 内置的,但我找不到。

标签: python-3.x kivy kivy-language


【解决方案1】:

约翰 别生气!我得到了解决方案.. 这是路径:在 kv 文件中,我们可以首先提及 Dropdown 小部件,在下拉下我们将提及复选框,这就是答案.. 这是 kv 文件代码:

DropDown:
                    padding: 0, 0, 0, root.width * 0.4
                    id: dropdown
                    on_select: btn.text = '{}'.format(args[1])

                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: person
                            text: 'Person'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(person.text, self.active)
                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: vehicle
                            text: 'Vehicle'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            id: vecle
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(vehicle.text, self.active)
                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: aircraft
                            text: 'Air_craft'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(aircraft.text, self.active)

.py 文件:

class My_class(BoxLayout):

def on_checkbox_active(checkbox_ref, name, checkbox_value):
    if checkbox_value:
        print('', name, 'is active')
    else:
        print('', name, 'is inactive')
pass

【讨论】:

  • 该小部件将让您在下拉菜单中选择多个选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多