我无法让我的kivy小部件从某个位置开始移动

时间:2018-08-24 18:17:36

标签: python kivy

我是kivy的新手,无法让此小部件在开始移动之前从某个位置开始。在我的kv文件中,我的窗口小部件位置设置为self.pos,在我的fall函数中,我使用self.pos更改窗口小部件的位置并使它下降。唯一的问题是我无法为小部件添加原点位置。这是我的代码:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Line
from kivy import Config
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, 
ReferenceListProperty,ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
Config.set('graphics', 'multisamples', '0')

class TetrisGame(GridLayout):
    block1= ObjectProperty(None)



class Block1(Widget):
    vel_x = NumericProperty(0)
    vel_y = NumericProperty(-1)
    position = ReferenceListProperty(vel_x,vel_y)
    def fall(self, pos):
        self.pos =  Vector(self.position) + self.pos

class TetrisApp(App):
    def build(self):
        game = TetrisGame()
        block = Block1()
        Clock.schedule_interval(block.fall, 1/60)
        return block

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

.kv:

<Block1>:
canvas:
    Rectangle:
        size: root.width/5, root.height/20
        pos: self.pos

如何解决此问题?

2 个答案:

答案 0 :(得分:0)

Python代码

  1. 添加导入语句:from kivy.graphics import Rectanglefrom kivy.core.window import Window
  2. 设置块的起始位置block = Block1(pos=(0, Window.height))
  3. 将块添加到Root小部件game.add_widget(block)
  4. 返回根窗口小部件return game
  5. 实施方法来更新或删除您添加到画布的说明
  6. dt(增量时间)添加为fall()方法的参数。

注意

如果dt(delta-time)不在参数列表中,我们将遇到

TypeError: fall() takes 1 positional argument but 2 were given

因此,每当我们使用Kivy Clock调度函数时,都必须包含dt作为参数。

如果我们要调度不接受dt参数的函数,则可以使用lambda表达式编写不接受dt的简短函数。

kv文件

  1. 赋予块颜色

示例

main.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy import Config
from kivy.properties import NumericProperty, ReferenceListProperty,ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
Config.set('graphics', 'multisamples', '0')

from kivy.graphics import Rectangle
from kivy.core.window import Window


class TetrisGame(GridLayout):
    block1 = ObjectProperty(None)


class Block1(Widget):
    vel_x = NumericProperty(0)
    vel_y = NumericProperty(-1)
    position = ReferenceListProperty(vel_x,vel_y)

    def __init__(self, **kwargs):
        super(Block1, self).__init__(**kwargs)
        with self.canvas:
            self.rect = Rectangle(pos=self.pos, size=self.size)

        self.bind(pos=self.update_rect)
        self.bind(size=self.update_rect)

    def update_rect(self, *args):
        self.rect.pos = self.pos
        self.rect.size = self.size

    def fall(self, dt):
        self.pos = Vector(self.position) + self.pos


class TetrisApp(App):

    def build(self):
        game = TetrisGame()
        block = Block1(pos=(0, Window.height))
        game.add_widget(block)
        Clock.schedule_interval(block.fall, 1/60)
        return game


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

tetris.kv

#:kivy 1.11.0

<Block1>:
    canvas:
        Color:
            rgba: 1, 0, 0, 1    # red color block
        Rectangle:
            size: root.width/5, root.height/20
            pos: self.pos

输出

Img01 Img02 Img03

答案 1 :(得分:0)

首先,我要指出您代码的错误,TetrisGame是一个无用的类,因为在您的情况下,您仅将其分配给本地变量:game = TetrisGame(),当您将其删除时,完成build()的运行,另一方面,块被返回,因此其作用域增大。

另一个可能的错误是,您在放置时会认为:

size: root.width / 5, root.height/20 

您没有更改窗口小部件的大小,只绘制了窗口小部件的一小部分,构建的返回结果是您正在绘制窗口的一部分的窗口,您要做的是创建另一个窗口小部件。窗口并在其中添加子元素。您必须在构造函数中设置大小。

要解决的主要问题是,相对于约定,千伏中的位置相对于左下角,而y +和右x +相对。

解决方案是使用Window获取窗口的大小。

*。py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy import Config
from kivy.properties import NumericProperty, ReferenceListProperty
from kivy.vector import Vector
from kivy.clock import Clock
from kivy.core.window import Window


Config.set('graphics', 'multisamples', '0')


class Block1(Widget):
    vel_x = NumericProperty(0)
    vel_y = NumericProperty(-1)
    position = ReferenceListProperty(vel_x,vel_y)
    def fall(self, _):
        self.pos =  Vector(self.position) + self.pos

class BackGround(Widget):
    pass

class TetrisApp(App):
    def build(self):
        background = BackGround()
        block = Block1(pos=(0, Window.height), size=(Window.width/4, Window.height/20))
        background.add_widget(block)
        Clock.schedule_interval(block.fall, 1/60)
        return background

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

*。kv

<Block1>:
    canvas:
        Rectangle:
            size: root.size
            pos: self.pos

注意:

您不应使用GridLayout ,仅当您要以网格形式放置多个小部件时才应使用GridLayout,而在这种情况下,这不是您想要的。