I am having a problem when I am trying to use the if statement in python.
I cannot see if a variable is true or false because it says the variable is not defined but I defined it in a method.
I am using kivy and kivyMD as well, just in case people were wondering why some of the code was there.
from kivymd.app import MDApp
from kivymd.uix.screen import Screen
from kivymd.uix.button import MDRectangleFlatButton, MDRoundFlatButton
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
from kivymd.uix.menu import MDDropdownMenu
class DemoApp(MDApp):
def show_data(self):
inputFahrenheit = self.root.ids.fahrenheit.text
if fahrenheit1 is True:
Celsius_Half = float(inputFahrenheit) - 32
Celsius_Before_Round = Celsius_Half * 5/9
Celsius = round(Celsius_Before_Round , 1)
def convert1F(self):
fahrenheit1 = True
celsius1 = False
def convert1C(self):
fahrenheit1 = False
celsius1 = True
def convert2F(self):
fahrenheit2 = True
celsius2 = False
def convert2C(self):
fahrenheit2 = False
celsius2 = True
def on_start(self):
self.theme_cls.primary_palette = "Green"
self.theme_cls.primary_hue = "A700"
self.theme_cls.theme_style = "Light"
def build(self):
kv = Builder.load_file("test.kv")
screen = Screen()
return kv
DemoApp().run()
The if statement is the problem there is a copy of the problem:
"fahrenheit1" is not defined
In order for fahrenheit1 to be defined, you need to declare it as a class attribute.
Either define in in the class __init__ or as a static attribute at the top of the class, outside of any method) as fahrenheit1: bool = <your_defualt_value>
Because there is no defined variable called fahrenheit1.
Fix that first
Related
I have spent a fair amount of time trying to fix this,
my actual goal is to run a forloop to generate a list in kivymd and while doing so I got this error?
TypeError: __init__() takes 1 positional argument but 2 were given
this is the code that I have simplified
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.list import *
KV = '''
ScrollView:
MDList:
id: list
'''
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
ib = IconLeftWidget(icon='github')
ibn = OneLineAvatarIconListItem(
IconLeftWidget(icon='github')
)
self.root.ids.list.add_widget(ib)
MainApp().run()
need a generate a list via a forloop and use the icon as a button
OneLineAvatarIconListItem( IconLeftWidget(icon='github') )# error line
I know that the problem is that you can only pass one argument for the function but there got a be a way right!
please help T-T
I don't know if it can be done in one line but this works for me
#ibn = OneLineAvatarIconListItem(text='Hello')
ibn = OneLineAvatarIconListItem()
ibn.add_widget(IconLeftWidget(icon='plus'))
ibn.add_widget(IconRightWidget(icon='minus'))
self.root.ids.list.add_widget(ibn)
You could create own widget to make it simpler
class MyItem(OneLineAvatarIconListItem):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add_widget(IconLeftWidget(icon='plus'))
self.add_widget(IconRightWidget(icon='minus'))
# ... code ...
#my_item = MyItem(text='World')
my_item = MyItem()
self.root.ids.list.add_widget(my_item)
Minimal working code
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.list import *
KV = '''
ScrollView:
MDList:
id: list
'''
class MyItem(OneLineAvatarIconListItem):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add_widget(IconLeftWidget(icon='plus'))
self.add_widget(IconRightWidget(icon='minus'))
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
ib = IconLeftWidget(icon='github')
self.root.ids.list.add_widget(ib)
ibn = OneLineAvatarIconListItem(text="Hello", bg_color="lime")
ibn.add_widget(IconLeftWidget(icon='plus'))
ibn.add_widget(IconRightWidget(icon='minus'))
self.root.ids.list.add_widget(ibn)
my_item = MyItem(text="World", bg_color="red")
self.root.ids.list.add_widget(my_item)
MainApp().run()
How can I create MDNavigationRail without KV language? I tried this code but I get a lot of errors.
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail()
navigationrail.add_widget(MDNavigationRailItem(icon="access-point"))
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()
You have to pass your object navigationrail as an argument of MDNavigationRailItem.
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.toolbar import MDToolbar
from kivy.utils import get_color_from_hex
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail(
md_bg_color = get_color_from_hex("#344954"),
# color_normal = get_color_from_hex("#718089"), #crash the app when clicking on an item, don't understand why...
color_active = get_color_from_hex("#f3ab44"),
visible = "Persistent")
for i in range(3):
item = MDNavigationRailItem(navigation_rail = navigationrail, text="item%d" %(i+1))
navigationrail.add_widget(item)
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()
I have created a custom Label that removes itself when clicked on, used the parent.remove_widget(child_instance) method with mitigate success : the widget graphically disappear, but when my mouse hover over its position, its on_enter and on_leave hovering events do still fires...
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.relativelayout import RelativeLayout
from kivy.lang.builder import Builder
from kivy.core.window import Window
Builder.load_string("""
<DrawingSpace>:
size_hint : None,None
size : 1000,700
Tag:
id : tag_test
pos : 100, 50
size_hint : None,None
size : self.texture_size
tag : "test text"
""")
class Tag(Label):
tag = kivy.properties.StringProperty("")
markup = kivy.properties.BooleanProperty(True)
hovered = kivy.properties.BooleanProperty(False)
def __init__(s,*args,**kargs):
s.register_event_type("on_enter")
s.register_event_type("on_leave")
Window.bind(mouse_pos=s.on_mouse_pos)
Label.__init__(s,*args,**kargs)
s._regular_text = "[color=ffffff]{}[/color]"
s._hovered_text = "[color=ff0000][s][b]{}[/b][/s][/color]"
def on_mouse_pos(s,*args):
pos = args[1]
inside = s.collide_point(*s.to_widget(*pos))
if s.hovered == inside:
return
s.hovered = inside
if inside :
s.dispatch("on_enter")
else :
s.dispatch("on_leave")
def on_touch_down(s,touch):
if s.collide_point(*touch.pos):
s.parent.remove_widget(s)
del s
return False
def on_tag(s,instance,text):
s.text = s._regular_text.format(s.tag)
def on_enter(s):
print ("on_enter:: text :",s.text)
s.text = s._hovered_text.format(s.tag)
pass
def on_leave(s):
print ("on_leave:: text :",s.text)
s.text = s._regular_text.format(s.tag)
pass
class DrawingSpace(RelativeLayout):
pass
class Main(App):
def build(s):
return DrawingSpace()
Window.fullscreen = False
Main().run()
how would you proceed to actually not only remove graphically the widget instance, but completely remove it so that its event do not get computed anymore ?
Not sure if this truly removes the widget, but if you add a call to funbind:
def on_touch_down(s,touch):
if s.collide_point(*touch.pos):
Window.funbind('mouse_pos', s.on_mouse_pos)
s.parent.remove_widget(s)
del s
return False
then the on_enter and on_leave events will stop.
I have some trouble to transfert a list of element, that i get from a file (in the first screen), to the second and third screen.
I have 3 Screen managed by ScreenManager, every screen is in a different file.py and have a file.kv.
This is what my ScreenManager looks like (filename : login.py):
from interface1 import Interface1App
from interface2 import Interface2App
class LoginApp(App):
def build(self):
manager = ScreenManager()
#add view login
manager.add_widget(Login(name='login'))
# add view 'interface1'
app = Interface1App()
app.load_kv()
interfacen1 = app.build()
manager.add_widget(interfacen1)
# add view 'interface2'
app2 = Interface2App()
app2.load_kv()
interfacen2 = app2.build()
manager.add_widget(interfacen2)
# add view 'interface3'
app3 = Interface3App()
app3.load_kv()
interfacen3 = app3.build()
manager.add_widget(interfacen3)
manager.transition = SlideTransition(direction="left")
return manager
In the screen manager login i import all the screens (ex: from interface1 import Interface1App)
In the second file, i put in self.list some data, and use it for that interface (filename : interface1.py):
from interface2 import Interface2App
class AllImage(Screen):
CONTAINER_PNG = os.path.join(AllImage_ROOT, 'images')
IMAGES_NAMES = [c[:-4] for c in os.listdir(CONTAINER_PNG)]
def __init__(self, **kwargs):
Screen.__init__(self, **kwargs)
for im in IMAGES_NAMES:
if IMAGES_NAMES != None :
toggleimage = ToggleWithImage(src=im+'.png')
toggleimage.bind(on_press= lambda a, im=im:self.onpress_addpage(self.listim, im))
self.layout.add_widget(toggleimage)
def change_screen(self, x, list):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'interface2'
self.manager.get_screen('interface2')
self.manager.list1 = [1,2,3]
def backtologin(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'login'
self.manager.get_screen('login')
class Interface1App(App):
'''The kivy App that runs the main root. All we do is build a AllImage
widget into the root.'''
def build(self):
screen = AllImage()
screen.name = 'interface1'
return screen
After that i want to use again the data collected in the 2nd interface (self.list) and use it in the 3rd Interface (filename: interace2.py):
from interface1 import AllImage #this isn't working
class Combinaison(Screen):
screen = ObjectProperty(None)
def __init__(self, **kwargs):
# self._previously_parsed_text = ''
super(Combinaison, self).__init__(**kwargs)
# self.list = list(self.manager.get_screen('interface1').list)
print(self.manager.list1) # The problem is here <===========
def backtointerface1(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'interface1'
self.manager.get_screen('interface1')
class Interface2App(App):
'''The kivy App that runs the main root. All we do is build a Combinaison
widget into the root.'''
def build(self):
screen = Combinaison()
screen.name = 'interface2'
return screen
With this code i have this error : print(self.manager.list1)
AttributeError: 'NoneType' object has no attribute 'list1'
I think i didn't understand how i should use the self.manager.list1=[1, 2, 3]
I hope that i was clear, sorry for the long post.
Thank you for your time :)
You can use Screen.manager.get_screen(name).list = list(self.list)
A complete example:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
class Screen1(Screen):
list = [1,2,3]
def __init__(self,**kwargs):
super(Screen1,self).__init__(**kwargs)
self.switch_button = Button(text="goto 2")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.list = [4,5,6]
self.manager.get_screen("screen2").list = list(self.list)
self.manager.current = "screen2"
class Screen2(Screen):
def __init__(self,**kwargs):
super(Screen2,self).__init__(**kwargs)
self.switch_button = Button(text="goto 1")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.manager.current = "screen1"
def on_enter(self):
print self.list
class MainApp(App):
def build(self):
sc1 = Screen1(name="screen1")
sc2 = Screen2(name="screen2")
self.sm = ScreenManager()
self.sm.add_widget(sc1)
self.sm.add_widget(sc2)
return self.sm
MainApp().run()
You can also use the ScreenManager to store the list or lists.
self.manager.list1 = [1,2,3] # dont call this in __init__
self.manager.list2 = [4,5,6] # call it in on_enter instead
Those lists will be available from all screens after they are added to the manager. The on_enter method on the screen would be suitable for your example.
I know this might be a very basic question, but after spending hours wrapping my head around it I still can't figure it out.
I basically just want to bind the text of a label to a variable in the python code. lets call it value. however it should get updated everytime I run a loop Clock.schedule_interval(RootWidget.update, 1.0/1.0)
here is the python, simplified so its basically just the time, which is also printed just to see if it is actually working.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.clock import Clock
from kivy.core.window import Window
import time
class RootWidget(FloatLayout):
def update(self, *args):
value = time.time()
print value
self.ids.value_label.text = str(value)
class MainApp(App):
def build(self):
Window.size = (800, 480)
r = RootWidget()
Clock.schedule_interval(r.update, 1)
print 'build running'
return r
def on_pause(self):
return True
if __name__ == '__main__':
MainApp().run()
the kv file looks as such:
<RootWidget>:
Label:
id: value_label
text:
y: 20.0
x: 0.0
width: 100.0
italic: False
height: 50.0
Clock.schedule_interval(RootWidget.update, 1.0/1.0)
You need to schedule the update method of an instance, not the class itself.
For instance:
r = RootWidget()
Clock.schedule_interval(r.update, 1)
return r
The clock will pass some arguments by default, so you should also declare the update method to accept these. If you don't want to use them then you can just do:
def update(self, *args):
...