Это о двух, как-то связанных проблемах. С одной стороны, речь идет о создании правильного подкласса, включающего метод «change_DF» для объекта DataFrame (DF) панд. (Веро 1 )С другой стороны, речь идет об использовании on_ {property} и ObjectProperty от kivy правильным способом, поэтому он обнаруживает изменения в упомянутой DF. (Prob 2 )
Относительно Prob1 есть несколько учебных пособий, например, от самой панды:https://pandas.pydata.org/pandas-docs/stable/development/extending.html#extending-subclassing-pandasи некоторые очень богатые детали, такие как:http://devanla.com/case-for-inheriting-from-pandas-dataframe.html
Подклассы Pandas DataFrame, обновления? (@stackoverflow)К сожалению, содержание, которое мне не известно на данный момент (придется подробно изучить этот класс / super / property / * args / ** kwargs / etc.… Не стесняйтесь учить меня в контексте данного фрагмента кода). ..!
Относительно Prob2 Я чувствую себя немного застрявшим с Prob1, потому что кажется, что вопрос заключается в том, что должен сравнивать kivy при проверке, были ли внесены какие-либо «соответствующие» измененияв "binded_kDF" ... (ну, мне кажется, что мне не хватает дополнительных знаний о принципах мощного EventDispatcher Kivy ... даже больше, чтобы изучать и изучать, очевидно)
Часть кода, о которой идет речь,готов к запуску с Py3.7.4:
from kivy.app import App
import pandas as pd
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class KivyDataFrame(pd.DataFrame):
@property
def _constructor(self):
return KivyDataFrame
def __init__(self, **kwargs):
super().__init__(**kwargs)
def change_DF(self, data):
# self.data = data # [Problem1] not how it works...
self.update(pd.DataFrame(data)) # ...and this one only works given (same structure with) same col-names
class KivySheet(GridLayout):
binded_kDF = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols=2
self.rows=2
self.counter = 1
def bind_kDF(self, kDF):
self.binded_kDF = kDF
def create_Sheet(self, *args):
print(self.binded_kDF)
for row in self.binded_kDF.to_numpy():
for value in row:
self.add_widget(Label(text=str(value)))
def update_Sheet(self, *args):
self.clear_widgets()
self.create_Sheet()
def on_binded_kDF(self, *args): # [Problem2] not called automatically when pressing Button (calling it beyond initiation; counter=2)
print("counter:", self.counter)
self.update_Sheet()
self.counter+=1
class AppFrame(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation="vertical"
self.kDF = KivyDataFrame(data={'col1': [1, 2], 'col2': [3, 4]})
self.kSh = KivySheet()
self.kSh.bind_kDF(self.kDF)
self.add_widget(self.kSh)
self.add_widget(Button(text="«change kDF»", on_press=lambda u:self.change_kDF()))
def change_kDF(self):
self.kDF.change_DF(data={'col1': [5, 6], 'col2': [7, 8]}) # change col-names and it doesn't work anymore (see Problem 1)
# self.kSh.update_Sheet() # necessary to have the wanted changing-effect (why Problem 2 has to be solved)
class MySheetApp(App):
def build(self):
return AppFrame()
if __name__ == '__main__':
MySheetApp().run()
Для обеих проблем я прокомментировал строку, которая не работала ( 1 ) или является обходным решением ( 2 ). Скомментируйте последнее, и вы увидите ожидаемый результат (включая «counter: 2»), который я ищу.
Сообщения об ошибках / предупреждениях, которые я получил относительно Prob1 (используя self.data = data ): UserWarning: Pandas не позволяет создавать столбцы с помощью нового имени атрибута - см. https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
... и относительно Prob2 : [ПРЕДУПРЕЖДЕНИЕ] [Свойство] Не удалось сравнить значения, поскольку " init () принимает 1 позиционный аргумент, но 2 задано". Чтобы избежать этого, рекомендуется установить для Force_dispatch значение True.