Kivy - 添加和删除标签

时间:2013-08-01 03:36:51

标签: python python-2.7 label kivy

我是Kivy的新手,无法找到有关添加和删除标签的真正答案。我通过Pong教程(你可能已经猜到了),并为4名玩家进行了调整。现在,我尝试添加标签以显示文本Winner!,然后点击该文字重新开始游戏。

到那里,它正在工作。问题是,在新游戏开始后,我无法让标签再次消失。此外,我不了解格式 - 我似乎无法使我的标签更大或在面板中将其降低。

我要发布所有代码,因为希望你还是喜欢玩这个游戏(一旦它被修复),我在那里肯定了#sa; sa添加和删​​除文本的更好,更少的方式。

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import NumericProperty, ReferenceListProperty,\
    ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint


class PongPaddle(Widget):
    score = NumericProperty(0)
    orientation = ObjectProperty([0, 0])
    can_move = ObjectProperty(0)

    def bounce_ball(self, ball):
        if self.collide_widget(ball):
            vx, vy = ball.velocity
            if self.orientation[0] == 25:                
                offset = (ball.center_y - self.center_y) / (self.height / 2)
                bounced = Vector(-1 * vx, vy)
                vel = bounced * 1.1
                ball.velocity = vel.x, vel.y + offset
            else:
                offset = (ball.center_x - self.center_x) / (self.width / 2)
                bounced = Vector(vx, -1 * vy)
                vel = bounced * 1.1
                ball.velocity = vel.x + offset, vel.y


class PongBall(Widget):
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)

    def move(self):
        self.pos = Vector(*self.velocity) + self.pos

class PongGame(Widget):
    ball = ObjectProperty(None)
    player1 = ObjectProperty(None)
    player2 = ObjectProperty(None)
    player3 = ObjectProperty(None)
    player4 = ObjectProperty(None)

    def initialize(self):
        SCORE = 1
        self.player1.orientation = [25, 200]
        self.player2.orientation = [25, 200]
        self.player3.orientation = [200, 25]
        self.player4.orientation = [200, 25]
        self.player1.score = SCORE
        self.player2.score = SCORE
        self.player3.score = SCORE
        self.player4.score = SCORE
        self.player1.can_move = 1
        self.player2.can_move = 1
        self.player3.can_move = 1
        self.player4.can_move = 1
        self.serve_ball()

    def serve_ball(self, vel=(4, 0)):
        self.ball.center = self.center
        self.ball.velocity = vel

    def update(self, dt):
        self.ball.move()

        #bounce of paddles
        self.player1.bounce_ball(self.ball)
        self.player2.bounce_ball(self.ball)
        self.player3.bounce_ball(self.ball)
        self.player4.bounce_ball(self.ball)

        #bounce ball off bottom or top
        if ((self.ball.y < self.y) and not self.player3.can_move) \
           or ((self.ball.top > self.top) and not self.player4.can_move):
            self.ball.velocity_y *= -1
        if ((self.ball.x < self.x) and not self.player1.can_move) \
           or ((self.ball.right > self.width) and not self.player2.can_move):
            self.ball.velocity_x *= -1

        #went off to a side to score point?
        if self.ball.x < self.x and self.player1.can_move == 1:
            self.player1.score -= 1
            self.serve_ball(vel=(4, randint(1, 4)))
            if self.player1.score <= 0:
                self.player1.can_move = 0
        elif self.ball.x > self.width and self.player2.can_move == 1:
            self.player2.score -= 1
            self.serve_ball(vel=(-4, randint(1, 4)))
            if self.player2.score <= 0:
                self.player2.can_move = 0
        elif self.ball.y > self.height and self.player4.can_move == 1:
            self.player4.score -= 1
            self.serve_ball(vel = (randint(1, 4), -4))
            if self.player4.score <= 0:
                self.player4.can_move = 0
        elif self.ball.y < self.y and self.player3.can_move == 1:
            self.player3.score -= 1
            self.serve_ball(vel = (randint(1, 4), 4))
            if self.player3.score <= 0:
                self.player3.can_move = 0

        if self.player1.can_move + self.player2.can_move + \
           self.player3.can_move + self.player4.can_move == 1:
            self.ball.velocity = (0, 0)
            global win_label
            win_label = Label(size_hint=(None, None),
                              text='[ref=winner]Winner![/ref]',
                              markup=True, text_size=(70, None))
            #win_label.texture_update()
            win_label.pos = (self.width / 2, self.height / 2 - 70)
