Python - Kivy - Botones - Posición y funcionalidad.

 
Vista:
Imágen de perfil de Jorge Alberto
Val: 137
Ha disminuido 1 puesto en Python (en relación al último mes)
Gráfica de Python

Kivy - Botones - Posición y funcionalidad.

Publicado por Jorge Alberto (48 intervenciones) el 15/07/2021 03:31:07
Hola. ¿Qué tal? Estoy practicando con kivy y se me ocurrió hacer un programa que genere un anagrama, el usuario tenga que adivinar cuál es la palabra y que el programa indique si es correcta o no. En sí, conseguí que el programa hiciera eso con el siguiente código. El código es largo, pero creo que lo principal esta en las lineas 124 y 28, donde no sé si build() es la mejor función a usar. No creo que sea lo más práctico o eficiente, pero solamente estoy practicando, asique no busco tanto eso si no que funcione.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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 = (.10, .54, 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},
                                            on_press = self.on_press_restart)
        self.window.add_widget(self.RESTART)
 
        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
        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},
                                            on_press = self.on_press_new)
                self.window.add_widget(self.NEW)
 
            else:
                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)
                self.window.add_widget(self.SORRY)
 
 
    def on_press_restart(self, instance):
        under_index = 0
        for item in self.underscores:
            self.underscores[under_index].text = '_'
            under_index += 1
        self.ind = 0
        self.word = ''
        # self.window.remove_widget(self.SORRY)
 
    def on_press_new(self, instance):
        # self.choices = create_anagram()
        print(self.choices)
 
        self.window.remove_widget(self.NEW)     # It owrks, but the game doesn't restart.
        self.window.remove_widget(self.CONGRAT)
 
if __name__ == '__main__':
    MainApp().run()

El problema esta en que no sé cómo generar una función para un juego nuevo. Se me ocurrió generar otro código que tenga una función __init__, otra new_game y que en la función on_press_new devuelva la función new_game. Hice esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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)
 
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 = [],[]  # This lists will contain, respectively, the letters of the word and 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()

Pero al correr la aplicación los botones no funcionan (ya sé que no tienen función, pero ni siquiera puedo hacer click en los mismos) y se crea todo en la parte inferior izquierda muy chico. Dejo una imagen de lo que pasa:


KivyAnagram

Alguna idea de cómo solucionar cualquiera de los dos problemas? De nuevo, no pretendo, por ahora, ser eficiente, si no que funcione.

PD: la mayoría de las cosas esta en inglés porque estoy practicando con libros y videos en inglés. Si no se entiende algo lo modifico, pero se me hacía muy engorroso cambiarlo acá.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 2.808
Oro
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Kivy - Botones - Posición y funcionalidad.

Publicado por tincopasan (887 intervenciones) el 16/07/2021 04:12:19
te ayudaría pero... "No creo que sea lo más práctico o eficiente, pero solamente estoy practicando, asique no busco tanto eso si no que funcione." el problema que para que funcione tiene que ser práctico y hay que reescribir varias cosas. Ahora como estás aprendiendo como todos nosotros, te recomiendo que aprendas desde el inicio a ser práctico y eficiente, los malos hábitos se adquiiren fácil y los buenos cuestan un montón, es como esos niños que cuentan : 1,2,4,7,9,6,5,10 y te preguntan que sigue, lo importante es contar correctamente hasta donde sepas, después agregas otras cosas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Jorge Alberto
Val: 137
Ha disminuido 1 puesto en Python (en relación al último mes)
Gráfica de Python

Kivy - Botones - Posición y funcionalidad.

Publicado por Jorge Alberto (48 intervenciones) el 16/07/2021 04:59:26
Si, es verdad. Conviene ser práctico desde el principio. Igual me refería más a que es posible que el código se pueda mejorar, pero eso solamente lo da la práctica.

Aún así, el segundo código no creo que sea malo (exceptuando que la función create_anagram y la lista podrían estar en otro archivo, pero las dejo ahí para que se entienda de dónde sale lo escrito en la línea 30), pero desde el principio los botones no salen como corresponden y no entiendo el por qué. Creo que eso no se trata de practicidad, si no de que hay algún error en el código.

Pero comprendo completamente lo que decís y te agradezco el consejo. Desde ahora lo pondré en práctica.

Muchas gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 2.808
Oro
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Kivy - Botones - Posición y funcionalidad.

Publicado por tincopasan (887 intervenciones) el 16/07/2021 05:09:48
Bien! un consejo que me parece fundamental para kivy, agrega los widgets en otra clase, deja la clase que hereda de App para lo mínimo y una ayuda, busca sobre los metodos de uso de ScreenManager y Screen te van a ayudar mucho en lo que buscás.Mañana hago algo de ejemplo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Jorge Alberto
Val: 137
Ha disminuido 1 puesto en Python (en relación al último mes)
Gráfica de Python

Kivy - Botones - Posición y funcionalidad.

Publicado por Jorge Alberto (48 intervenciones) el 16/07/2021 05:24:29
Sisi. En realidad en el primer código lo hice por error. Para cuando me di cuenta quise ver cómo quedaba. En sí el programa funcionaba, pero bueno... tenía problemas.

Con respecto al segundo código, el problema estaba en el self.windows=RelativeLayout(). Cuando lo eliminé (y todo lo que estaba relacionado a eso) el programa empezó a funcionar. Ahora solamente me falta ver cómo generar un nuevo juego sin la necesidad de cerrar el programa. Intenté varias cosas, pero nada funciona, asique a seguir buscando.

Había leído algo de ScreenManager y Screen, pero quería practicar un poco antes de meterme con eso.

Gracias nuevamente por la respuesta.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar