1

So i'm making a game for a class project and i want to add a grid of button, the size don't matter but after 2 day of try i m lost here is my python code:

import numpy as np
from collections import namedtuple

from kivy.app import App

from kivy.clock import Clock

from kivy.core.audio import SoundLoader
from kivy.core.window import Window
from kivy.graphics import Canvas
from kivy.graphics import Rectangle
from kivy.lang import Builder

from kivy.properties import ObjectProperty
from kivy.properties import ListProperty

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.screenmanager import NoTransition 
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget

field = namedtuple('field', ['rows', 'cols'])
FIELD = field(30, 60)

global a
a = "play"

        
class Jeu(Screen):     
    #here is the screen for the button grid
    #
    #
    #
    def test(self):
        Clock.schedule_interval(the_callback,0.1)
    def stop(self):
        Clock.unschedule(the_callback)

class MenuScreen(Screen):     
    pass
            
class RuleScreen (Screen):
    pass

class SettingsScreen(Screen):
    sound=SoundLoader.load('oui.wav')
    def fullscreen(self):
        name = self.ids.fullscreen.text
        if  Window.fullscreen == True:
            self.ids.fullscreen.text = 'Fullscreen off'
            Window.fullscreen = False
        else:
            self.ids.fullscreen.text = 'Fullscreen on'
            Window.fullscreen = True
    
    def music(self):
        sound=SoundLoader.load('oui.wav')
        name = self.ids.music.text
        global a
        if a == "play":
            self.ids.music.text = 'Music off'
            a= "stop"
             
        else:
            self.ids.music.text = 'Music on'
            a= "play"

class PloytestApp(App):
    def build(self):
        # Create the screen manager
        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(Jeu(name='jeu'))
        sm.add_widget(RuleScreen(name='rules'))
        sm.add_widget(SettingsScreen(name='settings'))
        sm.transition = NoTransition()
        return sm

sound=SoundLoader.load('oui.wav')
def my_callback(dt):
    if a=="stop":
        sound.stop()
    elif a =="play":
        sound.play()
event = Clock.schedule_interval(my_callback, 1 / 30.)

def the_callback(dt):
    print("aaaaa")
    
if __name__ == '__main__':
    PloytestApp().run()
    App.stop(exit())


and my .kv filles

#: import Window kivy.core.window.Window 
#:  import Clock kivy.clock


    
<MenuScreen>:
    GridLayout:
        cols: 1
        Image:
            id: gif
            source: 'test.zip' 
            allow_stretch: True
            keep_aspect: False
            anim_loop: 0
            Label:
                pos: self.parent.pos
                size: self.parent.size
                text:"Connway's game of life"
                font_size: 60
                color: 0.5, 0.8, 1, 1
                
        GridLayout:
            cols: 1
            Button:
                text: 'Play'
                on_release:
                    root.manager.current = 'jeu'
            Button:
                text:  'How to Play'
                on_release:
                    root.manager.current = 'rules'
            Button:
                text: 'Goto settings'
                on_release: 
                    root.manager.current = 'settings'
            Button:
                text: 'Quit'
                on_release: app.stop() 

<Jeu>:  
    GridLayout:
            cols:1
            Label:
               ** #here is the grid of button**
                text: "here the grid of button"
        GridLayout:
            cols:4
            ToggleButton:
                id:start
                text: 'Start simulation'
                on_state:
                    if self.state == 'normal':\
                    print("aa")
                    root.test()
                    if self.state == 'normal':\
                    root.stop()
            Button:
                id:next
                text: 'Next Generation'
            Button:
                id:clear
                text: 'Clear'
                on_press:
                    start.state ='normal' if start.state == 'down' else 'normal'
            Button:
                text:"Back to menu"
                on_press:
                    start.state ='normal' if start.state == 'down' else 'normal'
                on_release: 
                    root.manager.current = 'menu'
        
<RuleScreen>:
    GridLayout:
        cols:1
        Image:
            source: 'rules.jpg'
        GridLayout:
            cols: 2
            Button:
                text: 'Setting'
                on_release:
                    root.manager.current = 'settings'
            Button:
                text: 'Back to menu'
                on_release:
                    root.manager.current = 'menu'

<SettingsScreen>:
    GridLayout:
        cols: 1
        size: root.width - 100, root.height -100
        Button:
            id: fullscreen
            text: "Fullscreen off"
            on_release:
                root.fullscreen()
        Button:
            id: music
            text: "Music on"
            on_release:
                root.music()
        Button:
            text: 'Back to menu'
            on_press:                
                root.manager.current = 'menu'

i try to put a for loop but with no sucess, i tried to change the class of "Jeu" from Screen to GridLayout it not allow to start the program. I just want a grid of toggle button 10x10 is a good start .

I m sorry for the level of english it s not my main language so there may be french in my code. Also i use thonny to code since i m lazy and it s the program school make us instal. Thanks in advance for the help.

alex
  • 13
  • 3

1 Answers1

1

You would want to use RecycleView with RecycleGridLayout, as shown in this post.

file.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen

class Jeu(Screen):
    pass

class PloytestApp(App):

    def build(self):
        sm = ScreenManager()
        sm.add_widget(Jeu(name="jeu"))
        return sm

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

ploytest.kv

<Jeu>:
    RecycleView:
        data: [{'text': str(x)} for x in range(10 * 10)]
        viewclass: 'ToggleButton'

        RecycleGridLayout:
            rows: 10
            cols: 10
            size_hint: 1, 1
            default_size_hint: 1, 1

If you need to apply a custom text to each button, then you could use something like this

#:set texts [...]

<Jeu>:
    RecycleView:
        data: [{'text': texts[x]} for x in range(10 * 10)]
        viewclass: 'ToggleButton'

        RecycleGridLayout:
            rows: 10
            cols: 10
            size_hint: 1, 1
            default_size_hint: 1, 1

The first line declares a list named texts, in which you can put your 100 different texts.

Finally, if you want to add additional properties to each button, you can add as many as you want inside the data dictionary in the kv file. For example, if you want to also add some red color to the button's text:

<Jeu>:
    RecycleView:
        data: [{'text': str(x), 'color': (1, 0, 0, 1)} for x in range(10 * 10)]
        viewclass: 'ToggleButton'

        RecycleGridLayout:
            rows: 10
            cols: 10
            size_hint: 1, 1
            default_size_hint: 1, 1

EDIT

<Jeu>:
    BoxLayout:
        orientation: 'vertical'

        RecycleView:
            data: [{'text': str(x)} for x in range(10 * 10)]
            viewclass: 'ToggleButton'

            RecycleGridLayout:
                rows: 10
                cols: 10
                size_hint: 1, 1
                default_size_hint: 1, 1

        GridLayout:
            size_hint: 1, 0.1
            cols:4

            ToggleButton:
                text: 'Start simulation'

            Button:
                text: 'Next Generation'

            Button:
                text: 'Clear'

            Button:
                text:"Back to menu"
  • i tried what you suggest, but now i have the 100 Button behind the 4 button i use to go back to the main menu. I don't know how to resolve that. The 100 must be on top of the 4 other. thanks you anyway you make me done progress on my problem – alex Mar 30 '23 at 07:48
  • I don't know if I understood you clearly enough, but if you need the 100 buttons _above_ the other 4, then I've just edited the answer with that. It uses a BoxLayout to separate between the grid of 100 buttons and the grid of the other 4 buttons. If you need to change the sizing, just change the size_hint of the second GridLayout. – Gabriel Checchi Mar 30 '23 at 15:45
  • with your edit it work perfectly as i wanted thank you so much for the time you gave on my problem. – alex Mar 31 '23 at 10:50