mlodycezar
mlodycezar

Reputation: 57

Values disappear after using button in streamlit

I am trying to write an application to play Wheel of Fortune. Once I draw a password and want to e.g. draw points the password disappears. I know that this is caused by refreshing the application after pressing another button, but I do not know how to stop it.

This is how my code looks like.

import streamlit as st
import random

# Create a list containing the letters in a word
def lista_slowo(slowo):
    slowo = slowo.lower()
    lista_slowo = []
    for litera in slowo:
        lista_slowo.append(litera)
    return lista_slowo

# Create an empty list to display
def pusta_lista_na_tablicy(slowo):
    pusta_lista_na_tablicy = []
    for litera in slowo:
        pusta_lista_na_tablicy.append("_")
    return pusta_lista_na_tablicy

# Converting a list to a string
def zamien_na_stringa(lista_na_tablicy):
    napis = ""
    for x in lista_na_tablicy:
        napis = napis + x + " "
    return napis

st.sidebar.title("Koło fortuny")
st.sidebar.text("Witamy w grze Koło Fortuny.")
st.sidebar.text("Wybierz liczbę graczy.\nNastępnie kliknij przycisk 'Losuj kategorię'.")

slownik_kategorii = {"Zwierzęta":["Krowa","Kura","Koń"],
             "Owoce":["Mandarynka","Pomarańcza","Truskawka"],
             "Warzywa":["Ogórek","Marchewka","Sałata"],
             "Ubrania":["Spodnie","Koszulka","Koszula"],
            "Pojazdy":["Samochód","Motocykl","Samolot"]}

slownik_wartosci = [100,200,300,400,500,600,700,800,900,1000,1500,0]



ilosc_graczy = st.sidebar.selectbox("Wybierz ilość graczy",[1,2])

losuj = st.sidebar.button("Losuj kategorię")

kategoria = st.subheader("")

if losuj:
    kategoria = random.choice(list(slownik_kategorii))
    st.subheader(f"Kategoria: {kategoria}")
    slowo = random.choice(slownik_kategorii[kategoria])
    lista_na_tablicy = pusta_lista_na_tablicy(slowo)
    napis = zamien_na_stringa(lista_na_tablicy)
    st.title(napis)

    st.text("Słowo do odgadnięcia " + slowo)


odgaduj = st.sidebar.button("Odgadnij hasło")
krec = st.sidebar.button("Kręć kołem")
podaj_litere = st.sidebar.button("Podaje spółgłoskę")

if krec:
    wartosc = random.choice(slownik_wartosci)
    st.sidebar.text("Wartość spółgłoski: " + str(wartosc) + " zł")

if podaj_litere:
    podana_litera = ""
    podana_litera = st.sidebar.text_input("Wpisz spółgłoskę")
    st.sidebar.text(podana_litera)

I tried to replace the password generation button with a radio, but then every time you click another button the password draw from scratch

Upvotes: 1

Views: 3572

Answers (1)

MathCatsAnd
MathCatsAnd

Reputation: 861

1. Buttons don't retain state

Check out these similar questions/answers: here and here And this blog post I mentioned in both: here

Buttons do not retain state. They return True on the page load resulting from their click and then immediately go back to False. If you nest something inside a button, it will go away as soon as the user does something (because the page reloads and the button becomes false).

You can store a dictionary in session state to track if buttons are clicked so your conditionals don't revert to False.

Here's a simple example for general applicability:

import streamlit as st

if 'clicks' not in st.session_state:
    st.session_state['clicks'] = {}

def click(key):
    st.session_state.clicks[key] = True

def unclick(key):
    st.session_state.clicks[key] = False

def button_set(i):
    left, right = st.columns(2)
    left.button(f'Button {i}', on_click=click, args=(f'button{i}',))
    if st.session_state.clicks.get(f'button{i}', False):
        left.write(f'Button {i} was clicked!')
        st.slider(f'Slider {i}', key=f'slider{i}')
        right.button(f'Reset Button {i}', on_click=unclick, args=(f'button{i}',))

for i in range(3):
    button_set(i)

st.write(st.session_state)

2. Use session state to preserve random generation between reruns

Since Streamlit reruns with every interaction, care needs to be taken with random selection. In general, save any random generation to session state so that you can control when it is regenerated.

import streamlit as st
import random

animals = ['dog', 'cat', 'bird', 'fish', 'turtle', 'rabbit', 'hamster', 'snake', 'lizard', 'frog']

if 'my_pet' not in st.session_state:
    st.session_state.my_pet = random.choice(animals)

st.write(f"My pet is a {st.session_state.my_pet}.")

def change_pet():
    st.session_state.my_pet = random.choice(animals)

st.button("Change my pet", on_click=change_pet)

st.button('Do nothing')
st.slider('Move me', 0, 100)

3. Text display widgets have no output

This line doesn't make sense: kategoria = st.subheader("")

Upvotes: 2

Related Questions