##            win_label.size =  win_label.texture_size[0] + 20, \
##                             win_label.texture_size[1] + 20
            win_label.bind(on_ref_press=self.click_win_label)
            win_label.texture_update()
            self.add_widget(win_label)

    def click_win_label(self, instance, value):
        self.initialize()
        self.remove_widget(win_label)


    def on_touch_move(self, touch):
        if touch.x < self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player1.can_move:
            self.player1.center_y = touch.y
        if touch.x > self.width - self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player2.can_move:
            self.player2.center_y = touch.y
        if touch.y < self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player3.can_move:
            self.player3.center_x = touch.x
        if touch.y > 2* self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player4.can_move:
            self.player4.center_x = touch.x


class PongApp(App):
    def build(self):
        game = PongGame()
        game.initialize()
        game.serve_ball()
        Clock.schedule_interval(game.update, 1.0 / 60.0)
        return game


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

.kv文件:

#:kivy 1.0.9

<PongBall>:
    size: 50, 50 
    canvas:
        Ellipse:
            pos: self.pos
            size: self.size          

<PongPaddle>:
    size: root.orientation[0], root.orientation[1]
    canvas:
        Rectangle:
            pos:self.pos
            size:self.size

<PongGame>:
    ball: pong_ball
    player1: player_left
    player2: player_right
    player3: player_top
    player4: player_bottom


    Label:
        font_size: 50  
        center_x: root.width / 6
        top: root.top - root.height / 2 + 50
        text: str(root.player1.score)

    Label:
        font_size: 50  
        center_x: root.width * 5 / 6
        top: root.top - root.height / 2 + 50
        text: str(root.player2.score)

    Label:
        font_size: 50
        center_x: root.width / 2
        top: root.height / 6
        text: str(root.player3.score)

    Label:
        font_size: 50
        center_x: root.width / 2
        top: 5 * root.height / 6
        text: str(root.player4.score)

    PongBall:
        id: pong_ball
        center: self.parent.center

    PongPaddle:
        id: player_left
        x: root.x
        center_y: root.center_y

    PongPaddle:
        id: player_right
        x: root.width-self.width
        center_y: root.center_y

    PongPaddle:
        id: player_top
        y: root.y
        center_x: root.center_x

    PongPaddle:
        id: player_bottom
        y: root.height - self.height
        center_x: root.center_x

1 个答案:

答案 0 :(得分:1)

正在删除Label,问题是你正在添加无数个:)因为更新方法计划在每1/60秒调用一次:

Clock.schedule_interval(game.update, 1.0 / 60.0)

如果您的计算机不会冻结,则需要在添加小部件之前取消安排:

Clock.unschedule(self.update)

以下代码有效。我想建议不要使用全局变量(这只是一个非常糟糕的做法)。我也修改过。由于参数instance包含与self.win_label完全相同的内容,因此您甚至不需要此案例的类属性。另外,我改变了你居中的方式(self.win_label.center = self.center)。最后,使用[Button][1]而不是Label会更容易,因为您可以绑定其他方法,例如on_presson_release。实际上,您不需要ref。您只需绑定on_touch_down

即可
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import NumericProperty, ReferenceListProperty,\
    ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint


class PongPaddle(Widget):
    score = NumericProperty(0)
    orientation = ObjectProperty([0, 0])
    can_move = ObjectProperty(0)

    def bounce_ball(self, ball):
        if self.collide_widget(ball):
            vx, vy = ball.velocity
            if self.orientation[0] == 25:                
                offset = (ball.center_y - self.center_y) / (self.height / 2)
                bounced = Vector(-1 * vx, vy)
                vel = bounced * 1.1
                ball.velocity = vel.x, vel.y + offset
            else:
                offset = (ball.center_x - self.center_x) / (self.width / 2)
                bounced = Vector(vx, -1 * vy)
                vel = bounced * 1.1
                ball.velocity = vel.x + offset, vel.y


class PongBall(Widget):
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)

    def move(self):
        self.pos = Vector(*self.velocity) + self.pos

