Frage

Ich versuche Kivy zu lernen :wie man listview und seine Elementbindung manipuliert.Hier ist ein Teil meines Codes, in dem ich ein Problem habe.

Bearbeiten:Ich habe den Code geändert oder vielmehr alles hinzugefügt, anstatt nur einen Teil zu posten.

import re
import sys
import json
import requests
import datetime
from datetime import datetime
from random import randint

import time
#Kivy Imports
import  kivy
from kivy.app import App
from kivy.uix import label
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button

from kivy.properties import StringProperty, ObjectProperty

from kivy.adapters.listadapter import ListAdapter
from kivy.uix.listview import ListView, ListItemButton
from kivy.lang import Builder
from kivy.adapters import dictadapter
from kivy.uix.modalview import ModalView
#Kivy version
kivy.require('1.7.0')
#MainLayout Class with the GridView
class MainLayout(GridLayout):

    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)

        self.text_input = ObjectProperty()  #reference to the textinput from .kv
        self.apps_list =  ObjectProperty()
        self.logo100 = ObjectProperty()        

        self.domain = self.ids.text_input.text 
        self.apps_list = self.ids.apps_list 
        self.logo100 = self.ids.logo100


        self.apps_list.adapter.bind(on_selected_item=self.callback)

    def on_enter(self):
        apps = {'a', 'b', 'c', 'd', 'e' ,'f', 'g'}
        if apps != None :          
            list_adapter = ListAdapter(data = apps, 
                                       selection_mode = 'single',
                                       allow_empty_selection = True,
                                       cls = ListItemButton,
                                       sorted_keys=[])

        self.apps_list.adapter = list_adapter


    def callback(self, adapter):
        if len(self.adapter.selection) == 0:
            print "No selected item"
        else:
            print self.adapter.selection[0].text       


class WabApp(App):
    def build(self):
        return MainLayout()

if __name__ == '__main__':
    WabApp().run()

Für die .kv-Datei, die ich verwendet habe :

<MainLayout>:

    rows: 2
    orientation: 'horizontal'


    GridLayout:
        cols: 2
        orientation: 'vertical'
        row_force_default: True 
        row_default_height: 50

        Image:
            id: logo100
            source: 'logo100.png'
            size_hint: [.2, .1]
            texture: self.texture
            size: self.texture_size

        TextInput:
            id: text_input
            markup: True
            text: ''
            font_size: 32
            size_hint: [1.8, .1]
            multiline: False                    
            on_text_validate: root.on_enter()
            hint_text: 'test'
    ListView:
        id: apps_list
        allow_empty_selection: True

Wenn ich auf ein Element aus der Liste klicke, passiert nichts.

Ich weiß auch nicht, ob ich es benutzen soll :

self.apps_list.adapter.bind(on_selected_item=self.callback)

oder

self.apps_list.adapter.bind(on_selection_change=self.callback)

Tatsächlich zeigt weder das erste noch das zweite ein Wort auf der Konsole an.Irgendwelche Vorschläge ?

War es hilfreich?

Lösung

Es gibt mehrere Dinge, die Sie falsch machen, aber Ihr Hauptfehler ist die Nummer 2 der folgenden Liste:

  1. Sie können verwenden on_selection change.Soweit ich weiß, gibt es keine on_selected_item.

  2. Sie binden das Ereignis, bevor Sie das Objekt erstellen.Die folgende Anweisung befindet sich in der initiieren:

    self.apps_list.adapter.bind(on_selected_item=self.callback)
    

    aber es sollte nach dem Erstellen des neuen im on_enter sein ListAdapter.Es könnte die letzte Zeile der Methode sein.Siehe die Codes unten.

    def on_enter(self):
        ...
        self.apps_list.adapter = list_adapter
        self.apps_list.adapter.bind(on_selection_change=self.callback)
    
  3. MainLayout enthält keinen Adapter.In der Methode on_enter, Referenz self.adapter sollte geändert werden in adapter (parameter der Methode) oder self.apps_list.adapter.

  4. Die Art und Weise, wie Sie die Verweise auf erstellen domain, apps_list und logo100 ist seltsam.Ich wusste nichts von der Existenz des ids attribut im Widget aber Sie können es direkt verwenden.Also, statt:

    self.apps_list.adapter = list_adapter
    

    Sie können verwenden:

    self.ids.apps_list.adapter = list_adapter
    

    Es besteht keine Notwendigkeit der Überlastung der _initiieren_ methode überhaupt.

Wenn Sie nicht auf die zugreifen möchten apps_lists durch die ids attribut, dann können Sie Attribute in die Kopfzeile der Kivy-Sprache einfügen:

<MainLayout>:
    text_input: text_input
    apps_list: apps_list
    logo100: logo100

    rows: 2

Hier ist der endgültige funktionierende Python-Code, der alle genannten Änderungen enthält.Ich habe die Importe weggelassen.

# ... your imports
class MainLayout(GridLayout):

    def on_enter(self):
        apps = {'a', 'b', 'c', 'd', 'e' ,'f', 'g'}
        if apps != None :
            list_adapter = ListAdapter(data = apps, selection_mode = 'single',
            allow_empty_selection = True, cls = ListItemButton, sorted_keys=[])
        self.apps_list.adapter = list_adapter
        self.apps_list.adapter.bind(on_selection_change=self.callback)

    def callback(self, adapter):
        if len(adapter.selection) == 0:
            print "No selected item"
        else:
            print adapter.selection[0].text

class WabApp(App):
    def build(self):
        return MainLayout()

if __name__ == '__main__':
    WabApp().run()

Andere Tipps

Ihr Codebeispiel ist durcheinander und sehr unvollständig?Könnten Sie eine einfache funktionierende App geben, die Ihr Problem zeigt?

Ich kann ein paar Vorschläge machen, um Dinge zu beheben, von denen einer das Verhalten verursachen würde, das Sie sehen:

1) Du tust es self.apps_list = ObjectProperty() in der __init__ Methode.Das ist falsch, es erstellt keine ObjectProperty mit irgendeinem nützlichen Verhalten, sondern erstellt nur ein neues Attribut des Instanz ihrer Klasse, die Sie sogar in der nächsten Zeile ersetzen!Stattdessen sollten Sie Eigenschaften auf Klassenebene erstellen (z.die gleiche Ebene wie Funktionsmethoden).

2) Sie fügen Code ein, der an einen Adapter gebunden ist on_selection_change ereignis, aber auch code in on_enter das ersetzt den Adapter.Ihr Beispiel ist zu unvollständig, um zu wissen, wie oder wann letzteres aufgerufen wird, aber wenn es passiert, bevor Sie auf ein Listenelement klicken, kann Ihr Ereignis niemals ausgelöst werden, da der Adapter, an den es gebunden ist, ersetzt wurde.Dies würde das Verhalten ergeben, das Sie sehen.Um das Problem zu beheben, ersetzen Sie den Adapter nicht und binden Sie den Rückruf nicht erneut an den neuen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top