在Kivy中制作一个可调整大小的边界RelativeLayout

时间:2017-11-24 16:03:08

标签: python python-3.x kivy

我似乎在试图想出一种可调整大小的布局方面遇到了一些麻烦。至少这就是我所说的。

我正在开发一个更大的游戏项目,我需要为游戏创建一个“对话框”。我需要在文件dialogue中调用此类并按如下方式创建它:

dialogue_window = Dialogue(pos=(x, y), size=(x, y))

现在我还有一些名为x_bordery_border的图像文件,我想要拉伸以适应y和x尺寸。这是我到目前为止所提出的:

from kivy.uix.image import Image
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout


from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.button import Button


class Main(RelativeLayout):

    def __init__(self, size, pos):
        super().__init__()
        self.y_border = './assets/y_border.png'
        self.x_border = './assets/x_border.png'
        self.dialogue_left_border = None
        self.dialogue_right_border = None
        self.dialogue_top_border = None
        self.dialogue_background = None
        self.dialogue_bottom_border = None
        self.size = size
        self.pos = pos

        self.make_dialogue()

    def make_dialogue(self):
        self.dialogue_frame = RelativeLayout(pos=self.pos, size=self.size)

        self.dialogue_background = Image(source="./assets/dialogue_background.png",
                                         size=self.size,
                                         pos=self.pos)

        self.dialogue_left_border = Image(source=self.y_border,
                                          size=(self.size.x, 16))

        self.dialogue_right_border = Image(source=self.y_border,
                                           size=(16, self.size.y))

        self.dialogue_top_border = Image(source=self.x_border,
                                         size=(self.size.x, 16))

        self.dialogue_bottom_border = Image(source=self.x_border,
                                         size=(self.size.x, 16))

        self.dialogue_frame.add_widget(self.dialogue_background)
        self.dialogue_frame.add_widget(self.dialogue_left_border)
        self.dialogue_frame.add_widget(self.dialogue_right_border)
        self.dialogue_frame.add_widget(self.dialogue_top_border)
        self.dialogue_frame.add_widget(self.dialogue_bottom_border)


class MainApp(App):

    def build(self):
        self.title = "Dialogue"
        return Main((300, 500), (500, 500))


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

但由于某种原因,我收到了这个错误:

 Traceback (most recent call last):
   File "/Users/masterprogrammer/PycharmProjects/marssim/MarsSim/mars_dialogue.py", line 65, in <module>
     MainApp().run()
   File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/app.py", line 802, in run
     root = self.build()
   File "/Users/masterprogrammer/PycharmProjects/marssim/MarsSim/mars_dialogue.py", line 61, in build
     return Main((300, 500), (500, 500))
   File "/Users/masterprogrammer/PycharmProjects/marssim/MarsSim/mars_dialogue.py", line 29, in __init__
     self.make_dialogue()
   File "/Users/masterprogrammer/PycharmProjects/marssim/MarsSim/mars_dialogue.py", line 39, in make_dialogue
     size=(self.size.x, 16))
 AttributeError: 'ObservableReferenceList' object has no attribute 'x'
Exception ignored in: functools.partial(<function _widget_destructor at 0x10061fbf8>, 8)
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/uix/widget.py", line 265, in _widget_destructor
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/lang/builder.py", line 742, in unbind_widget
  File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'weakref' object has no attribute 'cline_in_traceback'
Exception ignored in: functools.partial(<function _widget_destructor at 0x10061fbf8>, 22)
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/uix/widget.py", line 265, in _widget_destructor
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/lang/builder.py", line 742, in unbind_widget
  File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'weakref' object has no attribute 'cline_in_traceback'
Exception ignored in: functools.partial(<function _widget_destructor at 0x10061fbf8>, 15)
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/uix/widget.py", line 265, in _widget_destructor
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/kivy/lang/builder.py", line 742, in unbind_widget
  File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'weakref' object has no attribute 'cline_in_traceback'

我认为是因为61 return Main((300, 500), (500, 500)),但我不知道有什么方法可以解决这个问题。我做了一些搜索,但找不到任何可以帮助我的东西。

我还想到了我需要的整体目标,使border的stretch属性成为真正的,因为它能够伸展。我还没有放置这些小部件,因为错误不让我看到我想要的确切位置

2 个答案:

答案 0 :(得分:0)

请使用make_dialogue方法分别替换所有self.size.xself.size.y self.size[0]self.size[1]我不知道这是否能解决您的问题但它会解决回溯错误

更新:不是使用None初始化您的图片,而是使用ObjectProperty(None)导入ObjetProperty from kivy.properties import ObjectProperty更新所有图片

答案 1 :(得分:0)

黑色窗口

黑色窗口是由于pos =(500,500)和size =(300,500)。窗口的大小是(800,600),即宽度= 800,高度= 600。我为了说明做了以下更改并使用了其他图像。有关详细信息,请参阅示例和输出。

构建方法

替换:

return Main(size=(300, 500), pos=(500, 500))

使用:

return Main(size=(300, 500), pos=(0, 0))

make_dialogue方法

将以下内容添加为最后一行:

self.add_widget(self.dialogue_frame)

错误 - 修复

解决方案是更换以下内容,如下所示。

__ init__ method

替换:

def __init__(self, size, pos):
    super().__init__()

使用:

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

参数pos&amp;大小

替换:

self.size = size
self.pos = pos

使用:

self.size = kwargs.get('size')
self.pos = kwargs.get('pos')
self.size.x = self.size[0]
self.size.y = self.size[1]
self.pos.x = self.pos[0]
self.pos.y = self.pos[1]

构建方法

替换:

return Main((300, 500), (500, 500))

使用:

return Main(size=(300, 500), pos=(500, 500))

实施例

main.py

from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button


class Main(RelativeLayout):

    def __init__(self, **kwargs):
        super(Main, self).__init__(**kwargs)
        self.y_border = './assets/y_border.png'
        self.x_border = './assets/x_border.png'
        self.dialogue_left_border = None
        self.dialogue_right_border = None
        self.dialogue_top_border = None
        self.dialogue_background = None
        self.dialogue_bottom_border = None
        self.size = kwargs.get('size')
        self.pos = kwargs.get('pos')
        self.size.x = self.size[0]
        self.size.y = self.size[1]
        self.pos.x = self.pos[0]
        self.pos.y = self.pos[1]

        self.make_dialogue()

    def make_dialogue(self):
        self.dialogue_frame = RelativeLayout(pos=self.pos, size=self.size)

        self.dialogue_background = Image(source="./assets/dialogue_background.png",
                                         size=self.size,
                                         pos=self.pos)

        self.dialogue_left_border = Image(source=self.y_border,
                                          size=(self.size.x, 16))

        self.dialogue_right_border = Image(source=self.y_border,
                                           size=(16, self.size.y))

        self.dialogue_top_border = Image(source=self.x_border,
                                         size=(self.size.x, 16))

        self.dialogue_bottom_border = Image(source=self.x_border,
                                         size=(self.size.x, 16))

        self.dialogue_frame.add_widget(self.dialogue_background)
        self.dialogue_frame.add_widget(self.dialogue_left_border)
        self.dialogue_frame.add_widget(self.dialogue_right_border)
        self.dialogue_frame.add_widget(self.dialogue_top_border)
        self.dialogue_frame.add_widget(self.dialogue_bottom_border)
        self.add_widget(self.dialogue_frame)


class MainApp(App):

    def build(self):
        self.title = "Dialogue"
        return Main(size=(300, 500), pos=(0, 0))


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

输出

Figure 1 - Dialogue