0

我刚开始学习 Kivy,所以我仍然熟悉它的功能。我正在尝试将图像作为我的应用程序主页的背景。这就是我所做的:

class Prin(BoxLayout):
    def __init__(self,**kwargs):
        super(Prin,self).__init__(**kwargs)
        layout = BoxLayout(orientation='vertical')
        with self.canvas:
            self.rect = Rectangle(source='test.png', pos=layout.center, size=(self.width, self.height))
        self.text = Label(text='Press start')
        fb = Button(text='Start!', size_hint =(0.5, 0.1), pos_hint ={'center_x':.5, 'y':.5}, padding=(10, 0), on_press=self.start)

        layout.add_widget(self.text)
        layout.add_widget(fb)
        self.add_widget(layout)
        
    def start(self,event):
        self.text.text = self.text.text+ "\nNew line"


class MainApp(App):
    def build(self):
            return Prin()
    

if __name__ == "__main__":
    app = MainApp()
    app.run()

所需的行为是覆盖整个屏幕的图像,这就是我放的原因pos=self.center, size=(self.width, self.height)

这是输出:

电流输出

所以我有两个问题:

1/ 为什么图像出现在左下角?实际上有什么小部件?我应该只有一个带有 2 个垂直方向小部件的 BoxLayout。我不明白那里有什么。

2/ 为什么要输入 size 和 pos 以获得所需的输出?

4

2 回答 2

1

我建议将所有图形元素放在一个.kv文件中,这样可以减少导入次数并且看起来更好。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

KV = ("""
<Prin>
    BoxLayout:
        orientation: 'vertical'
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'test.png'
                
        Label:
            id: label
            text: 'TEXT'
                
        Button:
            text: 'Start!'
            size_hint: None, None
            size_hint: 0.5, 0.1
            pos_hint: {'center_x': .5, 'center_y': .5}
            padding: 10, 0
            on_press: root.start()
            
""")


class Prin(BoxLayout):
    Builder.load_string(KV)

    def __init__(self, **kwargs):
        super(Prin, self).__init__(**kwargs)

    def start(self):
        self.ids.label.text += "\nNew line"


class MainApp(App):
    def build(self):
        return Prin()


if __name__ == "__main__":
    app = MainApp()
    app.run()

如果您仍然想不在kv文件中执行此操作,那么问题出在 中self.size,默认情况下,此值是[100, 100],只有在调用该类并将其添加到主窗口后它才会更改。

from kivy.core.window import Window

class Prin(BoxLayout):
    def __init__(self, **kwargs):
        super(Prin, self).__init__(**kwargs)

        with self.canvas.before:
            Rectangle(source='test.png', pos=self.pos, size=Window.size)

        print(self.size) # [100, 100]


...

class MainApp(App):
    def build(self):
        self.screen = Prin()
        return self.screen

    def on_start(self):
        print(self.screen.size)  # [800, 600]

当你提出问题时不要忘记导入,代码应该在没有任何操作的情况下运行

于 2021-04-08T16:05:21.163 回答
0

针对您的问题:

  1. 该图像出现在该位置,因为pos=layout.center它不是有效位置,因此将其设置为默认值([100, 100]我相信)。要解决此问题,请更改pos=layout.centerpos=layout.pos

  2. 您的尺寸也是默认值!这有点技术性,但是当您初始化您的Prin类时,您将 . 的大小指定RectangleBoxLayout. 但是,由于它还没有被初始化,所以 BoxLayout 还没有大小!同样,Kivy 通过给它一个默认大小来处理这个问题。

为什么我的按钮和标签正确?

Kivy 自动将 BoxLayout 的子项绑定到 BoxLayout 的大小和位置。此绑定可确保当 BoxLayout 的位置和大小发生变化时,其中的小部件也会发生变化(https://kivy.org/doc/stable/api-kivy.event.html)。

为什么 Kivy 不绑定矩形?

这与canvas. 画布是小部件共享的绘图指令,而不是任何单个小部件的属性。因此,您将以编程方式将矩形绑定到 BoxLayout。( https://kivy.org/doc/stable/api-kivy.graphics.instructions.html )

我如何实现您所说的这种绑定?

两种方式。首先(首选),您可以使用 KV 语言定义小部件,因为这将自动处理您希望的任何绑定。其次,您可以创建一个“on_size”回调。就像是:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.graphics import Rectangle


class Prin(BoxLayout):

    def __init__(self, **kwargs):
        super(Prin, self).__init__(**kwargs)
        layout = BoxLayout(orientation='vertical')
        with self.canvas:
            self.rect = Rectangle(source='test.png', pos=layout.pos, size=self.size)
        self.text = Label(text='Press start')
        fb = Button(text='Start!', size_hint=(0.5, 0.1), pos_hint={'center_x': .5, 'y': .5}, padding=(10, 0),
                    on_press=self.start)

        layout.add_widget(self.text)
        layout.add_widget(fb)
        self.add_widget(layout)

    def start(self, *_):
        self.text.text = self.text.text + "\nNew line"

    def resize(self, *_):
        widgets = self.children[:]
        self.canvas.clear()
        self.clear_widgets()
        with self.canvas:
            self.rect = Rectangle(source='test.png', pos=self.pos, size=self.size)
        for widget in widgets:
            self.add_widget(widget)

    on_size = resize


class TestApp(App):
    def build(self):
        return Prin()


if __name__ == "__main__":
    app = TestApp()
    app.run()

我只是想添加一个大 PS虽然上面的代码解决了你的问题,但它可能是以可以想象的效率最低的方式来解决的。在 kv 文件中定义小部件要好得多。

于 2021-04-08T16:20:08.393 回答