如何更改弹出窗口上的属性等于打开弹出窗口的按钮的属性?

时间:2017-11-15 16:42:42

标签: python python-3.x kivy

我的项目是纸牌游戏。每张卡也是一个按钮。当您点击正在播放的卡片时,会弹出一个弹出窗口,其中包含卡片图像,卡片文本的可滚动标签以及各种按钮。

PopUp

我目前的问题是尝试更改弹出窗口中的图像和文本以匹配实际的卡片按钮信息。我目前能够更改显示的信息,但仅作为最新的定义。据我所知,这是因为我重新定义了class属性,而不是class属性的实例。

我已尝试在卡片(按钮图片)文件中执行def__init __(自我,参数):但是当我尝试执行PlayMatWidget的绘制方法时,这会崩溃。

我认为这可能与Kivy对象属性有关,但我并不完全确定如何使用它们(主要是因为按钮不是在运行时创建的)

感谢您阅读!

Python文件:

body{
    max-width: 300px;
}
.discussionMessageDate {
    background: rgba(255, 255, 255, 0.8);
    border-radius: 10px;
    padding: 5px 13px;
    max-width: 300px;
    display: block;
    text-align: center;
}

.clearer{
    clear: both;
}

<div>
    <div class="discussionMessageDate">{date here}</div>
        <ul class="noDot">
            <li class="right"><span class="discussionMessage">{message}</span></li>
            <li class=""><span class="discussionMessage">{message}</span></li>
            <li class="right"><span class="discussionMessage">{message}</span></li>
        </ul>
    </div>
    <div class="clearer"></div>
    <div>
        <div class="discussionMessageDate">{date here}</div>
            <ul class="noDot">
                <li class="noDot + ..logic to figure out if to apple 'right' class"><span class="discussionMessage">{message}</span></li>
            </ul>
        </div>
    </div>

Kivy档案:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.lang import Builder
import random

Builder.load_string('''
<ScrollableLabel>:
    Label:
        size_hint_y: None
        height: self.texture_size[1]
        text_size: self.width, None
        text: root.text
''')


class ScrollableLabel(ScrollView):
    text = StringProperty('')


# Visual Representation of a Card or Deck
class ImageButton(ButtonBehavior, Image):
    pass


class CardBackend:
    def __init__(self, name, card_art, effect_one):
        self.name = name
        self.card_art = card_art
        self.effect = effect_one


class Card(ImageButton):
    # Defining the Popup Window
    main_pop = Popup()
    main_pop.title = 'Inspect Card'
    main_pop.title_align = 'center'
    main_pop.size_hint = None, None
    main_pop.size = 400, 400
    main_pop.auto_dismiss = False
    main_pop.opacity = 0.8

    # Variables or Variables to Be
    card_text = 'ABCDEFGHIJK1234567890' * 100
    card_art = Image(source='test.png', size_hint=(.9, .85), pos_hint={'x': -0.18, 'y': .125})

    # Primary Child Widget
    main_box = FloatLayout()

    # Buttons
    play_button = Button(text='Play', size_hint=(0.32, 0.1), pos_hint={'x': 0.01, 'y': 0.0})
    discard_button = Button(text='Discard', size_hint=(0.32, 0.1), pos_hint={'x': 0.34, 'y': 0.0})
    close_button = Button(text='Close', size_hint=(0.32, 0.1), pos_hint={'x': 0.67, 'y': 0.0})
    close_button.bind(on_press=main_pop.dismiss)

    # Scrolling Card Text Viewer
    card_info = ScrollableLabel(text=card_text, size_hint=(0.45, .8), pos_hint={'x': .55, 'y': .15})

    # Building main_pop.content
    main_box.add_widget(play_button)
    main_box.add_widget(discard_button)
    main_box.add_widget(close_button)
    main_box.add_widget(card_info)
    main_box.add_widget(card_art)
    main_pop.content = main_box


