I'm posting this because I want to add a canvas behind, inside, on top, I don't know, I want a background for the labels, and I have found out that I need a canvas to do that, but I don't know how to do it. I have been able to add a canvas as a background for a label, but since my app needs to be refreshed and resized I bump into problems that I am not able to fix.
I want to make the canvas so that it has the same size as the labels beside eachother, and I want to be able to remove it like when I remove the labels inside "theLayout".
I believe the problem is in the method "refresh" inside the class "HovedVindu".
If it is possible to not change the whole code and fix it so that a beginner like me is able to understand and modify it, I would appreciate it very much, if it is not possible I will still appreciate any help :)
I used paint 3D to visualize what I want to achieve:
main.py:
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
import kivy.uix.boxlayout
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Color, Rectangle, Canvas
Builder.load_file("struktur.kv")
sm = ScreenManager()
produkter = [["Melk", "04.06.2022"], ["Ost", "28.07.2022"], ["Tomat", "27.05.2022"], ["Banan", "02.06.2022"]]
class produktManager(object):
def lagreProdukt(self, navn, dato):
self.navn = navn
self.dato = dato
nyProdukt = [self.navn.text, self.dato.text]
if nyProdukt != ["", ""]:
produkter.insert(0, nyProdukt)
class HovedVindu(Screen):
def nyttProdukt(self):
show_popup()
def Refresh(self):
theLayout = self.ids.theLayout
for i in range(10):
for v in theLayout.children:
theLayout.remove_widget(v)
for i in produkter:
newLabel_navn = theLayout.add_widget(Label(text = i[0]))
newLabel_dato = theLayout.add_widget(Label(text = i[1]))
#with theLayout.canvas:
#(Color(0, 1, 1, .1))
#(Rectangle(size = (self.size), pos_hint = (self.pos)))
class P(FloatLayout):
def leggTilNyttProdukt(self, Navn, Dato):
produktManager().lagreProdukt(Navn, Dato)
Navn.text = ""
Dato.text = ""
class MainApp(App):
def build(self):
sm.add_widget(HovedVindu(name="hoved"))
return sm
def show_popup():
show = P()
popupWindow = Popup(title="Legg til ett nytt produkt", content=show, size_hint=(None,None),size=(400,400), title_align="center")
popupWindow.open()
if __name__ == "__main__":
MainApp().run()
struktur.kv:
#:kivy 2.1.0
#:import RiseInTransition kivy.uix.screenmanager.RiseInTransition
<HovedVindu>:
FloatLayout:
size_hint: 1, .1
pos_hint: {"x": 0, "top": 1}
canvas.before:
Color:
rgba: 1, 1, 1, .8
Rectangle:
pos: self.pos
size: self.size
Button:
text: "+"
size_hint: .15, .8
pos_hint: {"x": .8, "top": .9}
on_release: root.nyttProdukt()
Button:
text: "Refresh"
size_hint: .2, .8
pos_hint: {"x": .2, "top": .9}
on_release:
root.Refresh()
FloatLayout:
size_hint: 1, .9
canvas.before:
Color:
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
GridLayout:
id: theLayout
cols: 2
rows: 10
Label:
text: "NAVN"
canvas.before:
Color:
rgba: 1, 0, 0, .2
Rectangle:
pos: self.pos
size: self.size
Label:
text: "DATO"
canvas.before:
Color:
rgba: 1, 0, 0, .2
Rectangle:
pos: self.pos
size: self.size
<P>:
TextInput:
id: navn
hint_text: "Navnet på produktet"
size_hint: .6, .15
pos_hint: {"x": .2, "top": .9}
TextInput:
id: dato
hint_text: "Siste forbruksdag"
size_hint: .6, .15
pos_hint: {"x": .2, "top": .7}
Button:
text: "Legg til produkt"
size_hint: 0.8, 0.2
pos_hint: {"x":0.1, "y":0.1}
on_release: root.leggTilNyttProdukt(navn, dato)
In order to have a label with some background color and use it dynamically you can create a dynamic class inherited from Label
. You can also create any desired prop. for advanced usage.
First define a class in .py
inherited from Label
,
class CustomLabel(Label):
background_color = ListProperty([1, 1, 1, 1])
Now design it using kvlang
,
<CustomLabel>:
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
Now your label is ready to use.
def Refresh(self):
...
for n, i in enumerate(produkter, start = 1):
newLabel_navn = theLayout.add_widget(CustomLabel(text = i[0], background_color = [1, 1/n, 1, 0.5]))
newLabel_dato = theLayout.add_widget(CustomLabel(text = i[1], background_color = [1/n, 1, 1, 0.8]))
...