Search code examples
pythonuser-interfacepyglet

Changing the contents of a Pyglet Window, after clicking a buttons


Recently, I was making a UI app from Pyglet, which would basically be a To-Doer. It consists of a main menu, which will display all the text files in the folder. These text files contains a list of the task that I have to, with the name of the text file as the general name for those tasks. For example, if I have to make a To-Do list while coding a game, the file name could "Pong.txt" and may contain a list as so ["Set up background", "Player Inputs", "Character movement", "UI", "Exporting"]. Upon clicking the bullet point next to the item, it should open up a menu showing all of the tasks that I have to do. There is also a plus sign to create new tasks for a new project and the first thing you type will be the file name.

The problem that is coming is in the transition from the main-menu to the to-do menu, where it should display.

  • Set up background
  • Player Inputs
  • Character movement
  • UI
  • Exporting

on the click of a button. Since the code is 300 lines and I was not sure which all parts were important, I am attaching the entire code here, because at Stack, they appreciate, having the code with the question instead of a GitHub link.

def draw(line:list):
    dataCopy.clear()
    textList.clear()
    coords.clear()
    dataCopyGenerator(len(line), dataCopy)
    endpoint = 585 - (len(dataCopy) * 45)

    for i in range(585, endpoint, -45):
        l = len(dataCopy) - (585 - i)//45
        j = len(dataCopy) - l
        if i % 45 == 0 and j <= len(dataCopy):
            if len(textList) >= len(boxList):
                dataCopy[j] = pt.shapes.Rectangle(10, i-15, 30, 30, color=pink, batch=otherMenu)
                boxList.append(dataCopy[j])
                dataCopy[j].draw()
        if {'x': 10, 'y': i, 'size': 30} in coords:
            continue
        else:
            coords.append({'x': 10, 'y': i, 'size': 30})
        dataCopy[j] = pt.text.Label(t, font_name="Times New Roman", font_size=24, x=60,
                                    y=i, anchor_x='left', anchor_y='center', batch=otherMenu, color=TextColor2)
        textList.append(dataCopy[j])
    for i in range(len(textList)):
        print(i)
        textList[i].text = line[i]
def mainMenu():
    filesCopy.clear()
    dataCopyGenerator(len(files), filesCopy)
    endpoint = 585 - (len(filesCopy) * 45)

    for i in range(585, endpoint, -45):
        l = len(filesCopy) - (585 - i)//45
        j = len(filesCopy) - l
        if i % 45 == 0 and j <= len(filesCopy):
            if len(filesList) >= len(circleList):
                filesCopy[j] = pt.shapes.Circle(30, i-5, radius=10,color=pink, batch=menu)
                circleList.append(filesCopy[j])
                filesCopy[j].draw()
        if {'x': 10, 'y': i, 'size': 30} in menuCoords:
            continue
        else:
            menuCoords.append({'x': 10, 'y': i, 'size': 30})
        filesCopy[j] = pt.text.Label(t, font_name="Times New Roman", font_size=24, x=60,
                                    y=i, anchor_x='left', anchor_y='center', batch=menu, color=TextColor2)
        filesList.append(filesCopy[j])
    for i in range(len(filesList)):
        filesList[i].text = files[i]

@window.event
def on_mouse_press(x, y, button, modifiers):
    global data, menuIsVisible, line
    
    #Main Menu
    for i in range(len(menuCoords)):
        if (button == pt.window.mouse.LEFT) and x > circleList[i].x - circleList[i].radius and x < ( circleList[i].x+ circleList[i].radius) and y >  circleList[i].y - circleList[i].radius and y < ( circleList[i].y + circleList[i].radius):
            menuIsVisible == False
            back_line1.visible = True
            back_line2.visible = True
            with open(files[i] + ".txt", "r") as f:
                line = f.read()
                line1 = list(map(str.strip, line.strip('][').replace('"', '').split(',')))
            draw(line1)    
            print (line1)
            return menuIsVisible, line1

@window.event
def on_draw():
    global menuIsVisible, line1

    window.clear()
    batch.draw()
    title.draw()
    textFieldB.draw()
    typed_text.draw()
    if menuIsVisible == True:        
        mainMenu()
        menu.draw()
    elif menuIsVisible == False:
        draw(line1)
        print
        otherMenu.draw()
@window.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
    if scroll_y == 1:        
        if title.y < background.height - 40:
            return
        else:
            for i in range(len(textList)):
                textList[i].y -= 10
            for i in range(len(boxList)):
                boxList[i].y -= 10
            title.y -= 10
    elif scroll_y == -1:
        for i in range(len(textList)):
            textList[i].y += 10
        for i in range(len(boxList)):
            boxList[i].y += 10
        title.y += 10
        

pt.app.run()

Appreciate it!

Edit: I have posted just the functions which draw, the main menu and the other menu along with some important window.event.


Solution

  • What you need is a Scene Manager. A scene manager basically handles all the scene changing and the stuff alike while making games. A good way to make one in pyglet will be to create a class for all you items. Then create a function inside the class which will hide and show all the items

    class item1:
        def __init__(self): 
            self.obj1 = pyglet.shapes.Rectangle(x, y, width, height, color, batch)
            self.obj2 = pyglet.shapes.Rectangle(x, y, width, height, color, batch) 
        def show(self):
            obj1.visible = True
            obj2.visible = True
        def hide(self):
            obj1.visible = False
            obj2.visible = False
    
    class item2:
        def __init__(self): 
            self.obj1 = pyglet.shapes.Rectangle(x, y, width, height, color, batch)
            self.obj2 = pyglet.shapes.Rectangle(x, y, width, height, color, batch) 
        def show(self):
            obj1.visible = True
            obj2.visible = True
        def hide(self):
            obj1.visible = False
            obj2.visible = False
    

    Now create a class called sceneManager

    class sceneManager:
        def __init__(self): 
            pass 
        def scene1(self):
            item1.show()
            item2.hide()
    
        def scene2(self):
            item1.hide()
            item2.show()
    

    Now you can call the sceneManager.scene2() once you click the button.