Guten Tag,
ich bin grad dabei eine GUI in Kivy zu schreiben. Diese ist relativ klein und hat 5 Buttons, einen Slider und ein Canvas(aktuelle noch Button).
Bisher habe ich einen Standard tab in dem ein Button ist, der eine Funktion auslöst, die mir einen zusätzlichen Tab öffnet mit oben besagten Buttons und Canvas.
Siehe bilder:
https://ibb.co/jUnm0V
https://ibb.co/dJKS7A
Nun hätte ich gerne wenn ich den Button set focus drücke, dass der slider den Wert 0 annimmt. Das klappt auch wenn es nur einen Tab gibt. Sobald ich zwei tabs habe, und den Button setfocus aus dem Tab 1 drücke verändert sich jedoch der slider aus Tab 2.
Ich dachte das könnte ich umgehen, wenn ich jedem Widget eines Tabs die ID übergebe, die der Länge der Liste der Tabs entspricht. Sprich alle widgets des ersten Tabs haben die ID 1 und die Widgets des zweiten Tabs die ID 2. Das klappt auch soweit.
Wenn ich nun per bind eine Methode an ein Widget knüpfe, wird ja auch das Objekt übergeben. Also habe ich die ID des übergebenen Objekts also des Buttons aus Tab 1 der ID des Sliders übergeben, sodass also auch der Slider des Tab 1 addressiert wird, was jedoch nicht klappt.
Wie könnte man sowas bewerkstelligen ?
Besten Dank im vorraus
Anbei hier der Code:
class RootWidget(BoxLayout):
def __init__(self,**kwargs):
super(RootWidget, self).__init__(**kwargs)
self.liste=[]
self.tp=TabbedPanel(do_default_tab=False)
self.add_widget(self.tp)
self.thd=TabbedPanelItem(text='+')
self.tp.add_widget(self.thd)
self.b_add=Button(text='add tab')
self.thd.add_widget(self.b_add)
self.b_add.bind(on_press=self.addtab)
def addtab(self, test=None):
self.tp.add_widget(self.createtabs())
def createtabs(self):
print('Button is pressed')
self.th=TabbedPanelItem(text='Tab '+str(len(self.tp.tab_list)),id=str(len(self.tp.tab_list)))
self.th.focus=self.th
#self.tp.add_widget(self.th)
self.Box=BoxLayout(orientation='vertical',id=str(len(self.tp.tab_list)))
self.BoxL=BoxLayout(id=str(len(self.tp.tab_list)))
self.BoxR=GridLayout(cols=6,id=str(len(self.tp.tab_list)))
self.th.add_widget(self.Box)
self.Box.add_widget(self.BoxR)
self.Box.add_widget(self.BoxL)
#should be the matplotlib canvas
self.b2=Button(text='btn 2',id=str(len(self.tp.tab_list)))
self.b_convert=Button(text='convert .nsdx to .txt',id=str(len(self.tp.tab_list)))
self.b_load=Button(text='load data',id=str(len(self.tp.tab_list)))
self.b_setfocus=Button(text='set focus',id=str(len(self.tp.tab_list)))
self.b_calcbeam=Button(text='calculate\nbeamproperties',id=str(len(self.tp.tab_list)))
self.b_export=Button(text='export plot',id=str(len(self.tp.tab_list)))
self.s_slider=Slider(id=str(len(self.tp.tab_list)),min=0,max=100,value=50)
#buttons
self.BoxL.add_widget(self.b2)
self.BoxR.add_widget(self.b_convert)
self.BoxR.add_widget(self.b_load)
self.BoxR.add_widget(self.b_setfocus)
self.BoxR.add_widget(self.b_calcbeam)
self.BoxR.add_widget(self.b_export)
self.BoxR.add_widget(self.s_slider)
#bind functions
self.b_convert.bind(on_press=self.callback)
self.b_setfocus.bind(on_press=self.setfocus)
return self.th
def setfocus(self,actualbutton):
actualbutton.id
self.s_slider.id=actualbutton.id
self.s_slider.value=0
return
Kivy GUi mit mehreren Tabs. Aktuellen tab fokussieren
Guten Tag,
ich bin grad dabei eine GUI in Kivy zu schreiben. Diese ist relativ klein und hat 5 Buttons, einen Slider und ein Canvas(aktuelle noch Button).
Bisher habe ich einen Standard tab in dem ein Button ist, der eine Funktion auslöst, die mir einen zusätzlichen Tab öffnet mit oben besagten Buttons und Canvas.
Siehe bilder:
https://ibb.co/jUnm0V
https://ibb.co/dJKS7A
Nun hätte ich gerne wenn ich den Button set focus drücke, dass der slider den Wert 0 annimmt. Das klappt auch wenn es nur einen Tab gibt. Sobald ich zwei tabs habe, und den Button setfocus aus dem Tab 1 drücke verändert sich jedoch der slider aus Tab 2.
Ich dachte das könnte ich umgehen, wenn ich jedem Widget eines Tabs die ID übergebe, die der Länge der Liste der Tabs entspricht. Sprich alle widgets des ersten Tabs haben die ID 1 und die Widgets des zweiten Tabs die ID 2. Das klappt auch soweit.
Wenn ich nun per bind eine Methode an ein Widget knüpfe, wird ja auch das Objekt übergeben. Also habe ich die ID des übergebenen Objekts also des Buttons aus Tab 1 der ID des Sliders übergeben, sodass also auch der Slider des Tab 1 addressiert wird, was jedoch nicht klappt.
Wie könnte man sowas bewerkstelligen ?
Besten Dank im vorraus
Anbei hier der Code:
ich bin grad dabei eine GUI in Kivy zu schreiben. Diese ist relativ klein und hat 5 Buttons, einen Slider und ein Canvas(aktuelle noch Button).
Bisher habe ich einen Standard tab in dem ein Button ist, der eine Funktion auslöst, die mir einen zusätzlichen Tab öffnet mit oben besagten Buttons und Canvas.
Siehe bilder:
https://ibb.co/jUnm0V
https://ibb.co/dJKS7A
Nun hätte ich gerne wenn ich den Button set focus drücke, dass der slider den Wert 0 annimmt. Das klappt auch wenn es nur einen Tab gibt. Sobald ich zwei tabs habe, und den Button setfocus aus dem Tab 1 drücke verändert sich jedoch der slider aus Tab 2.
Ich dachte das könnte ich umgehen, wenn ich jedem Widget eines Tabs die ID übergebe, die der Länge der Liste der Tabs entspricht. Sprich alle widgets des ersten Tabs haben die ID 1 und die Widgets des zweiten Tabs die ID 2. Das klappt auch soweit.
Wenn ich nun per bind eine Methode an ein Widget knüpfe, wird ja auch das Objekt übergeben. Also habe ich die ID des übergebenen Objekts also des Buttons aus Tab 1 der ID des Sliders übergeben, sodass also auch der Slider des Tab 1 addressiert wird, was jedoch nicht klappt.
Wie könnte man sowas bewerkstelligen ?
Besten Dank im vorraus
Anbei hier der Code:
Code: Alles auswählen
class RootWidget(BoxLayout):
def __init__(self,**kwargs):
super(RootWidget, self).__init__(**kwargs)
self.liste=[]
self.tp=TabbedPanel(do_default_tab=False)
self.add_widget(self.tp)
self.thd=TabbedPanelItem(text='+')
self.tp.add_widget(self.thd)
self.b_add=Button(text='add tab')
self.thd.add_widget(self.b_add)
self.b_add.bind(on_press=self.addtab)
def addtab(self, test=None):
self.tp.add_widget(self.createtabs())
def createtabs(self):
print('Button is pressed')
self.th=TabbedPanelItem(text='Tab '+str(len(self.tp.tab_list)),id=str(len(self.tp.tab_list)))
self.th.focus=self.th
#self.tp.add_widget(self.th)
self.Box=BoxLayout(orientation='vertical',id=str(len(self.tp.tab_list)))
self.BoxL=BoxLayout(id=str(len(self.tp.tab_list)))
self.BoxR=GridLayout(cols=6,id=str(len(self.tp.tab_list)))
self.th.add_widget(self.Box)
self.Box.add_widget(self.BoxR)
self.Box.add_widget(self.BoxL)
#should be the matplotlib canvas
self.b2=Button(text='btn 2',id=str(len(self.tp.tab_list)))
self.b_convert=Button(text='convert .nsdx to .txt',id=str(len(self.tp.tab_list)))
self.b_load=Button(text='load data',id=str(len(self.tp.tab_list)))
self.b_setfocus=Button(text='set focus',id=str(len(self.tp.tab_list)))
self.b_calcbeam=Button(text='calculate\nbeamproperties',id=str(len(self.tp.tab_list)))
self.b_export=Button(text='export plot',id=str(len(self.tp.tab_list)))
self.s_slider=Slider(id=str(len(self.tp.tab_list)),min=0,max=100,value=50)
#buttons
self.BoxL.add_widget(self.b2)
self.BoxR.add_widget(self.b_convert)
self.BoxR.add_widget(self.b_load)
self.BoxR.add_widget(self.b_setfocus)
self.BoxR.add_widget(self.b_calcbeam)
self.BoxR.add_widget(self.b_export)
self.BoxR.add_widget(self.s_slider)
#bind functions
self.b_convert.bind(on_press=self.callback)
self.b_setfocus.bind(on_press=self.setfocus)
return self.th
def setfocus(self,actualbutton):
actualbutton.id
self.s_slider.id=actualbutton.id
self.s_slider.value=0
return
Zuletzt geändert von Alsen am Donnerstag 22. November 2018, 09:34, insgesamt 1-mal geändert.
könntest du dann meinen vorherigen Kommentar löschen. Ich finde leider keine Option das selber zu bewerkstellige.__deets__ hat geschrieben: Mittwoch 21. November 2018, 16:58 Bitte benutz die Code-Tags, so ist das nicht zu entziffern.
Besten Dank
@Alsen: trotz code-Tags sind die Einrückungen kaputt. Hier gibt es einen Vorschau-Knopf, mit dem man sehen kann, ob der Post auch richtig dargestellt wird.
Zum Problem: Du überschreibst alle Attribute Deiner Klasse beim Erzeugen eines neuen Tabs. Du mußt für die Tabs eine eigene Klasse schreiben und die Tabs z.B. in einer Liste in RootWidget speichern.
Zum Problem: Du überschreibst alle Attribute Deiner Klasse beim Erzeugen eines neuen Tabs. Du mußt für die Tabs eine eigene Klasse schreiben und die Tabs z.B. in einer Liste in RootWidget speichern.
so habe es jetzt eingerückt. Danke war mir gar nicht aufgefallen.Sirius3 hat geschrieben: Donnerstag 22. November 2018, 09:23 @Alsen: trotz code-Tags sind die Einrückungen kaputt. Hier gibt es einen Vorschau-Knopf, mit dem man sehen kann, ob der Post auch richtig dargestellt wird.
Zum Problem: Du überschreibst alle Attribute Deiner Klasse beim Erzeugen eines neuen Tabs. Du mußt für die Tabs eine eigene Klasse schreiben und die Tabs z.B. in einer Liste in RootWidget speichern.
Also wenn ich jetzt ein Objekt meiner Klasse tab, was einem TabbedPanelItem entspricht an die Klasse RootWidget übergeben sollte und da in einer Liste speichere. Soll ich dann über eine For -Schleife die Objekte in der Liste an mein TabbedPanel tp anhängen?
Wenn das so gedacht ist verstehe ich dennoch nicht wie die Buttons dann eindeutig in den Tabs addressiert werden.
Außerdem ist es doch schon so wenn ich die Methode createtabs aufrufe über die Methode addtabs, dass ein Objekt der Klasse TabbedpanelItem also mein th an die Klasse Rootwidget übergeben wird bzw das alles ja in dieser Klasse passiert. Verstehe leider nicht ganz den Vorteil einer weiteren Klasse in diesem Fall. Die ID der erstellten Tabs und der darin liegenden Widgets ist ja bereits eindeutig. Also Tab 1 hat auch die ID 1 ,da diese sich nach der Länge der Tab_Liste orientiert, welche automatisch im hintergrund von Kivy angelegt wird.
Du beziehst dich an diversen Stellen auf Attribute, die du in createtabs anlegst. ZB self.s_slider. Wenn du jetzt 20 Tabs anlegst, dann zeigt self.s_slider immer nur auf den jeweils letzten. Auf die anderen kannst du nicht mehr zugreifen. Damit wird dann setfocus immer nur den letzten Tab erreichen.
Stattdessen musst du einen callback erzeugen, der das konkrete Objekt das er in den Focus ruecken soll kennt. ZB mit functools.partial.
Ganz generell legst du vieeeeel zu viel Zustand auf self an. Die ganzen Boxen, layouts etc. haben da ueberaupt nichts verloren. Die sind Teil deiner Widget-Hiearchie, und es gibt keinen Grund, die alle auf self. verfuegbar zu machen.
Stattdessen musst du einen callback erzeugen, der das konkrete Objekt das er in den Focus ruecken soll kennt. ZB mit functools.partial.
Ganz generell legst du vieeeeel zu viel Zustand auf self an. Die ganzen Boxen, layouts etc. haben da ueberaupt nichts verloren. Die sind Teil deiner Widget-Hiearchie, und es gibt keinen Grund, die alle auf self. verfuegbar zu machen.
@Alsen: dass Du irgendwelche IDs verteilst, ist dem Programm ziemlich egal. In setfocus überschreibst Du sogar die ID Deines Sliders, ohne das das irgendetwas bewirkt; das Attribut s_slider zeigt immer noch auf den zuletzt angelegten Slider. Alle vorhergenenden Tabs sind für Dich nicht mehr erreichbar.
Jeder Tab ein eigenes in sich abgeschlossenes Objekt. Das Knöpfe hat und Methoden, die auf diese Knöpfe reagieren. Es ist also ganz natürlich, das auch als Klasse zu implementieren. Dann ist auch klar, welcher Knopf zu welchem Slider gehört, und Du kannst Dir die IDs sparen.
Jeder Tab ein eigenes in sich abgeschlossenes Objekt. Das Knöpfe hat und Methoden, die auf diese Knöpfe reagieren. Es ist also ganz natürlich, das auch als Klasse zu implementieren. Dann ist auch klar, welcher Knopf zu welchem Slider gehört, und Du kannst Dir die IDs sparen.