2015-11-19 24 views
9

Mam klienta gniazda, który wywołuje klasę View() za każdym razem, gdy otrzymuje wiadomość. Podzieliłem swój kod w taki sposób, aby ta klasa mogła po prostu używać print() lub dowolnej innej metody wyświetlania, tak jak lubię. Wydaje się jednak, że Kivy nie lubi tej metody. Rozszerzyłem klasę Kivy o BoxLayout dla mojego widoku i mogę zadzwonić do funkcji message(). Klasa wygląda mniej więcej tak:Jak zaktualizować elementy Kivy z wątku?

class View(BoxLayout): 
    def __init__(self, **kwargs): 
     super(View, self).__init__(**kwargs) 
     self.btn = Button(text='Default') 
     # Bind button press method 
     self.btn.bind(on_press=self.message) 
     self.add_widget(self.btn) 
    def message(self, message): 
     self.btn.text = 'Meow' 
     self.add_widget(Button(text='Meow')) 
     print(str(message)) 

Funkcja komunikatu jest rzeczywiście wywoływana i drukuje, ale interfejs nie aktualizuje się. Jednak po naciśnięciu przycisku aktualizuje on interfejs, a także drukuje.

Sprawdziłem, czy użyć przycisku StringProperty, aby zmodyfikować tekst przycisku, ale również się to nie udało. Tak jak w przypadku, gdy to co robię jest całkowicie niewykonalne, próbuję później narysować cały interfejs składający się z przycisków width * height, w postaci tablicy.

Każde wejście jest bardzo doceniane, doprowadzało mnie do szaleństwa.


EDIT 1 * Mam następnie na kilka uwag i próbowała kilka rzeczy. Dodałem klasę Clock i zlecam jej wykonanie metody update() z View. Metoda aktualizacji po prostu zmienia tekst kilku elementów. Zauważyłem, że działa, kiedy zaplanować go, jak pokazano poniżej:

def update(self, *args, **kwargs): 
    self.btn.text = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for i in range(32)) 
def message(self, message): 
    try: 
     print(message) 
     self.text = 'sending' 
    except Exception as e: 
     print(e) 

Gwint teraz po prostu przypisuje właściwości text widzianą w message(). Wykonywane są również okresowo uruchamiane metody update(), przypisujące losowy tekst. Problem jednak, że nie może ustawić tekstu. To nie działa:

def update(self, *args, **kwargs): 
    self.btn.text = self.text 

Czy muszę robić coś źle gdzie indziej, jakieś sugestie?


EDIT 2 * Błąd próbuję debugowania jest here.

+0

Nie można modyfikować elementów lub właściwości UI z wątku innego niż mainthread. Spójrz na klasę Kivy '' 'Clock''' dla planowania funkcji uruchamianych na mainthread. – bj0

+0

W odpowiedzi na @ bj0 można użyć automatycznego dekoratora '@ mainthread' do automatycznego zastosowania tej metody do funkcji. – inclement

+0

Hej, zmieniłem stanowisko z dalszymi ustaleniami.Doceniam pomoc i sugestię użycia 'Clock()', ale jak wspomniano powyżej, nadal nie jest w pełni funkcjonalna. – timur

Odpowiedz

3

Ponieważ nie publikujesz pełnego przykładu pracy, mogę tylko zgadywać, co robisz. Wygląda na to, że masz jakieś wydarzenie (wiadomość przychodzącą) w wątku i chcesz wyświetlić tekst, kiedy to nastąpi. Musisz "popchnąć" aktualizacje interfejsu głównego do wątku, ale nie musisz wykonywać okresowych aktualizacji za pomocą Clock, możesz po prostu zaplanować jednorazowe połączenia z Clock.schedule_once.

from functools import partial 

def update(self, text, *a): 
    self.btn.text = text 

def message(self, message): 
    Clock.schedule_once(partial(self.update, message), 0) 

Jak szorstki wspomniano, można to zrobić „push do głównego wątku” automatycznie z @mainthread dekoratora:

@mainthread 
def update(self, text): 
    self.btn.text = text 

def message(self, message): 
    update(message) 

W ten sposób, gdy dzwonisz update zostanie wykonany na głównym wątku.

+0

Moim zamiarem było nie opublikować pełnego przykładu pracy, ponieważ jest to część zadania i nie chciałbym, aby moja praca była plagiatowana. Teraz udostępniłem repo na GitHubie, dostępnym [tutaj] (https://github.com/TimurKiyivinski/falampous-coconut-appreciator). Od tego czasu usunąłem metody zegara i wróciłem do używania '@ mainthread'. Plik, którego szukasz, to 'client.py'. – timur

+0

Zwykle, gdy nie chcesz (lub nie możesz) opublikować kodu, nad którym pracujesz, po prostu stwórz minimalną aplikację, która ma problem, który próbujesz rozwiązać. Pomaga, gdy ludzie mogą odtworzyć twój problem. – bj0

+2

OK, po zerknięciu na twój kod, nie wygląda to na problem Kivy, ale na problem '' 'multiprocessing'''. Oddzielne procesy nie współdzielą pamięci, więc wiele odwołań między obiektami nie działa poprawnie. Zamiast tego użyj wątku i powinno działać tak, jak myślisz – bj0