向标签添加 canvas 的正确方法

Proper way of adding a canvas to a label

我发布这个是因为我想在后面、里面、上面添加一个 canvas,我不知道,我想要标签的背景,我发现我需要a canvas 来做到这一点,但我不知道该怎么做。我已经能够添加 canvas 作为标签的背景,但由于我的应用程序需要刷新和调整大小,我遇到了无法修复的问题。

我想让 canvas 与彼此旁边的标签大小相同,并且我希望能够像删除“theLayout”中的标签一样删除它。

我认为问题出在 class“HovedVindu”中的“刷新”方法。

如果可以不更改整个代码并修复它以便像我这样的初学者能够理解和修改它,我将非常感激,如果不可能我仍然会感谢任何帮助:)

我使用 paint 3D 来可视化我想要实现的目标:

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)

为了拥有带有背景颜色的标签并动态使用它,您可以创建一个继承自 Label 的动态 class。您还可以创建任何所需的道具。用于高级用法。

先定义一个class in .py继承自Label,

class CustomLabel(Label):
    background_color = ListProperty([1, 1, 1, 1])

现在使用kvlang

设计它
<CustomLabel>:
    canvas.before:
        Color: 
            rgba: self.background_color
        Rectangle:
            pos: self.pos
            size: self.size

现在您的标签可以使用了。

    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]))
        ...