python-3.x Q:ValueError:创建pygame项目时未找到子字符串

0lvr5msh  于 2023-04-13  发布在  Python
关注(0)|答案(1)|浏览(84)

我正在做一个创建鼓机的项目,我是通过pygame在python中制作的,我得到了这个异常--

pygame 2.1.2 (SDL 2.0.18, Python 3.8.0)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 85, 
in _run_code
    exec(code, run_globals)
  File "c:\Users\Dell\.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
    cli.main()
  File "c:\Users\Dell\.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
    run()
  File "c:\Users\Dell\.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
    runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 262, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 95, 
in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 85, 
in _run_code
    exec(code, run_globals)
  File "c:\Users\Dell\Documents\My beatMaker\My beats app.py", line 228, in <module> 
    exit_button, loading_button, delete_button, load_rectangle = draw_load_menu()    
  File "c:\Users\Dell\Documents\My beatMaker\My beats app.py", line 157, in draw_load_menu
    name_index_start = saved_beats[beat].index('name: ') + 6
ValueError: substring not found

我是pygame的初学者,我正在通过freecodecamp.org学习。我试图从我的手中修复这个错误,没有任何工作。这是我的主文件-

main.py

import pygame
from pygame import mixer
pygame.init()

WIDTH = 1300
HEIGHT = 650

black = (0, 0, 0)
white = (255, 255, 255)
gray = (128, 128, 128)
dark_gray = (50, 50, 50)
green = (0, 255, 0)
gold = (212, 175, 55)
blue = (0, 255, 255)

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Beat Maker")
label_font = pygame.font.Font("Roboto-Bold.ttf", 32)
medium_font = pygame.font.Font("Roboto-Bold.ttf", 24)

fps = 60
timer = pygame.time.Clock()
beats = 8
instruments = 5
boxes = []
clicked = [[-1 for _ in range(beats)] for _ in range(instruments)]
active_list = [1 for _ in range(instruments)]
bpm = 240
playing = True
active_length = 0
active_beat = 0
beat_changed = True
save_menu = False
load_menu = False
saved_beats = []
file = open('saved_beats.txt', 'r')
for line in file:
    saved_beats.append(line)
beat_name = ''
typing = False

# load in sounds
hi_hat = mixer.Sound('sounds\hi hat.wav')
snare = mixer.Sound('sounds\snare.wav')
drum = mixer.Sound('sounds\kick.wav')
crash = mixer.Sound('sounds\crash.wav')
clap = mixer.Sound('sounds\clap.wav')
pygame.mixer.set_num_channels(instruments * 3)

def play_notes():
    for i in range(len(clicked)):
        if clicked[i][active_beat] == 1 and active_list[i] == 1:
            if i == 0:
                hi_hat.play()
            if i == 1:
                snare.play()
            if i == 2:
                drum.play()
            if i == 3:
                crash.play()
            if i == 4:
                clap.play()


