【问题标题】:Kivy - Labels, Buttons and LayoutsKivy - 标签、按钮和布局
【发布时间】:2021-09-24 13:05:15
【问题描述】:

你好世界! 首先,我是这个页面的英文版的新手。我认为我的英语很好,但如果有任何错误,请告诉我,我会改正的。其次,我编写的代码(我会在一分钟内向您展示)可能不是最有效的,但我只希望它工作。事情是这样的……

我正在练习 kivy,我决定制作一个程序,它可以从单词列表中创建一个字谜,用户必须猜测这个单词,然后程序会判断它是否正确。我制作了一个程序,但我遇到了“新单词”按钮的问题(可以说是一个新游戏),所以我决定制作一个新代码(我会向你展示旧版本)一条评论)。而这个新代码从一开始就失败了。当我添加标签和按钮时,我不仅无法点击它们,而且它们还显示在屏幕的左下角,而且非常小。图片显示结果:Labels, Buttons and RelativeLayout

from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from random import choice, shuffle
from kivy.core.window import Window

Window.clearcolor = (.10, .54, 1, 1)
Window.size = (500,300)

# ------- THIS PART SHOULD GO ON A SEPARATE FILE ----------------------------
list_of_words = ['ELEPHANT', 'LION', 'COCODRILE', 'MONKEY', 'KANGAROO']

def create_anagram():
    # Takes a word from the list and shuffles the letters to create the anagram
    choices = choice(list_of_words)
    list_letters = []
    for item in choices:
        list_letters.append(item)
    shuffle(list_letters)
    choices = ''.join(list_letters)

    return choices
# ----------------------------------------------------------------------------
class Anagram(RelativeLayout):

    def __init__(self, **kwargs):
        super(Anagram, self).__init__(**kwargs)
        # These are all variables which will be used later on.

        self.choices = create_anagram()
        self.window = RelativeLayout()
        self.font_size = 20                     
        self.letters, self.underscores = [],[]  
        self.ind = 0                            # Index used on chose_letter()
        self.size_x, self.size_y = 100, 50      # Sizes for the labels and button
        self.pos_x = 0                          # Initial position for the labels and buttons
        self.word = ''                          # will concatonate the letters choosen

        self.new_game()

    def new_game(self):
        with self.canvas.after:
            for item in self.choices:
                self.letters.append(Button(text=item,
                                        size_hint=(1/len(self.choices), 0.2),
                                        pos_hint = {'x': self.pos_x, 'top': .8},
                                        font_size = self.font_size,
                                        color='#688FF8',
                                        background_color = '#1F48F2',
                                        disabled = False))

                self.underscores.append(Label(text='_',
                                        size_hint=(1/len(self.choices), 0.2),
                                        pos_hint = {'x': self.pos_x, 'top': 0.4},
                                        size=(self.size_x, self.size_y),
                                        font_size = self.font_size,
                                        color = '#FFFFFF'))

                self.pos_x += 1/len(self.choices)

            # Adding buttons for the letters and the underscores.
        for item in self.letters:
            self.window.add_widget(item)
        for item in self.underscores:
            self.window.add_widget(item)

class MainAnagramApp(App):
    def build(self):
        return Anagram()

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

就是这样。这就是代码和问题所在。知道为什么会这样吗?

顺便说一句,我试过不使用“with self.canvas”,但它甚至没有显示小部件。我也尝试过更改布局(Grid、Anchor等),但问题完全一样。

谢谢!

