This is mostly me not grasping object oriented programming, but involving the clock function
I want my GUI to have a button that starts a constantly updating function (scheduled using the clock function). And also want that GUI to have a button that ends the constantly updating function. (or is there a better way to accomplish this? put it in an if statement? boolean that changes when I press that button, would that value update on the python side?)
import kivy
import sqlite3
import sched, time
import smbus
import time
from Naked.toolshed.shell import execute_js, muterun_js
import os
import signal
import multiprocessing, signal
from kivy.uix.behaviors.button import ButtonBehavior
from kivy.uix.button import Button
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.base import runTouchApp
from kivy.clock import Clock
from kivy.properties import ListProperty
from kivy.properties import ObjectProperty
from kivy.vector import Vector
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.event import EventDispatcher
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.stacklayout import StackLayout
from kivy.core.image import Image
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition, WipeTransition, SwapTransition
bus = smbus.SMBus(1)
address = 0x04
p = multiprocessing.Process(target = muterun_js,args=('iss_telemetry.js',)) #might delete this
conn = sqlite3.connect('iss_telemetry.db') #sqlite database call change to include directory
c = conn.cursor()
val = ""
def StringToBytes(val):
retVal = []
for c in val:
retVal.append(ord(c))
return retVal
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
class CalibrateScreen(Screen):
pass
class ManualControlScreen(Screen):
def __init__(self, **kwargs):
super(ManualControlScreen, self).__init__(**kwargs)
def i2cWrite(self, *args):
bus.write_i2c_block_data(address, 0, StringToBytes(*args))
class MimicScreen(Screen, EventDispatcher):
def __init__(self, **kwargs):
super(MimicScreen, self).__init__(**kwargs)
class MainScreenManager(ScreenManager):
pass
class MyButton(Button):
pass
def point_inside_polygon(x, y, poly):
...
class TriangleButton(ButtonBehavior, Widget):
...
class MainApp(App):
event = Clock.schedule_interval(self.update_labels, 1)
event()
event.cancel()
def build(self):
self.mimic_screen = MimicScreen(name = 'mimic')
root = ScreenManager(transition=WipeTransition())
root.add_widget(MainScreen(name = 'main'))
root.add_widget(CalibrateScreen(name = 'calibrate'))
root.add_widget(self.mimic_screen)
root.add_widget(ManualControlScreen(name = 'manualcontrol'))
root.current= 'main'
# Clock.schedule_interval(self.update_labels, 1)
return root
def clockStart(self):
event()
def clockEnd(self):
event.cancel()
def i2cWrite(self, *args):
bus.write_i2c_block_data(address, 0, StringToBytes(*args))
def update_labels(self, dt):
c.execute('select two from telemetry')
values = c.fetchall()
psarj = values[0]
ssarj = values[1]
ptrrj = values[2]
strrj = values[3]
beta1b = values[4]
beta1a = values[5]
beta2b = values[6]
beta2a = values[7]
beta3b = values[8]
beta3a = values[9]
beta4b = values[10]
beta4a = values[11]
aos = values[12]
self.mimic_screen.ids.psarjvalue.text = str(psarj[0])[:-5]
self.mimic_screen.ids.ssarjvalue.text = str(ssarj[0])[:-5]
self.mimic_screen.ids.ptrrjvalue.text = str(ptrrj[0])[:-5]
self.mimic_screen.ids.strrjvalue.text = str(strrj[0])[:-5]
self.mimic_screen.ids.beta1bvalue.text = str(beta1b[0])[:-5]
self.mimic_screen.ids.beta1avalue.text = str(beta1a[0])[:-5]
self.mimic_screen.ids.beta2bvalue.text = str(beta2b[0])[:-5]
self.mimic_screen.ids.beta2avalue.text = str(beta2a[0])[:-5]
self.mimic_screen.ids.beta3bvalue.text = str(beta3b[0])[:-5]
self.mimic_screen.ids.beta3avalue.text = str(beta3a[0])[:-5]
self.mimic_screen.ids.beta4bvalue.text = str(beta4b[0])[:-5]
self.mimic_screen.ids.beta4avalue.text = str(beta4a[0])[:-5]
Builder.load_string('''
#:kivy 1.8
#:import kivy kivy
#:import win kivy.core.window
<MainScreen>:
...
<ManualControlScreen>:
...
<CalibrateScreen>:
...
<MimicScreen>:
name: 'mimic'
FloatLayout:
psarjvalue: psarjvalue
id: mimicscreenlayout
Image:
source: 'iss1.png'
allow_stretch: True
keep_ratio: False
...
Button:
id: mimicstartbutton
size_hint: 0.25,0.1
pos_hint: {"x": 0.07, "y": 0.6}
text: 'MIMIC'
disabled: False
font_size: 30
on_release: telemetrystatus.text = 'Sending Telemetry...'
on_release: app.clockStart()
on_release: mimicstopbutton.disabled = False
on_release: mimicstartbutton.disabled = True
Button:
id: mimicstopbutton
size_hint: 0.25,0.1
pos_hint: {"x": 0.07, "y": 0.4}
text: 'Stop'
disabled: True
font_size: 30
on_release: telemetrystatus.text = 'I2C Stopped'
on_release: app.clockStop()
on_release: mimicstopbutton.disabled = True
on_release: mimicstartbutton.disabled = False
Button:
size_hint: 0.3,0.1
pos_hint: {"Left": 1, "Bottom": 1}
text: 'Return'
font_size: 30
on_release: app.clockStop()
on_release: root.manager.current = 'main'
<TriangleButton>:
...
''')
if __name__ == '__main__':
MainApp().run()
Here's the relevant class:
class MainApp(App):
event = Clock.schedule_interval(self.update_labels, 1)
event()
event.cancel()
def build(self):
self.mimic_screen = MimicScreen(name = 'mimic')
root = ScreenManager(transition=WipeTransition())
root.add_widget(MainScreen(name = 'main'))
root.add_widget(CalibrateScreen(name = 'calibrate'))
root.add_widget(self.mimic_screen)
root.add_widget(ManualControlScreen(name = 'manualcontrol'))
root.current= 'main'
# Clock.schedule_interval(self.update_labels, 1)
return root
def clockStart(root):
event()
def clockEnd(root):
event.cancel()
def i2cWrite(self, *args):
bus.write_i2c_block_data(address, 0, StringToBytes(*args))
def update_labels(self, dt):
...
And here's the relevant part of the kv code (reduced)
<MimicScreen>:
name: 'mimic'
FloatLayout:
...
Button:
...
on_release: app.clockStart()
Button:
...
on_release: app.clockStop()
Button:
...
on_release: app.clockStop()
So when I try to run it like this it complains about not knowing what event is. I was under the impressing that declaring it outside the class functions would make it available to the whole class.
Suggestions? Advice? Thanks for any help
It's complaining because you need to define a variable as global to use it inside a function you haven't passed it into or attach it to the object with self.varname. Moreover, you're creating the event and then cancelling it right away before build has been called.
You should have a button that has a method on_release that starts a schedule_interval functional call with Clock. This button should become disabled after being pressed. Your second button will then unschedule using cancel.
Here's a basic working example:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock
class MyLayout(BoxLayout):
pass
class StartButton(Button):
def on_release(self):
self.event_handle = Clock.schedule_interval(self.clocks_are_fun,0.5)
self.disabled = True
def clocks_are_fun(self,dt):
self.parent.parent.ids.mylabel.text = 'Frames: ' + str(Clock.frames)
def closing_time(self):
self.event_handle.cancel()
class StopButton(Button):
def on_release(self):
self.parent.parent.ids.button1.closing_time()
self.parent.parent.ids.button1.disabled = False
class MyApp(App):
def build(self):
boxyFunTime = MyLayout()
return boxyFunTime
if __name__ == '__main__':
MyApp().run()
And the .kv file:
<MyLayout>:
id: mylayoutid
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
StartButton:
text: 'start'
id: button1
StopButton:
text: 'stop'
id: button2
Label:
id: mylabel
Related
I am ultimately trying to retrieve data from an API call to populate MDLabels. I am new to Kivy so i hope my question is not to simple but i have not found a working example after hours of searching.
import kivy
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivymd.uix.screen import Screen
from kivymd.uix.label import MDLabel
from kivymd.uix.boxlayout import BoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivy.lang.builder import Builder
#Global variable from a dictionary
orch_hostName = str("some text to add to a MDLabel")
class MyGui(Screen):
orch_info = ObjectProperty(None)
def on_enter(self):
orch_info1 = orch_hostName
self.ids.orch_info.text = "orch_info1"
class MainApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Gray"
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_hue = "300"
return MyGui()
if __name__ == "__main__":
MainApp().run()
##################################################
KV File
Widget:
<MyGui>
orch_info: orch_info
MDFloatLayout:
MDLabel:
id: orch_info
multiline: True
halign: 'left'
markup: True
theme_text_color: 'Custom'
text_color: (105 / 255.0, 105 / 255.0, 105 / 255.0, 1)
text: ""
font_style: 'H1'
pos_hint: {'x': .85, 'y': .47}
def __init__(self, **kwargs):
super(MyGui, self).__init__(**kwargs)
self.orch_info.text = orch_hostName
print(self.orch_info.text)
The issue is a simple one, getting Kivy to integrate the Timer1 code as a label in FloatLayout.
I have this .py file:
import kivy
kivy.require('1.10.0')
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.stacklayout import StackLayout
from kivy.clock import Clock
from kivy.properties import StringProperty, NumericProperty, ObjectProperty
from digitalclock import DigitalClock
from kivy.animation import Animation
import time
class IntroScreen(Screen):
pass
class ContScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
backbone = Builder.load_file("main.kv")
class Status(FloatLayout):
_change = StringProperty()
_tnd = ObjectProperty(None)
def update(self, *args):
self.time = time.asctime()
self._change = str(self.time)
self._tnd.text = str(self.time)
print (self._change)
class Timer1(Label):
a = NumericProperty(10) # seconds
color = 1, 1, 1, 1
font_size = 50
def start(self):
Animation.cancel_all(self) # stop any current animations
self.anim = Animation(a=0, duration=self.a)
def finish_callback(animation, incr_crude_clock):
incr_crude_clock.text = "COOL"
self.anim.bind(on_complete=finish_callback)
self.anim.start(self)
def on_a(self, instance, value):
self.text = str(round(value, 1))
class XGApp(App):
time = StringProperty()
def update(self, *args):
self.time = str(time.asctime())
def build (self):
Clock.schedule_interval(self.update, 1)
t1 = Timer1()
return backbone
xApp = XGApp()
if __name__ == "__main__":
xApp.run()
and the .kv:
<ContScreen>:
DigitalClock:
pos_hint: {'center_x': 0.1, 'center_y': 0.9}
size_hint: (0.075, 0.075)
StackLayout
orientation: "tb-rl"
spacing: 15
Button:
text: "1"
size_hint: None, .16
width: 225
on_press:
self.background_color = (1.7, 0, 1.7, 1)
t1.start()
I am trying to get the Timer1 aspect as a label in FloatLayout on the .kv, which appears as the button is triggered. At the moment, what I've been getting is the Timer1 as a full-screen label.
Please help!
Solution
Move the design view of Timer's Label from Python code into kv file.
Add constructor for class Timer and accepts arguments, root, instance, duration, bg_colour
In kv file, pass arguments root (screen 'cont'), instance of button, duration, background colour when instantiating Timer
In build method, remove t1 = Timer1()
Example
main.py
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock
from kivy.properties import StringProperty, NumericProperty, ObjectProperty
from kivy.animation import Animation
import time
class IntroScreen(Screen):
pass
class ContScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class Status(FloatLayout):
_change = StringProperty()
_tnd = ObjectProperty(None)
def update(self, *args):
self.time = time.asctime()
self._change = str(self.time)
self._tnd.text = str(self.time)
print (self._change)
class Timer(Label):
a = NumericProperty() # seconds
def __init__(self, root, instance, duration, bg_colour, **kwargs):
super(Timer, self).__init__(**kwargs)
self.obj = instance
self.a = duration
self.root = root
self.obj.disabled = True # disable widget/button
self.obj.background_color = bg_colour
self.root.add_widget(self) # add Timer/Label widget to screen, 'cont'
def animation_complete(self, animation, widget):
self.root.remove_widget(widget) # remove Timer/Label widget to screen, 'cont'
self.obj.background_color = [1, 1, 1, 1] # reset to default colour
self.obj.disabled = False # enable widget/button
def start(self):
Animation.cancel_all(self) # stop any current animations
self.anim = Animation(a=0, duration=self.a)
self.anim.bind(on_complete=self.animation_complete)
self.anim.start(self)
def on_a(self, instance, value):
self.text = str(round(value, 1))
class XGApp(App):
time = StringProperty()
def update(self, *args):
self.time = str(time.asctime())
def build (self):
Clock.schedule_interval(self.update, 1)
return Builder.load_file("main.kv")
if __name__ == "__main__":
XGApp().run()
kv file
#:import DigitalClock digitalclock
#:import Timer main.Timer
<ContScreen>:
DigitalClock:
pos_hint: {'center_x': 0.1, 'center_y': 0.9}
size_hint: (0.075, 0.075)
StackLayout
orientation: "tb-rl"
spacing: 15
Button:
text: "1"
size_hint: None, .16
width: 225
on_press:
Timer(root, self, 5, [0.17, 1.7, 0, 1]).start()
Button:
text: "2"
size_hint: None, .16
width: 225
on_press:
Timer(root, self, 10, [1.7, 0, 1.7, 1]).start()
<Timer>:
canvas.before:
Color:
rgba: 0, 0, 0.5, 1 # 50% blue
Rectangle:
size: self.size
pos: self.pos
size_hint: 0.3, .1
font_size: 50
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
Output
One way to make it work is to have the Button create the timer. Start by adding a start_timer() method to the ContScreen class:
class ContScreen(Screen):
def start_timer(self, *args):
timer = Timer1(size_hint=(0.2, 0.2))
self.add_widget(timer)
timer.start()
For this to work, make three other changes:
Change your main.kv file to make a root widget (eliminate the <> surrounding ContScreen).
Change the on_press for the button in the .kv file by replacing t1.start() with root.start_timer().
Eliminate the t1 = Timer1() statement from your build method in the XGApp class.
Another approach would be to create the Timer1 in the .kv file, and just start it running when the Button is pressed. To do this, change your .kv file to include a Timer:
ContScreen:
DigitalClock:
pos_hint: {'center_x': 0.1, 'center_y': 0.9}
size_hint: (0.075, 0.075)
StackLayout
orientation: "tb-rl"
spacing: 15
Button:
text: "1"
size_hint: None, .16
width: 225
on_press:
self.background_color = (1.7, 0, 1.7, 1)
timer.start()
Timer1:
id: timer
text: '0.0'
size_hint: (0.2, 0.2)
Move your backbone = Builder.load_file("main.kv") to after the definition of the Timer1 class. And change the ContScreen class back to:
class ContScreen(Screen):
pass
I am working on one simple Kivy GUI application. What i am trying to do is that i am want to access one object 'obj_random' of class 'CL_Random' from second screen(in which it is not created). I just don't know how to access declared in one screen to different screen.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
#from kivy.uix.boxlayout import BoxLayout
#from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class CL_FirstWindow(Screen):
def change_screen(self):
obj_random = CL_Random()
self.parent.current = 'second_window'
class CL_SecondWindow(Screen):
scond_prop = ObjectProperty(None)
def change_screens(self):
self.parent.current = 'first_window'
class ScreenManagement(ScreenManager):
pass
class CL_Random:
def __init__(self):
self.x = 5
presentation = Builder.load_file("rough2.kv")
class app(App):
def build(self):
return presentation
obj_app = app()
obj_app.run()
rough2.kv
ScreenManagement:
CL_FirstWindow:
CL_SecondWindow:
<CL_FirstWindow>:
id: first_window_id
name: 'first_window'
FloatLayout:
Button:
text: 'Button1'
size_hint: 0.3, 0.12
pos_hint: {'x':0.1,'y':0.6}
on_release: root.change_screen()
<CL_SecondWindow>:
id: second_window_id
name: 'second_window'
FloatLayout:
Button:
text: 'Button2'
size_hint: 0.3, 0.12
pos_hint: {'x':0.1,'y':0.6}
on_release: root.change_screens()
Label:
id: second_label_id
text: 'SECOND SCREEN'
pos_hint: {'x': 0.20, 'y':0.8}
size_hint: 1, 0.1
font_size: 35
halign: 'left'
valign: 'middle'
text_size: self.size
Thnks
To access a variable that is declared within a class the first thing is that this variable must be an attribute of the class so that the scope is greater, but as in your case the variable is local and it will be eliminated when it finishes executing the function.
On the other the solution is based on accessing the other Screen via the ScreenManager, and having the object access to the attribute for it we use the get_screen() method:
CL_SecondWindow --> ScreenManager --> CL_FirstWindow --> obj_random
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class CL_FirstWindow(Screen):
def change_screen(self):
self.obj_random = CL_Random()
self.manager.current = 'second_window'
class CL_SecondWindow(Screen):
scond_prop = ObjectProperty(None)
def change_screens(self):
first_screen = self.manager.get_screen('first_window')
print(first_screen.obj_random.x)
self.parent.current = 'first_window'
class ScreenManagement(ScreenManager):
pass
class CL_Random:
def __init__(self):
self.x = 5
presentation = Builder.load_file("rough2.kv")
class app(App):
def build(self):
return presentation
obj_app = app()
obj_app.run()
I am trying to make a screen view with buttons. The problem is that the amount of buttons needed each time will change, therefore I am not able to use the kv file to make theses buttons. I am having trouble adding buttons through the normal python code. Any help is appreciated.
import kivy
import webbrowser
import MSQLHandler
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.listview import ListItemButton
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition, CardTransition, SwapTransition, FadeTransition, WipeTransition, FallOutTransition, RiseInTransition, NoTransition
from kivy.lang import Builder
from kivy.uix.button import Button
class Login_Failed(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Loged_In(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Registers(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Login_Screen(Screen):
teacher_connect_image = ObjectProperty()
username_text_input = ObjectProperty()
password_text_input = ObjectProperty()
teacherid_text_input = ObjectProperty()
def LoginButton(self):
if self.teacherid_text_input.text == "":
Number = 0
else:
Number = int(self.teacherid_text_input.text)
MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number)
def changeScreen(self, next_screen):
self.manager.current = next_screen
if MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is True:
print("Returns True")
changeScreen(self, "Loged_In")
elif MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is False:
print("Returns False")
changeScreen(self, "Login_Failed")
else:
print("Null")
class ScreenManagerr(ScreenManager):
pass
class MainKivyFrameApp(App):
def build(self):
Registers().add_widget(Button(text="Helpp"))
return ScreenManagerr()
mainFrame = MainKivyFrameApp()
mainFrame.run()
If you look to where the app is being built, you will see: Registers().add_widget(Button(text="Helpp"))
This is where I have tried to add a Button to the screen of Registers. This doesn't give me any errors, but it still does not show the button.
Solution
In the kv file, add an event (on_enter or on_pre_enter) in each screen and bind it to a callback method as shown in the following snippets and example. Remember to remove the widgets that were added dynamically before leaving the current screen, by adding an event (on_leave or on_pre_leave).
Snippets
<Registers>:
on_pre_enter: self.add_buttons(n)
on_leave: self.remove_buttons()
Example
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.properties import ObjectProperty, NumericProperty
class MyScreenManager(ScreenManager):
total_button = NumericProperty(2)
class Login(Screen):
login = ObjectProperty(None)
def on_pre_enter(self):
Window.size = (400, 300)
def check_password(self, instance, password):
if password == "pwd":
instance.current = "registers"
class Registers(Screen):
container = ObjectProperty(None)
def on_pre_enter(self):
Window.size = (800, 600)
def add_buttons(self, n):
print("Registers: n={}".format(n))
for i in range(n):
self.container.add_widget(Button(text="Button #{}".format(i), id=str(i)))
def remove_buttons(self, *args):
for child in [child for child in self.container.children]:
self.container.remove_widget(child)
class Welcome(Screen):
pass
class TestApp(App):
title = "ScreenManager - Add Widgets Dynamically"
def build(self):
return MyScreenManager()
if __name__ == "__main__":
TestApp().run()
test.kv
#:kivy 1.10.0
#:import SwapTransition kivy.uix.screenmanager.SwapTransition
<MyScreenManager>:
transition: SwapTransition()
Login:
Registers:
on_pre_enter:
self.add_buttons(app.root.total_button)
on_leave:
self.remove_buttons()
Welcome:
<Login>:
id: login
name: "login"
login: login
GridLayout:
size_hint: (0.5, 0.5)
pos_hint: {"center_x": 0.5, "center_y": 0.6}
rows: 3
padding: 20
Label:
size_hint: (0.2, 0.2)
text:"Password:"
font_size: 30
halign: "center"
valign: "middle"
TextInput:
id: password
size_hint: (0.2, 0.06)
cursor_blink: True
font_size: 20
multiline: False
password: True
Button:
text: "Continue"
size_hint: (0.2, 0.08)
on_release:
root.login.check_password(root.manager, password.text)
<Registers>:
name:'registers'
container: container
BoxLayout:
orientation: 'vertical'
Button:
text: 'Return to Login'
on_press: root.manager.current = 'login'
Button:
text: 'Next Screen'
on_press: root.manager.current = 'welcome'
BoxLayout:
id: container
orientation: 'vertical'
<Welcome>:
name:'welcome'
BoxLayout:
Label:
text: 'Welcome!'
Button:
text: 'Return to Registers'
on_press:
app.root.total_button = 5
root.manager.current = 'registers'
Output
So this is the basic code of my tab item.
import kivy
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.gridlayout import GridLayout
Builder.load_string("""
<Test>:
size_hint: .8, .5
pos_hint: {'center_x': .4, 'center_y': .3}
do_default_tab: False
TabbedPanelItem:
text: 'Tab 1'
Label:
text: 'Syntax'
TabbedPanelItem:
text: 'Changeover'
TabbedPanelItem:
text: 'Map'
""")
class Test(TabbedPanel):
pass
class TabbedPanelApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TabbedPanelApp().run()
and i want to insert spinner on Tab 1, how to make it work? this is my spinner code.
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.properties import ListProperty, ObjectProperty
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
import kivy
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
class MultiSelectSpinner(Button):
dropdown = ObjectProperty(None)
values = ListProperty([])
selected_values = ListProperty([])
def __init__(self, **kwargs):
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 = '''
BoxLayout:
orientation: 'vertical'
size_hint: .7, .6
pos_hint: {'center_x': .3, 'center_y': .7}
do_default_tab: False
BoxLayout:
Label:
text: 'Food Type'
MultiSelectSpinner:
values: 'Fried Chicken', 'Burger'
<MultiSelectOption#ToggleButton>:
size_hint: 8, None
height: '40dp'
'''
runTouchApp(Builder.load_string(kv))
i need abit pointer please
i try to merge the code but not working.
glad if someone can help
i think its best if you create a custom TabbledPanelItem. and then implement that spinner in it.forgive my indentation
class Mod(TabbedPanelItem):
one = ObjectProperty(None)
def __init__(self,**kwargs):
super(Mod,self).__init__(**kwargs)
def on_touch_down(self, touch):
if self.state == 'down':
# dispatch to children, not to self
for child in self.children:
child.dispatch('on_touch_down', touch)
return
else:
super(Mod, self).on_touch_down(touch)
def on_release(self, *largs):
if self.parent:
self.parent.tabbed_panel.switch_to(self)
print(self.parent.children)
lola = MultiSelectSpinner()
lola.toggle_dropdown()
else:
# tab removed before we could switch to it. Switch back to
# previous tab
self.panel.switch_to(self.panel.current_tab)