class PongGame(Widget):
    ball = ObjectProperty(None)
    player1 = ObjectProperty(None)
    player2 = ObjectProperty(None)
    player3 = ObjectProperty(None)
    player4 = ObjectProperty(None)

    def initialize(self):
        SCORE = 1
        self.player1.orientation = [25, 200]
        self.player2.orientation = [25, 200]
        self.player3.orientation = [200, 25]
        self.player4.orientation = [200, 25]
        self.player1.score = SCORE
        self.player2.score = SCORE
        self.player3.score = SCORE
        self.player4.score = SCORE
        self.player1.can_move = 1
        self.player2.can_move = 1
        self.player3.can_move = 1
        self.player4.can_move = 1
        self.serve_ball()

    def serve_ball(self, vel=(4, 0)):
        self.ball.center = self.center
        self.ball.velocity = vel

    def update(self, dt):
        self.ball.move()

        #bounce of paddles
        self.player1.bounce_ball(self.ball)
        self.player2.bounce_ball(self.ball)
        self.player3.bounce_ball(self.ball)
        self.player4.bounce_ball(self.ball)

        #bounce ball off bottom or top
        if ((self.ball.y < self.y) and not self.player3.can_move) \
           or ((self.ball.top > self.top) and not self.player4.can_move):
            self.ball.velocity_y *= -1
        if ((self.ball.x < self.x) and not self.player1.can_move) \
           or ((self.ball.right > self.width) and not self.player2.can_move):
            self.ball.velocity_x *= -1

        #went off to a side to score point?
        if self.ball.x < self.x and self.player1.can_move == 1:
            self.player1.score -= 1
            self.serve_ball(vel=(4, randint(1, 4)))
            if self.player1.score <= 0:
                self.player1.can_move = 0
        elif self.ball.x > self.width and self.player2.can_move == 1:
            self.player2.score -= 1
            self.serve_ball(vel=(-4, randint(1, 4)))
            if self.player2.score <= 0:
                self.player2.can_move = 0
        elif self.ball.y > self.height and self.player4.can_move == 1:
            self.player4.score -= 1
            self.serve_ball(vel = (randint(1, 4), -4))
            if self.player4.score <= 0:
                self.player4.can_move = 0
        elif self.ball.y < self.y and self.player3.can_move == 1:
            self.player3.score -= 1
            self.serve_ball(vel = (randint(1, 4), 4))
            if self.player3.score <= 0:
                self.player3.can_move = 0

        if self.player1.can_move + self.player2.can_move + \
           self.player3.can_move + self.player4.can_move == 1:
            self.ball.velocity = (0, 0)
            Clock.unschedule(self.update)

            self.win_label = Label(size_hint=(None, None),
                              text='[ref=winner]Winner![/ref]',
                              markup=True, font_size=70, color=[1,0,0,1])
            #win_label.texture_update()
            #self.win_label.pos = (self.width / 2, self.height / 2 - 70)
            self.win_label.center = self.center
##            win_label.size =  win_label.texture_size[0] + 20, \
##                             win_label.texture_size[1] + 20
            self.win_label.bind(on_ref_press=self.click_win_label)
            self.win_label.texture_update()
            self.add_widget(self.win_label)


    def click_win_label(self, instance, value):
        self.remove_widget(self.win_label)
        #self.remove_widget(instance) # this should also work:
        self.initialize()
        Clock.schedule_interval(self.update, 1.0 / 60.0)



    def on_touch_move(self, touch):
        if touch.x < self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player1.can_move:
            self.player1.center_y = touch.y
        if touch.x > self.width - self.width / 3 and touch.y > self.height / 6 \
            and touch.y < 5 * self.height / 6 and self.player2.can_move:
            self.player2.center_y = touch.y
        if touch.y < self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player3.can_move:
            self.player3.center_x = touch.x
        if touch.y > 2* self.height / 3 and touch.x > self.width / 6 \
            and touch.x < 5 * self.width / 6 and self.player4.can_move:
            self.player4.center_x = touch.x


class PongApp(App):
    def build(self):
        game = PongGame()
        game.initialize()
        #game.serve_ball()
        Clock.schedule_interval(game.update, 1.0 / 60.0)
        return game

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