저번 시간에는 Input widgets에 알아보았다. 이번에는 widgets을 배치할 수있는 layout에 대해서 알아보자.
widgets 이나 text을 배치할 수 있게 해주는 기능이다.
기본적으로 맨 우측과 좌측을 제외한 중앙 화면 기준으로 layout을 구성할 수 있다.
(물론 config를 바꾸면 전체화면을 활용할 수 있다.)
st.columns(spec, *, gap="small", vertical_alignment="top")
화면을 세로 방향으로 비율대로 나누어 text나 widgets을 배치할 수있게 해준다.
예를들어 내가 웹페이지 화면에서 1대1비율로 버튼을 배치하고자 한다면 아래 사진과 같이 배열을 할 수 있다.


기본적으로 코드는
import streamlit as st
col1, col2 = st.columns([1,1])
with col1:
st.button('test1')
col2.button('test2')
이런식으로 사용이 가능하다.
기본적으로 streamlit의 경우 오른쪽으 widgets이 배치가 되어진다.
예를들어 button을 양옆 끝으로 배치하고 싶다고 한다면import streamlit as st col1, *_, col2 = st.columns([1, 7, 1]) with col1: st.button('test1') col2.button('test2') with st.expander(label='test'): ...
이렇게 표현이 되는데 살짝 오른쪽으로 치우쳐짐을 확인 할 수 있다.
이때 비율을 조절하면 완전히 끝으로 붙일수는 있지만import streamlit as st col1, *_, col2 = st.columns([1, 8, 1]) with col1: st.button('test1') col2.button('test2') with st.expander(label='test'): ...
비율조절이 실패하면
이렇게 된다.
이것을 해결하기 위해 button의 use_container_width을 True로 설정해도 같은 결과가 나온다..
개인적으로 느끼기에 안쓸수는 없는 기능이지만 비율조절이 힘든 매울 짜증나는 기능이다.
st.container(*, height=None, border=None, key=None)

화면을 가로 방향으로 나누어 text나 widgets을 배치할 수있게 해준다.
colums와는 다르게 비율을 정하는게 아닌 위에서부터 컨테이너처럼 쌓듯이 배치해준다.
st.dialog(title, *, width="small")
modal창과 같은 기능이다.

어떤 특정 버튼이나 셀렉트박스를 선택하는 등의 상호작용을 통해서 보여진다.
(이게 왜 Layouts에 있는지 모르겟다.)
특정 함수위에 decorated를 통해서 정해진다.
예를들어 사진과 같은 dialog창을 나타내고싶으면
import streamlit as st
@st.dialog(title='Hello Dialog')
def a():
st.write('Hello')
if st.button('Dialog Button'):
a()
처럼 표현할 수있는데 a라는 함수위에 데코레이터 st.dialog를 통해서 dialog창을 나타낸다.
또한, 해당 a함수를 실행시키기 위해서 st.button을 삽입한 것도 볼 수 있다.

dialog의 경우, 위와같이 단순 text만 표현할 수 있지만 특정 input을 받아서 제출하는 용도로 활용할 수 있다.
이때, 어떤 버튼(예를 들면 submit)을 눌럿을 때, 자동으로 dialog창이 꺼지기를 원한다면 반드시 st.rerun을 넣어줘야 알아서 dialog창이 꺼지게 된다.
이때, st.rerun을 통해 dialog창을 꺼지게 한다면 dialog의 함수는 return값을 받을 수 없기에(기본적으로 st.rerun이후의 코드는 retrun코드처럼 실행이 되지않는다.) dialog의 input값을 받고 그 값을 활용하기 위해서는 꼭 st.sesstion_state을 통해 값을 전달 받아야 한다.dialog창 끄기
import streamlit as st @st.dialog(title='Hello Dialog', width='small') def a(): test = st.text_input(label='test') if st.button(label='Submit'): ... if st.button('Dialog Button'): a()test라는 text input을 받는 dialog창을 만들었다. 하지만 해당 dialog의 경우, Submit버튼을 눌러도 dialog창이 꺼지지 않게 된다. 여기서 만약 dialog창을 버튼을 누름과 동시에 꺼지게 하고 싶다면
import streamlit as st @st.dialog(title='Hello Dialog', width='small') def a(): test = st.text_input(label='test') if st.button(label='Submit'): st.rerun() if st.button('Dialog Button'): a()을 하면 된다.
값 주고 받기
위에서 dialog를 끄는법에 대해서 알았다. 그럼 이제 값을 주고받는 것에 대해서 알아보면
import streamlit as st @st.dialog(title='Hello Dialog', width='small') def a(): test = st.text_input(label='test') if st.button(label='Submit'): st.rerun() return test if st.button('Dialog Button'): test = a() print(test)이렇게 코드를 구성할 수 있을 것이다. dialog의 경우 함수 데코레이터처럼 쓰니 return을 통해서 값을 전달받으면 편하다. 하지만 해당 코드를 실행하면,
라는 오류 메세지를 볼 수 있게 된다. 왜냐하면 처음 실행할때, test라는 변수가 없기에 이런 오류가 생기는 것이다.
그렇다면 여기서 Dialog Button을 눌러서 test값을 정의하면 될 것 같지만,
같은 결과가 나옴을 알 수 있다. 원인은 위에서 서술한 것과 같은 이유이다.
따라서 위에 문제를 해결하기 위해서는 st.session_state를 써서 값을 전달받아야한다.import streamlit as st if 'test' not in st.session_state: st.session_state['test'] = None @st.dialog(title='Hello Dialog', width='small') def a(): test = st.text_input(label='test') if st.button(label='Submit'): st.session_state['test'] = test st.rerun() if st.button('Dialog Button'): a() print(st.session_state['test'])해당 코드를 실행하면 정상적으로 input값을 받을 수 있음을 확인 할 수 있다.