【问题标题】:Displaying a background image in Kivy在 Kivy 中显示背景图像
【发布时间】:2021-04-08 13:59:34
【问题描述】:

我刚开始学习 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 以获得所需的输出?

【问题讨论】:

    标签: python python-3.x canvas kivy


    【解决方案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]
    

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

    【讨论】:

      【解决方案2】:

      回答您的问题:

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

      2. 您的尺寸也是默认值!这有点技术性,但是当您初始化Prin 类时,您将Rectangle 的大小指定为BoxLayout 的当前大小。但是,由于它还没有被初始化,所以 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()
      

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

      【讨论】:

        猜你喜欢
        • 2013-04-30
        • 1970-01-01
        • 2020-02-05
        • 2010-09-27
        • 2016-02-12
        • 2019-02-11
        • 2019-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多