【问题标题】:Kivy: How to make label size and size of a canvas equal?Kivy:如何使标签大小和画布大小相等?
【发布时间】:2020-04-10 19:05:05
【问题描述】:

我使用 Gridlayout 制作了一个方形的标签网格。现在我想为标签添加背景颜色(每个标签都有不同的矩形)。我尝试通过以下代码做到这一点。

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle, Color
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label


class MyGrid(FloatLayout):
    def __init__(self,**kwargs):
        super(MyGrid,self).__init__(**kwargs)
        self.grid=GridLayout()
        self.grid_size=4
        self.grid.cols=self.grid_size
        for k in range(self.grid_size):
            for i in range(self.grid_size):
                with self.grid.canvas:
                    Rectangle(size=(100,100),pos=(k*160+100,i*160+100),source="52852.JPG")
        for h in range(self.grid_size):
            for j in range(self.grid_size):
                self.grid.add_widget(Label(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100)))
        self.add_widget(self.grid)

class GameApp(App):
    def build(self):
        return MyGrid()

if __name__ == '__main__':
    GameApp().run()

在此代码中,如果我没有指定“self.grid.cols”,它会在 python 控制台中生成警告,并且当窗口切换到全屏模式时,画布中的矩形会保留原始大小和位置,但标签不要。我想在画布矩形前面获取标签,它们还应该保留指定的屏幕大小。此外,如果我将“self.grid.size”更改为任何其他数字,它也应该制作该长度的标签网格和相应数量的画布。我也为此尝试了浮动布局,但没有帮助。无论窗口大小如何,画布矩形和标签都应该适合窗口。如果我能用python文件(而不是.kv文件)来解决上述问题,那就更好了。如果您知道此问题的任何其他解决方案或任何其他小部件,请告诉我。就像按钮小部件一样,我们可以指定背景颜色和文本,您也可以添加任何可以完成上述任务的小部件。您应该将矩形画布中的“源”替换为任何已知的图像文件。我希望你明白。如果您不这样做,请告诉我。 :)

【问题讨论】:

  • Labels 正在改变大小,因为所有Widgets 的默认值都是填充其父级(包括GridLayoutFloatLayoutLabel)。 Rectangles 没有这种行为,并保持您分配给它们的位置和大小。因此,您可以将Widgets 设置为不更改位置和大小,或者您可以让RectangleWidgets 一样调整它们的大小。您喜欢哪种方式?

标签: python python-3.x canvas kivy kivy-language


【解决方案1】:

Widgets 设置为不更改sizepos 是最简单的解决方案。基本上只用size_hint=(None, None),不要用GridLayout

from kivy.app import App
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label


class MyGrid(FloatLayout):
    def __init__(self,**kwargs):
        super(MyGrid,self).__init__(**kwargs)
        self.grid_size=4
        for k in range(self.grid_size):
            for i in range(self.grid_size):
                with self.canvas:
                    Rectangle(size=(100,100),pos=(k*160+100,i*160+100),source="52852.JPG")
        for h in range(self.grid_size):
            for j in range(self.grid_size):
                self.add_widget(Label(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100), size_hint=(None, None)))

class GameApp(App):
    def build(self):
        return MyGrid()

if __name__ == '__main__':
    GameApp().run()

要使RectanglesLabels 更改possize 有点复杂。在下面您的代码的修改版本中,我保留LabelsRectanglesbind 的列表,adjust_common_size() 方法在sizeMyGrid 更改时运行。然后该方法调整LabelsRectanglessizepos 以匹配:

from kivy.app import App
from kivy.properties import ListProperty
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label


class MyGrid(FloatLayout):
    common_size = ListProperty((100, 100))
    def __init__(self,**kwargs):
        super(MyGrid,self).__init__(**kwargs)
        self.grid_size=4
        self.rects = []
        self.labels = []
        for k in range(self.grid_size):
            one_row = []
            self.rects.append(one_row)
            for i in range(self.grid_size):
                with self.canvas:
                    one_row.append(Rectangle(size=self.common_size,pos=(k*160+100,i*160+100),source="52852.JPG"))
        for h in range(self.grid_size):
            one_row = []
            self.labels.append(one_row)
            for j in range(self.grid_size):
                label = Label(text="labwl"+str(h)+str(j),size=self.common_size,pos=(h*160+100,j*160+100), size_hint=(None, None))
                one_row.append(label)
                self.add_widget(label)

        self.bind(size=self.adjust_common_size)

    def adjust_common_size(self, instance, new_size):
        self.common_size = (new_size[0] * 0.9 / self.grid_size, new_size[1] * 0.9 / self.grid_size)
        for k in range(self.grid_size):
            for i in range(self.grid_size):
                adjusted_pos = (k * new_size[0] / self.grid_size, i * new_size[1] / self.grid_size)
                rect = self.rects[k][i]
                label = self.labels[k][i]
                label.size = self.common_size
                label.pos = adjusted_pos
                rect.size = self.common_size
                rect.pos = adjusted_pos

class GameApp(App):
    def build(self):
        return MyGrid()

if __name__ == '__main__':
    GameApp().run()

没有必要为common_size 使用ListProperty,但如果您决定使用kv 会很方便。

这是一个有趣的问题。这是使RectangleLabel 匹配的更好方法。下面的代码使用了GridLayout,但定义了MyLabel以包含它自己的Rectangle,并保持它的Rectanglepossize中匹配:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label

class MyLabel(Label):
    def __init__(self, **kwargs):
        super(MyLabel, self).__init__(**kwargs)
        with self.canvas.before:
            self.rect = Rectangle(size=self.size,pos=self.pos,source="52852.JPG")
        self.bind(size=self.adjust_size)
        self.bind(pos=self.adjust_pos)

    def adjust_pos(self, instance, new_pos):
        self.rect.pos = new_pos

    def adjust_size(self, instance, new_size):
        self.rect.size = new_size


class MyGrid(FloatLayout):
    def __init__(self,**kwargs):
        super(MyGrid,self).__init__(**kwargs)
        self.grid=GridLayout()
        self.grid_size=4
        self.grid.cols=self.grid_size
        for h in range(self.grid_size):
            for j in range(self.grid_size):
                self.grid.add_widget(MyLabel(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100)))
        self.add_widget(self.grid)

class GameApp(App):
    def build(self):
        return MyGrid()

if __name__ == '__main__':
    GameApp().run()

使用这种方法,您根本不必在MyGrid 中创建Rectangles,因为每个Label 都会创建自己的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 2017-01-24
    • 2016-07-01
    • 2019-07-22
    • 1970-01-01
    相关资源
    最近更新 更多