【问题讨论】:

    标签: python button layout kivy label


    【解决方案1】:

    您不需要self.window = RelativeLayout()with self.canvas.after:。这是您的 Anagram 类的修改版本:

    class Anagram(RelativeLayout):
    
        def __init__(self, **kwargs):
            super(Anagram, self).__init__(**kwargs)
            # These are all variables which will be used later on.
    
            self.choices = create_anagram()
            # self.window = RelativeLayout()
            self.font_size = 20
            self.letters, self.underscores = [],[]
            self.ind = 0                            # Index used on chose_letter()
            self.size_x, self.size_y = 100, 50      # Sizes for the labels and button
            self.pos_x = 0                          # Initial position for the labels and buttons
            self.word = ''                          # will concatonate the letters choosen
    
            self.new_game()
    
        def new_game(self):
            # with self.canvas.after:
            for item in self.choices:
                self.letters.append(Button(text=item,
                                        size_hint=(1/len(self.choices), 0.2),
                                        pos_hint = {'x': self.pos_x, 'top': .8},
                                        font_size = self.font_size,
                                        color='#688FF8',
                                        background_color = '#1F48F2',
                                        disabled = False))
    
                self.underscores.append(Label(text='_',
                                        size_hint=(1/len(self.choices), 0.2),
                                        pos_hint = {'x': self.pos_x, 'top': 0.4},
                                        size=(self.size_x, self.size_y),
                                        font_size = self.font_size,
                                        color = '#FFFFFF'))
    
                self.pos_x += 1/len(self.choices)
    
            # Adding buttons for the letters and the underscores.
            for item in self.letters:
                self.add_widget(item)
            for item in self.underscores:
                self.add_widget(item)
    

    注意ButtonsLabels 是使用self.add_widget() 而不是self.window.add_widget() 添加的。

    在您的代码中,当您在with self.canvas.after: 中创建Button 时,用于绘制Button 的画布指令将添加到Anagram 实例的canvas.after 中。但是没有添加实际的Button 小部件。所以你有一个Button 的图像,但它不能用作Button

    【讨论】:

    • 非常感谢。现在它起作用了。在我尝试过的第一个代码中(我忘了在另一条评论中向您展示)我使用了 self.window = RelativeLayout() 并且 wigdets 显示在窗口上。知道为什么这次没有用吗?我将在下一个答案中显示代码。
    • 关于canvas.after,实际上我一开始并没有输入(只有canvas)。我想过尝试 canvas.after 看看它是否有效,然后我忘了删除它。也谢谢你。
    【解决方案2】:

    这是旧版本的代码。这是对约翰·安德森的回答。

    from kivy.app import App
    from kivy.uix.relativelayout import RelativeLayout
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.button import Button
    from kivy.uix.label import Label
    from random import choice, shuffle
    from kivy.core.window import Window
    
    Window.clearcolor = (24/243, 132/243, 1, 1)
    Window.size = (500,300)
    
    list_of_words = ['ELEPHANT', 'LION', 'COCODRILE', 'MONKEY', 'KANGAROO']
    
    def create_anagram():
        # Chooses a word from the list and shuffles the letters to create the anagram
    
        choices = choice(list_of_words)
        list_letters = []
        for item in choices:
            list_letters.append(item)
        shuffle(list_letters)
        choices = ''.join(list_letters)
    
        return choices
    
    class MainApp(App):
    
        def build(self):
    
            # These are all variables which will be used later on.
            
            self.choices = create_anagram()
            self.window = RelativeLayout()
            self.font_size = 20
            self.letters, self.underscores = [],[]
            self.ind = 0                         # Index used on chose_letter()
            self.size_x, self.size_y = 100, 50
            self.pos_x = 0
            self.word = ''                       # will concatonate the letters choosen.
    
            # Adding the buttons to the respectives lists.
            for letter in self.choices:
                self.window.add_widget(Button(text=letter,
                                            size_hint=(1/len(self.choices), 0.2),
                                            pos_hint = {'x': self.pos_x, 'top': .8},
                                            font_size = self.font_size,
                                            color='#688FF8',
                                            background_color = '#1F48F2',
                                            on_press = self.chose_letter,
                                            disabled = False))
                
                self.underscores.append(Label(text='_',
                                            size_hint=(1/len(self.choices), 0.2),
                                            pos_hint = {'x': self.pos_x, 'top': 0.4},
                                            size=(self.size_x, self.size_y),
                                            font_size = self.font_size,
                                            color = '#FFFFFF'))
    
                self.pos_x += 1/len(self.choices)
    
            # Adding buttons for the letters and the underscores.
            for item in self.letters:
                self.window.add_widget(item)
            for item in self.underscores:
                self.window.add_widget(item)            
    
            self.RESTART = Button(text='RESTART',
                                                size_hint=(0.2,0.1),
                                                font_size = 12,
                                                pos_hint = {'center_x': .5,'center_y': 0.1},
                                                background_color = '#B50E0E',
                                                on_press = self.on_press_restart)
            self.window.add_widget(self.RESTART)
    
            self.SORRY = Label(text='SORRY, WORNG WORD!',
                                                size_hint=(.8, .4),
                                                pos_hint = {'center_x':0.5, 'center_y': 0.45},
                                                font_size = self.font_size,
                                                color = '#1884F3')
            self.window.add_widget(self.SORRY)
    
            return self.window
    
    
        
        def chose_letter(self, instance):
            # When the user clicks on a letter, it adds that letter to the first empty label and to self.word
            
            if self.ind == len(self.choices):               # If we click a button when the word is complete (either correct or incorrect)
                return True                                 # This will allow the program not to add 1 to self.ind (and will not cursh)
    
            _choice = instance.text                         # Gets the text from the button
            # instance.disabled = True
            self.underscores[self.ind].text = _choice       # Changes the first underscore for the text in _choice
            self.ind += 1                                   # Adds 1 to the index counter
            self.word += _choice                            # Copies the word created, in order to compare it to the words on the list (in the next line)
            
    
            # It shows a message, either the word is correct or not.
            
            if len(self.choices) == len(self.word):
                if self.word in list_of_words:
                    self.CONGRAT = Label(text='CONGRATULATIONS! THE WORD IS: ',
                                                size_hint=(.8, .4),
                                                pos_hint = {'center_x':0.5, 'center_y': 0.45},
                                                font_size = self.font_size)
                    self.window.add_widget(self.CONGRAT)
    
                    self.NEW = Button(text='NEW WORD',
                                                size_hint=(0.2,0.1),
                                                font_size = 12,
                                                pos_hint = {'center_x': .5,'center_y': 0.1},
                                                background_color = '#B50E0E',
                                                on_press = self.on_press_new)
                    self.window.add_widget(self.NEW)
                else:
                    self.SORRY.color = '#000000'
    
                
            
    
    
        def on_press_restart(self, instance):
            
            for item in range(len(self.underscores)):
                self.underscores[item].text = '_'
    
    
            self.ind = 0
            self.word = ''
            self.SORRY.color = '#1884F3'
            
        def on_press_new(self, instance):
            # self.choices = create_anagram()
            print(self.choices)
            
            self.window.remove_widget(instance)     # It owrks, but the game doesn't restart.
            self.window.remove_widget(self.CONGRAT)
    
    if __name__ == '__main__':
        MainApp().run()
    

    【讨论】:

    • 顺便说一句,我不认为这是因为缺少画布。我已经尝试了没有它的第二个代码,但它仍然无法正常工作。但我当然可能是错的。
    • 在这段代码中,您将在build() 方法中构建按钮和标签,并将self.window 作为App 的根小部件返回。在您原始帖子的代码中,self.window 从未实际使用过。
    • @JohnAnderson 再次感谢您。我得到了它!现在我更仔细地查看了代码,我可以看到我已经可以让它变得更好(我已经尝试过了)。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2023-03-24
    • 2012-09-29
    • 2023-04-04
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多