def draw_grid(clicks, beat, actives):
    left_box = pygame.draw.rect(screen, gray, (0,0, 206, HEIGHT - 150), 4)
    bottom_box = pygame.draw.rect(screen, gray, (0, HEIGHT - 150, WIDTH, 150), 4)
    boxes = []
    colors = [gray, white, gray]

    hi_hat_text = label_font.render('Hi Hat', True, colors[actives[0]])
    screen.blit(hi_hat_text, (30, 40))

    snare_text = label_font.render('Snare', True, colors[actives[1]])
    screen.blit(snare_text, (30, 145))

    drum_text = label_font.render('Bass Drum', True, colors[actives[2]])
    screen.blit(drum_text, (30, 240))

    crash_text = label_font.render('Crash', True, colors[actives[3]])
    screen.blit(crash_text, (30, 340))

    clap_text = label_font.render('Clap', True, colors[actives[4]])
    screen.blit(clap_text, (30, 435))

    for i in range(instruments):
        pygame.draw.line(screen, gray, (0, (i*100)+1), (200, (i*100)+1), 3)

    for i in range(beats):
        for j in range(instruments):
            if clicks[j][i] == -1:
                color = gray
            else:
                if active_list[j] == 1:
                    color = green
                else:
                    color = dark_gray
            rect = pygame.draw.rect(screen, color, 
                                                  ((i * ((WIDTH-200) // beats) + 200), (j*100), 
                                                   ((WIDTH-200) // beats), ((HEIGHT-150)//instruments)
                                                  ), 0, 3
                                   )
            pygame.draw.rect(screen, gold, 
                                          ((i * ((WIDTH-200) // beats) + 200), (j*100), 
                                          ((WIDTH-200) // beats), ((HEIGHT-150)//instruments)
                                          ), 5, 5
                                   )
            pygame.draw.rect(screen, black, 
                                                  ((i * ((WIDTH-200) // beats) + 200), (j*100), 
                                                   ((WIDTH-200) // beats), ((HEIGHT-150)//instruments)
                                                  ), 2, 5
                                   )
            boxes.append((rect, (i, j)))

        active = pygame.draw.rect(screen, blue, (beat*((WIDTH-200)//beats)+200, 0, ((WIDTH-200)//beats), instruments*100), 5, 3)
    return boxes

def draw_save_menu(beat_name, typing):
    pygame.draw.rect(screen, black, (0, 0, WIDTH, HEIGHT))
    menu_text = label_font.render('SAVE MENU: Enter a Name for Current beat', True, white)
    saving_btn = pygame.draw.rect(screen, gray, (WIDTH//2 - 166, HEIGHT*0.75, 400, 100), 0, 5)
    saving_txt = label_font.render('Save beat', True, white)
    screen.blit(saving_txt, (WIDTH//2-50, HEIGHT*0.75+30))
    screen.blit(menu_text, (400, 40))
    exit_btn = pygame.draw.rect(screen, gray, (WIDTH-200, HEIGHT-100, 180, 90), 0, 5)
    exit_text = label_font.render('Close', True, white)
    screen.blit(exit_text, (WIDTH-150, HEIGHT-70))
    if typing:
        pygame.draw.rect(screen, dark_gray, (400, 200, 600, 200), 0, 5)
    entry_rect = pygame.draw.rect(screen, gray, (400, 200, 600, 200), 5, 5)
    entry_text = label_font.render(f'{beat_name}', True, white)
    screen.blit(entry_text, (430, 250))
    return exit_btn, saving_btn, entry_rect

def draw_load_menu():
    pygame.draw.rect(screen, black, (0, 0, WIDTH, HEIGHT))
    menu_text = label_font.render('LOAD MENU: Select a Beat a Load', True, white)
    loading_btn = pygame.draw.rect(screen, gray, (WIDTH//2 - 166, HEIGHT*0.87, 400, 100), 0, 5)
    loading_txt = label_font.render('Load beat', True, white)
    delete_btn = pygame.draw.rect(screen, gray, ((WIDTH//2)-600, HEIGHT*0.87, 200, 100), 0, 5)
    delete_text = label_font.render('Delete Beat', True, white)
    screen.blit(delete_text, ((WIDTH//2)-583, HEIGHT*0.87+30))
    screen.blit(loading_txt, (WIDTH//2-50, HEIGHT*0.87+30))
    screen.blit(menu_text, (400, 40))
    exit_btn = pygame.draw.rect(screen, gray, (WIDTH-200, HEIGHT-100, 180, 90), 0, 5)
    exit_text = label_font.render('Close', True, white)
    screen.blit(exit_text, (WIDTH-150, HEIGHT-70))
    loaded_rectangle = pygame.draw.rect(screen, gray, (190, 90, 1000, 450), 3, 5)
    for beat in range(len(saved_beats)):
        if beat < 10:
            beat_clicked = []
            row_text = medium_font.render(f'{beat + 1}', True, white)
            screen.blit(row_text, (200, 100 + beat * 50))
            name_index_start = saved_beats[beat].index('name: ') + 6
            name_index_end = saved_beats[beat].index(', beats:')
            name_text = medium_font.render(saved_beats[beat][name_index_start:name_index_end], True, white)
            screen.blit(name_text, (240, 100 + beat * 50))
    return exit_btn, loading_btn, delete_btn, loaded_rectangle


run = True
while run:
    timer.tick(fps)
    screen.fill(black)

    boxes = draw_grid(clicked, active_beat, active_list)
    # lower menu buttons
    play_pause = pygame.draw.rect(screen, gray, (50, HEIGHT-100, 200, 100), 0, 5)
    play_text = label_font.render('Play/Pause', True, white)
    screen.blit(play_text, (70, HEIGHT-80))
    if playing:
        play_text2 = medium_font.render('Playing', True, dark_gray)
    else:
        play_text2 = medium_font.render('Paused', True, dark_gray)
    screen.blit(play_text2, (70, HEIGHT-40))
    # bpm stuff
    bpm_rect = pygame.draw.rect(screen, gray, (300, HEIGHT - 100, 250, 100), 5, 5)
    bpm_text = medium_font.render('Beats Per Minute', True, white)
    screen.blit(bpm_text, (330, HEIGHT-80))
    bpm_text2 = medium_font.render(f'{bpm}', True, dark_gray)
    screen.blit(bpm_text2, (330, HEIGHT-40))
    bpm_add_rect = pygame.draw.rect(screen, gray, (560, HEIGHT-100, 45, 45), 0, 5)
    bpm_sub_rect = pygame.draw.rect(screen, gray, (560, HEIGHT-50, 45, 45), 0, 5)
    add_text = medium_font.render('+5', True, white)
    sub_text = medium_font.render('-5', True, white)
    screen.blit(add_text, (565, HEIGHT-89))
    screen.blit(sub_text, (567, HEIGHT-40))

    # beats stuff
    beats_rect = pygame.draw.rect(screen, gray, (700, HEIGHT - 100, 250, 100), 5, 5)
    beats_text = medium_font.render('Beats Per Loop', True, white)
    screen.blit(beats_text, (730, HEIGHT-80))
    beats_text2 = medium_font.render(f'{beats}', True, dark_gray)
    screen.blit(beats_text2, (730, HEIGHT-40))
    beats_add_rect = pygame.draw.rect(screen, gray, (960, HEIGHT-100, 45, 45), 0, 5)
    beats_sub_rect = pygame.draw.rect(screen, gray, (960, HEIGHT-50, 45, 45), 0, 5)
    add_text2 = medium_font.render('+1', True, white)
    sub_text2 = medium_font.render('-1', True, white)
    screen.blit(add_text2, (965, HEIGHT-89))
    screen.blit(sub_text2, (967, HEIGHT-40))

    # instruments rects
    instruments_rects = []
    for i in range(instruments):
        rect = pygame.rect.Rect((0, i * 100), (200, 100))
        instruments_rects.append(rect)
    
    # save and load stuff
    save_button = pygame.draw.rect(screen, gray, (1050, HEIGHT-100, 200, 40), 0, 5)
    save_text = label_font.render('Save Beat', True, white)
    screen.blit(save_text, (1077, HEIGHT - 100))
    load_button = pygame.draw.rect(screen, gray, (1050, HEIGHT-50, 200, 40), 0, 5)
    load_text = label_font.render('Load beat', True, white)
    screen.blit(load_text, (1077, HEIGHT - 50))

    # clear board
    clear_button = pygame.draw.rect(screen, gray, (570, HEIGHT - 150, 200, 40), 0, 5)
    clear_text = label_font.render('Clear', True, white)
    screen.blit(clear_text, (635, HEIGHT-147))

    if save_menu:
        exit_button, saving_button, entry_rectangle = draw_save_menu(beat_name, typing)
    if load_menu:
        exit_button, loading_button, delete_button, load_rectangle = draw_load_menu()

    # sounds stuff
    if beat_changed:
        play_notes()
        beat_changed = False

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            for i in range(len(boxes)):
                if boxes[i][0].collidepoint(event.pos) and not save_menu and not load_menu:
                    coords = boxes[i][1]
                    clicked[coords[1]][coords[0]] *= -1
        if event.type == pygame.MOUSEBUTTONUP and not save_menu and not load_menu:
            if play_pause.collidepoint(event.pos) and playing:
                playing = False
            elif not playing:
                playing = True
            elif bpm_add_rect.collidepoint(event.pos):
                bpm += 5
            elif bpm_sub_rect.collidepoint(event.pos):
                bpm -= 5
            elif beats_add_rect.collidepoint(event.pos):
                beats += 1
                for i in range(len(clicked)):
                    clicked[i].append(-1)
            elif beats_sub_rect.collidepoint(event.pos):
                beats -= 1
                for i in range(len(clicked)):
                    clicked[i].pop(-1)
            elif clear_button.collidepoint(event.pos):
                clicked = [[-1 for _ in range(beats)] for _ in range(instruments)]
            elif save_button.collidepoint(event.pos):
                save_menu = True
            elif load_button.collidepoint(event.pos):
                load_menu = True
            for i in range(len(instruments_rects)):
                if instruments_rects[i].collidepoint(event.pos):
                    active_list[i] *= -1
        elif event.type == pygame.MOUSEBUTTONUP:
            if exit_button.collidepoint(event.pos):
                save_menu = False
                load_menu = False
                playing = True
                beat_name = ''
                typing = False
            elif entry_rectangle.collidepoint(event.pos):
                if typing:
                    typing = False
                elif not typing:
                    typing = True
            elif saving_button.collidepoint(event.pos):
                file = open('saved_beats.txt', 'w')
                saved_beats.append(f'\nname: {beat_name}, beats: {beats}, bpm: {bpm}, selected: {clicked}')
                for i in range(len(saved_beats)):
                    file.write(str(saved_beats[i]))
                file.close()
                save_menu = False
                typing = False
                beat_name = ''
        if event.type == pygame.TEXTINPUT and typing:
            beat_name += event.text
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_BACKSPACE and len(beat_name) > 0 and typing:
                beat_name = beat_name[:-1]

    beat_length = 3600 // bpm

    if playing:
        if active_length < beat_length:
            active_length += 1
        else:
            active_length = 0
            if active_beat < beats - 1:
                active_beat += 1
                beat_changed = True
            else:
                active_beat = 0
                beat_changed = True

    pygame.display.flip()

pygame.quit()

看看有没有什么不对的地方。我会尽力改正我的错误。
谢谢

2nc8po8w

2nc8po8w1#

这似乎是一个模糊的问题。在不知道文件内容的情况下,看起来好像是通过以下几行:

saved_beats.append(f'\nname: {beat_name}, beats: {beats}, bpm: {bpm}, selected: {clicked}')
for i in range(len(saved_beats)):
    file.write(str(saved_beats[i]))

你有一个f字符串,它的开头是\n,当它被写入文件时,会产生如下内容:

name: foo, beats: 3, bpm: 10, selected: bar
name: foo, beats: 3, bpm: 10, selected: bar
name: foo, beats: 3, bpm: 10, selected: bar
.
.
.

注意开头的空行。
您可以将\n移动到行尾。

saved_beats.append(f'name: {beat_name}, beats: {beats}, bpm: {bpm}, selected: {clicked}\n')

或者如果你必须保持特定的格式:
变更:

if beat < 10:
    beat_clicked = []
    row_text = medium_font.render(f'{beat + 1}', True, white)
    screen.blit(row_text, (200, 100 + beat * 50))
    name_index_start = saved_beats[beat].index('name: ') + 6
    name_index_end = saved_beats[beat].index(', beats:')
    name_text = medium_font.render(saved_beats[beat][name_index_start:name_index_end], True, white)
    screen.blit(name_text, (240, 100 + beat * 50))

if beat < 10:
    beat_clicked = []
    if saved_beats[beat].startswith("name:"):
        row_text = medium_font.render(f'{beat + 1}', True, white)
        screen.blit(row_text, (200, 100 + beat * 50))
        name_index_start = saved_beats[beat].index('name: ') + 6
        name_index_end = saved_beats[beat].index(', beats:')
        name_text = medium_font.render(saved_beats[beat][name_index_start:name_index_end],
                                       True, white)
        screen.blit(name_text, (240, 100 + beat * 50))

如果该行不是以name:开头,则将跳过所有屏幕更改。
你也可以将if条件改为:

if len(saved_beats[beat].strip()) > 0:

相关问题