class PlayMatWidget(FloatLayout):
    def draw(self):
        # Create Backend
        # Draw Backend
        # Create Card() using Backend

        # Defining Card Data (Removed for imported Decks)
        backend_bewd = CardBackend('Blue Eyes White Dragon', 'bewd.png', 'One')
        backend_dragon = CardBackend('Dragon Egg', 'test.png', 'Two')
        backend_lava = CardBackend('Lava Golem', 'lavagolem.png', 'Three')

        # Creating Card Button Objects
        card_zero = Card()
        card_one = Card()
        card_two = Card()

        # Defining Card Title
        card_zero.main_pop.title = backend_lava.name
        card_one.main_pop.title = backend_dragon.name
        card_two.main_pop.title = backend_bewd.name

        # Defining Card Text for Scrollview
        card_zero.card_info.text = backend_bewd.effect

        # Defining Card Art
        card_zero.source = backend_bewd.card_art
        card_one.source = backend_dragon.card_art
        card_two.source = backend_lava.card_art

        deck_dictionary = {
            0: card_zero,
            1: card_one,
            2: card_two,
        }

        # Prototype Shuffle for top card
        # drawing = random.choice(deck_list)

        # Creating a Physical Card Object
        # drawn_card = Card()

        # OLD
        # Applying Card Data from backend to front end Card Object
        # drawn_card.main_pop.title = drawing.name
        # drawn_card.source = drawing.card_art
        # drawn_card.card_art.source = drawing.card_art
        # drawn_card.card_info.text = drawing.effect

        # Used to check somethings
        for x in range(0, 3):
            print(deck_dictionary[x].source)
            print(deck_dictionary[x].main_pop.title)

        self.ids.PlayerField.add_widget(random.choice(deck_dictionary), index=int(len(self.ids.PlayerField.children)/2))


class CardGameApp(App):
    def build(self):
        return PlayMatWidget()


if __name__ == "__main__":
    CardGameApp().run()

2 个答案:

答案 0 :(得分:0)

1 /每当你覆盖__init__方法时,你需要调用super()方法,如果不对kivy小部件这样做,它们会崩溃,因为它们不会被正确初始化,对于python 3我相信你想做

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

2 /通常在kivy中,创建属性并按名称传递它更容易,而不是将参数传递给init,这样你甚至不需要覆盖__init__,避免1 /中的错误

class CardBackend:
    name = StringProperty()
    card_art = StringProperty()
    effect = stringProperty()

…

card = CardBackend(
    name='Blue Eyes White Dragon',
    card_art='bewd.png',
    effect='One')

或者,在kv中使用

CardBackend:
    name: 'Blue Eyes White Dragon'
    card_art: 'bewd.png'
    effect: 'One'

3 /在Card中你确实定义了类中的所有内容而不是__init__,这意味着当定义类时,此代码将运行,而不是实例是创建的,也许你真的想要一个函数,而不是一个类?或者您可能希望覆盖on_press的{​​{1}}方法,并使用卡的属性而不是当前使用的硬编码值将所有代码放入其中。

答案 1 :(得分:0)

我解决了。我将弹出框的创建移动到了卡类的功能中。在kivy文件中,我将inspect_card()函数绑定到Kivy卡按钮的on_press事件。

以前Pop Up是在创建卡时定义的。因此,无论我点击哪个卡片按钮,弹出窗口始终都会将信息对应于最新创建的卡片。

将其移动到一个函数意味着只在启动该函数时才创建Pop Up,因此所有相关信息都对应于调用它的Button的源信息。这样,实例是否在类内部并不重要,因为每次运行时都会重新定义它。

Success Video

卡类具有功能:

class Card(ImageButton):
    # Defining the Popup Window
    def inspect_card(self):
        main_pop = Popup()
        main_pop.title = 'Inspecting ' + self.cardname
        main_pop.title_align = 'center'
        main_pop.size_hint = None, None
        main_pop.size = 400, 400
        main_pop.auto_dismiss = False
        main_pop.opacity = 0.8

        # Variables or Variables to Be
        card_text = self.effecttext
        card_art = Image(source=self.source, size_hint=(.9, .85), pos_hint={'x': -0.18, 'y': .125})

        # Primary Child Widget
        main_box = FloatLayout()

        # Buttons
        play_button = Button(text='Play', size_hint=(0.32, 0.1), pos_hint={'x': 0.01, 'y': 0.0})
        discard_button = Button(text='Discard', size_hint=(0.32, 0.1), pos_hint={'x': 0.34, 'y': 0.0})
        close_button = Button(text='Close', size_hint=(0.32, 0.1), pos_hint={'x': 0.67, 'y': 0.0})
        close_button.bind(on_press=main_pop.dismiss)

        # Scrolling Card Text Viewer
        card_info = ScrollableLabel(text=card_text, size_hint=(0.45, .8), pos_hint={'x': .55, 'y': .15})

        # Building main_pop.content
        main_box.add_widget(play_button)
        main_box.add_widget(discard_button)
        main_box.add_widget(close_button)
        main_box.add_widget(card_info)
        main_box.add_widget(card_art)
        main_pop.content = main_box
        main_pop.open()

Kivy卡片按钮,弹出

的新绑定和引用属性
<Card@ImageButton>:
    size_hint: 0.8,0.8
    pos_hint: {'x':0, 'y':0.1}
    cardname: 'stuff'
    effecttext: 'ABCDEFGHIJKL123456789' * 30
    on_press: print('confirming press')
    on_press: root.inspect_card()

(Prop列出的值是默认值,我在MainGameWidget中将它们更改为下面的字段。稍后我会将其中的大部分内容移到Deckbuilder功能中)