繁体   English   中英

在 Kivy 中显示背景图像

[英]Displaying a background image in Kivy

我刚开始学习 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)

这是 output:

电流输出

所以我有两个问题:

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

2/ 为什么要输入尺寸和位置以获得所需的 output?

我建议将所有图形元素放在一个.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] ,只有在调用 class 并将其添加到主 window 后才会更改。

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]

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

针对您的问题:

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

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

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

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

为什么 Kivy 不绑定矩形?

这与canvas 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 文件中定义小部件要好得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM