MENU

【入門】Streamlitで魅せるUIを速攻開発!要点&実用サンプル満載

本ブログではこれまで、自作ツール開発の記事で CustomTkinter を中心に取り上げてきました。


その理由は、ドラッグ&ドロップ操作の快適さに加え、ファイルサイズや周辺機器へのアクセス制限をあまり気にせず使えるという利点があるからです。

しかし、CustomTkinter には大きな弱点もあります。
特に、テーブル形式のデータ表示については標準でサポートされておらず、外部モジュールを組み合わせても使い勝手に課題が残るのが現状です。

そこで今回注目したのが、Streamlitです。本記事では、初めてStreamlitを使う方を対象に、

  • Streamlitの概要と注意点
  • UI作成時のポイント
  • よく使うウィジェットの解説

について、実用的でコピペOKなサンプルコードを交えながら、「すぐに使える」Webアプリ開発の基礎を丁寧に紹介していきます。

普段TkinterやCustomTkinterでUIを組んでいる方はもちろん、Pythonで初めてUI開発に挑戦する方にもおすすめの内容です。

目次

Streamlitの概要

引用元:https://streamlit.io/

Streamlitは、PythonスクリプトをそのままWebアプリとして動かせるフレームワークです。
特に機械学習やデータ分析の分野で注目を集めており、プログラミングの知識があれば、ほんの数行のコードだけで美しいインタラクティブなUIが作れるのが大きな特徴です。

従来、Webアプリを作るには、HTMLやJavaScript、CSSといった複数の技術を学ぶ必要がありました。
しかしStreamlitを使えば、Pythonのコードだけで、フォームやボタン、グラフ、テーブルなどを簡単に画面上に表示することができます。

import streamlit as st

st.title("こんにちは、Streamlit!")

name = st.text_input("あなたの名前は?")

# ボタンが押されたら表示
if st.button("表示する"):
    st.write(f"ようこそ、{name}さん!")

詳しい使い方は、下記のStreamlit公式サイトをご確認ください。

セットアップ方法https://docs.streamlit.io/get-started/installation
公式ドキュメントhttps://docs.streamlit.io/
APIリファレンス(ウィジェット、グラフ描画など)https://docs.streamlit.io/develop/api-reference

米国・サンフランシスコに拠点を置くスタートアップ「Streamlit Inc.」によって開発され、2019年10月にリリースされました。その後、2022年3月にSnowflake社(クラウドデータプラットフォーム企業)に約8億ドルで買収され、現在はSnowflakeの一部として開発・運用が続けられています

Streamlitの動作原理

Streamlit コマンドの引数に Python ファイルを指定することで、そのスクリプトを Web アプリとして実行できます。

streamlit run Pythonファイル

streamlit コマンドは単なるランチャーとして動作し、内部で Tornado ベースの軽量 Web サーバを起動するとともに、指定された Python スクリプトを Python インタプリタ上で実行します。

Python ファイルに記述された Streamlit のウィジェットは、ブラウザから送られてきた入力情報を受け取り、スクリプトを再実行し、その結果を HTML や JavaScript に変換してブラウザへ返すことで、Web アプリとして動作します。

Streamlitの最大の特徴は、スクリプト駆動(Script-Driven)であるということです。

つまり、streamlit run demo.py のようにアプリを起動すると、Pythonスクリプトが最初の1行目から順に実行され、それがそのまま画面に反映されるというシンプルな動作モデルになっています。

Streamlitの注意点

Streamlitはシンプルで強力ですが、いくつか注意点・特徴があります。

  • ファイルやフォルダの扱いに制限がある
    ブラウザでのUIであるため、セキュリティポリシーの観点からフォルダ選択ダイアログは提供されていません。
    ファイル選択ダイアログは利用可能ですが、アップロードされたファイルのローカルでのフルパス情報は取得できません。更に、選択できるファイルの容量制限(デフォルトは200MBまで、設定により拡張可能)が存在します。

  • スクリプトは毎回先頭から再実行される
    ボタンを押す、入力を変える、ページを開くなどのイベントが発生するたびに、Pythonファイル全体が先頭から実行されます。そのため、importの数やプログラムの量が多い場合は、画面の動作が遅くなります。

  • 毎回ページ全体がリレンダリングされる
    Pythonファイル全体が先頭から実行されるため、画面も毎回全て再描画されます。

  • 状態管理を明示的に行う必要がある
    通常の状態では、変数は「前回の値を保持」できません。入力や処理結果を保持するには、st.session_stateを使って変数の値を保持・更新する必要があります。

  • 基本はシングルプロセスで動作
    各セッション(ユーザーの接続)は内部的には独立して処理されますが、Pythonのグローバル変数やモジュールスコープの変数はプロセス全体で共有されます。同時接続が増えると共有リソースの競合や意図しないデータの混在が起きる場合があります。

  • ページ遷移や複雑なルーティングは標準では苦手
    Streamlitは「1ページ完結型アプリ」として最適化されているため、複雑なページ遷移やページごとの権限管理は制限が多く、実装しづらいです。

  • HTML/JSの自由度が低め
    st.markdown(unsafe_allow_html=True) で一部HTMLの記述は可能ですが、それでも足りない場合はStreamlit Componentsと呼ばれる拡張機能を用いる必要があります。

  • デバッグでブレイクポイントが使えない
    VisualCodeなどの統合開発環境において、ブレイクポイントで処理を止めて、変数の中身を確認することが困難です。いくつか方法はありますが、いずれも設定が複雑であり、うまく行かないことも多いです。
    幸いなことに、イベントの発生で必ずプログラムが頭から再実行されるため、プログラムの修正内容が即座に反映される(結果が確認できる)という大きなメリットもあります。

  • 動作環境と運用面
    ローカルPC、Streamlit Cloud(旧Streamlit Sharing)、Dockerコンテナなどで動かせます。
    オンプレや独自サーバーでも運用可能ですが、セキュリティ・スケーラビリティ設計は要検討です。

Streamlit のインストール方法

下記のコマンドでインストールします。

pip install streamlit

プログラムの先頭に下記の1行を記述します。

import streamlit as st

Streamlitアプリの実行方法

既に前述しましたが、Streamlit.exe を使ってPythonファイルを実行します。
例えば、sample.py を実行したい場合は コマンドプロンプトから次のコマンドを実行します。

streamlit run sample.py

実行すると、次の2つの画面が表示されます。
もしWebページが表示されない場合、コマンドプロンプトに表示されているURLにアクセスしてください。

Webサーバの起動

Webページの表示

起動したWebサーバは、Control+C で停止させることが可能です。

streamlit.exe には、次のコマンドが使用可能です。

コマンド説明
activateメールアドレスを入力して Streamlit をアクティベート(認証用)
cacheキャッシュの管理(クリアなど)
configStreamlit の設定ファイルを操作(編集・確認)
docsブラウザで公式ドキュメントを表示
hello「Hello World」サンプルアプリを実行
helpコマンドのヘルプ情報を表示(全体のサブコマンド確認に便利)
runPython スクリプトを実行(例:streamlit run app.py
versionバージョン情報を表示(--version と同じ動作)

Webページの作り方

基本構成

最もシンプルなページ構成です。 
set_page_config はWebページに持たせるメタ情報(タイトル、アイコン、レイアウトなど)を設定します。
title はページ上部に表示されるタイトルで、続けて入力やボタンなどのウィジェットと、それがクリックされた時の動作を記述します。
最後に、markdown は任意の場所に置けますが、この例ではボディとフッダを分ける水平線の描画に使っています。
最後に、caption でフッダとして表示したい文字列を出力しています。

import streamlit as st

# ページ設定
st.set_page_config(
    page_title="Webアプリ",
    page_icon="✨",
    layout="centered",
    initial_sidebar_state="auto"
)

# タイトル
st.title("デモ画面")

# テキスト入力
user_input = st.text_input("名前を入力してください")

# ボタン表示
if st.button("入力"):
    if user_input:
        st.success(f"名前:{user_input}")
    else:
        st.warning("エラー✍️")

# 備考(フッター的な位置づけ)
st.markdown("---")
st.caption("Powered by Streamlit • 単一ページデモ")

サイドバー構成

sidebar が標準装備されているため、サイドバーが簡単に実現できます。
sidebar にヘッダ、ラジオボタン、テキスト入力を配置し、ラジオボタンの状態(page変数)で右側の処理を分岐しています。

import streamlit as st

st.set_page_config(layout="wide")  # 横幅広め推奨

# サイドバー(左側に配置されるUI)
with st.sidebar:
    st.header("📂 サイドメニュー")
    page = st.radio("ページ選択", ["ホーム", "設定", "ヘルプ"])
    username = st.text_input("ユーザー名")

# メイン画面
st.title("🖥️ メイン表示領域")

if page == "ホーム":
    st.write(f"ようこそ、{username or 'ゲスト'}さん!")
elif page == "設定":
    st.write("ここは設定ページです")
elif page == "ヘルプ":
    st.write("ヘルプ情報を表示します")

右側(メイン表示領域)の処理量が多い場合は、各処理を関数化(またはクラス化)し、機能ごとに別ファイルへ分割して管理するのが理想的です。
そしてそれらは、必要になったタイミングで import することで、不要なモジュールの読み込みを避け、処理負荷を軽減できます。

逆に、ファイルの先頭でまとめて import すると、使用しないモジュールまでメモリに読み込まれてしまうため、パフォーマンス低下の要因になります

画面遷移

Streamlit ではページ切り替えをサポートしていません。しかし、ページ遷移のような振る舞いはできます。
前述のサイドバー構成を使わず、画面の操作に応じて関数(又はクラス)をimport する方法です。

import streamlit as st

st.set_page_config(layout="wide")  # 横幅広め推奨

page = st.radio("ページ選択", ["ホーム", "設定", "ヘルプ"])
username = st.text_input("ユーザー名")
# メイン画面
st.title("🖥️ メイン表示領域")

if page == "ホーム":
    st.write(f"ようこそ、{username or 'ゲスト'}さん!")
elif page == "設定":
    st.write("ここは設定ページです")
elif page == "ヘルプ":
    st.write("ヘルプ情報を表示します")

ウィジェットを横に並べる

ウィジェットは上から下に配置されますが、columns を使うことで、横並びに配置することも可能です。
columns の中にさらに columns を使うことも可能ですが、入れ子(ネスト)構造が深くなりすぎるとレイアウトが崩れたり、レスポンシブ性に影響することもあるので、視覚的なバランスに注意しましょう。

import streamlit as st

# タイトル
st.title("🎛️ 3カラムのウィジェット配置")

# カラムを3つ並べる
col1, col2, col3 = st.columns(3)

# 各カラムにウィジェット配置
with col1:
    st.subheader("カラム1")
    name = st.text_input("名前を入力")

with col2:
    st.subheader("カラム2")
    agree = st.checkbox("利用規約に同意する")

with col3:
    st.subheader("カラム3")
    submit = st.button("送信")

# 結果表示(オプション)
if submit and agree:
    st.success(f"{name} さん、送信ありがとうございます!🎉")
elif submit and not agree:
    st.warning("利用規約に同意してください ⚠️")

ウィジェットのデザインを変更する

あまり複雑なデザイン変更はできませんが、色を変えたり線種を変える程度であれば、markdownにCSSを記述することで対応できます。この時、引数のunsafe_allow_htmlTrueにしないとCSSが反映されないのでご注意ください。

import streamlit as st

# カスタムCSSの挿入
st.markdown("""
    <style>
    /* ボタンの色変更 */
    div.stButton > button {
        background-color: #4CAF50;
        color: white;
        border-radius: 8px;
    }

    /* テキストボックスの色変更 */
    div[data-baseweb="input"] input {
        background-color: #f0f8ff;
        color: #000080;
        border: 1px solid #1e90ff;
    }
    </style>
    """, unsafe_allow_html=True)

# ウィジェット表示
st.text_input("名前を入力してください")
st.button("送信")

画面への文字列出力(write、markdown、code、latex)

Webページに文字列を表示する方法として write とmarkdown があります。
write は表示内容に応じて自動的に適切な形式で出力してくれる print の様な存在です。

import streamlit as st

st.write("こんにちは、世界!")               # テキスト
st.write(1234)                              # 数値
st.write({"Python": "楽しい", "Streamlit": "便利"})  # 辞書型
st.write([1, 2, 3])                         # リスト
st.write(pd.DataFrame(...))                # データフレーム

一方、markdown は Markdown形式の表記でテキストを整形表示してくれます。見出し、リスト、リンク、画像などに対応し、Webページらしいデザインで出力できます。

st.markdown("# タイトル(H1)")
st.markdown("**太字**や *斜体* の装飾")
st.markdown("- 箇条書き1\n- 箇条書き2")
st.markdown("[リンク](https://streamlit.io)")
st.markdown("![画像](https://www.example.com/image.png)")

Streamlitでは安全性の観点から、HTMLタグは基本的にサニタイズ(危険な要素の除去)されます。ただし、unsafe_allow_html=True を指定すると一部のHTMLタグが有効化され、埋め込みCSSの適用も可能になります。これを利用することで、マークアップ内でレイアウトや装飾をカスタマイズできます。

Streamlitでは、Pythonコードの中で文字列としてCSSを定義して、それを st.markdown() 経由で HTML と一緒に埋め込むことで、アプリの実行時にCSSを動的に生成して適用することができます。

import streamlit as st

# CSSを埋め込む(HTMLと一緒に)
st.markdown("""
    <style>
    .custom-box {
        background-color: #f0f8ff;
        border: 2px solid #4CAF50;
        padding: 20px;
        border-radius: 10px;
        font-family: 'Segoe UI', sans-serif;
        box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
        transition: 0.3s;
    }
    .custom-box:hover {
        border-color: #45a049;
        background-color: #e6ffe6;
    }
    </style>
    
    <div class="custom-box">
        <h3>🌟 カスタムカード</h3>
        <p>これはCSSで装飾されたコンポーネントです。</p>
        <p><strong>ホバーすると色が変わります。</strong></p>
    </div>
""", unsafe_allow_html=True)

code は、Webページ中にソースコード(HTMLやPythonなど)を埋め込む際、キーワードをハイライト表示してくれます。

import streamlit as st

code_snippet = '''
def greet(name):
    return f"Hello, {name}!"
'''

st.code(code_snippet, language='python')

latexは、数学の数式を見栄え良く表示してくれます。

import streamlit as st

st.latex(r"\sqrt{3x-1} + (1+x)^2")

変数の保持方法

Streamlit はイベントが発生するたび、Python スクリプト全体を先頭から再実行する仕組みです。
そのため、通常の変数は再実行のたびに初期化されてしまいます。

しかし Streamlit は、一部のウィジェットに対して st.session_state を自動で使うことで、
ユーザーが入力した値をセッション中に復元できるようにしています。

とはいうものの、value引数を明示指定すると、それが優先されて以前の入力が消えることがあります。特に if 文で表示を分岐したり、外部モジュールの導入で構造が複雑化すると、思った通りに復元されない場合も多いのです。

このように、Streamlit の状態保持は万能ではなく、構造によっては挙動が不安定になるケースもあるため、値を確実に保持する方法として次の2通りが用意されています。

仕組み主な目的特徴
st.session_stateユーザーのセッション中に変数を保持- 画面遷移なしで動的更新可能
- 一時的(ページ更新で消える)
experimental_set_query_params()
experimental_get_query_params()
URLベースで状態を保存・共有- 永続的(URLに残る)
- 外部共有可能

st.session_stateのサンプル

import streamlit as st

# 初期化(最初だけ)
if "name" not in st.session_state:
    st.session_state.name = ""

# 入力フォーム
name = st.text_input("お名前を入力", value=st.session_state.name, key="name")

# ボタンで状態更新
if st.button("保存"):
    st.session_state.name = name

# 表示
st.write("保存された名前:", st.session_state.name)

experimental_set_query_params()/experimental_get_query_params()のサンプル

import streamlit as st

# URLパラメータの取得
params = st.experimental_get_query_params()
page = params.get("page", ["home"])[0]  # デフォルトは "home"

# ボタンでURLパラメータを変更
if st.button("設定ページに移動"):
    st.experimental_set_query_params(page="setting")

# 表示切り替え
if page == "home":
    st.write("🏠 ホームページです")
elif page == "setting":
    st.write("⚙️ 設定ページです")

# 今のURLパラメータを表示
st.write("現在のクエリパラメータ:", params)

主なウィジェット

文字列の入力(text_input/number_input)

入力欄を表示します。

import streamlit as st

name = st.text_input("名前を入力してください")
st.write(f"こんにちは、{name}さん!")

数値だけを受け付ける入力欄も作成可能です。この場合、右端の+-ボタンで、値の増減ができます。

import streamlit as st

age = st.number_input("年齢を入力してください", 
        min_value=0, max_value=120, step=1)
st.write(f"あなたは {age} 歳ですね!")

ON/OFFチェック(checkbox/toggle)

チェックボックスとトグルボタンの2通りが利用可能です。

import streamlit as st

agree = st.checkbox("利用規約に同意する")
if agree:
    st.write("ありがとうございます!")
import streamlit as st

agree = st.toggle("利用規約に同意する")
if agree:
    st.write("ありがとうございます!")

ラジオボタン(radio)

ラジオボタンは、horizontal True にすると横に項目が表示されます。指定しない場合、もしくはFalseにすると項目が縦に並びます。

import streamlit as st

gender = st.radio("性別を選択してください",
            ["男性", "女性", "その他"],
            horizontal=True)
st.write(f"選択された性別: {gender}")

コンボボックス(selectbox)

コンボボックスのテキスト部分は、リスト内の項目を検索・絞り込むためのフィルターとして機能するため、任意の文字列を直接入力して選択値を変更することはできません

import streamlit as st

# コンボボックス(単一選択)
fruit = st.selectbox(
    "好きなフルーツを1つ選んでください:",
    ["りんご", "バナナ", "みかん"],
    index=1  # 初期選択を「バナナ」に
)

第一引数("好きなフルーツを1つ選んでください:")は内部的に必要なので省略できませんが、label_visibilityを "collapsed" にすることで非表示にできます。
また、placeholder で未選択時のメッセージを表示できます。

import streamlit as st

# コンボボックス(単一選択)
fruit = st.selectbox(
    "好きなフルーツを1つ選んでください:",
    ["りんご", "バナナ", "みかん"],
    index=None,
    placeholder="フルーツを選択してください",
    label_visibility="collapsed"
)

リストボックス(nultiselect)

一般的なリストボックスとは違い、コンボボックスのテキスト部に、選択項目が表示されるスタイルです。

import streamlit as st

# リストボックス(複数選択)
colors = st.multiselect(
    "好きな色を選んでください(複数可):",
    ["赤", "青", "緑", "黄色"],
    default=["赤", "青"]  # 初期選択
)

ボタン(button)

ボタンの戻り値は True か False で、Trueの時にボタンを押された時の処理を記述します。

import streamlit as st

if st.button("クリックして挨拶"):
    st.write("こんにちは、Streamlit!")

ボタンには on_clickにコールバック関数が指定できます。これにより、ボタンが押されたことを if 文で判定する必要がなくなります。

import streamlit as st

def say_hello():
    st.write("Hello from callback!")

st.button("挨拶する", on_click=say_hello)

ファイルのダウンロード(download_button)

バイナリデータや文字列をユーザーのローカルに保存できるようにするボタンを生成します
data にダウンロードしたいデータ(文字列 or バイナリ)を指定し、データに応じた MIMEタイプを mimie に指定します。

import pandas as pd
import streamlit as st

df = pd.DataFrame({"名前": ["太郎", "花子"], "年齢": [25, 30]})
csv = df.to_csv(index=False)

st.download_button("CSVをダウンロード", 
        data=csv, file_name="data.csv",
        mime="text/csv")

mime に指定する主なタイプ

CSV(.csv)→ text/csv
ZIP(.zip)→ application/zip
JPEG画像(.jpg / .jpeg)→ image/jpeg
PNG画像(.png)→ image/png
Excel(.xlsx)→ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
MP3音声(.mp3)→ audio/mpeg
MP4動画(.mp4)→ video/mp4

スライダー(slider)

スライダーはスライドを止めた際に値を受け取ることができます。
スライド中の値の変化は受け取れません。

import streamlit as st

volume = st.slider("音量を選択", 0, 100, 50)
st.write(f"音量は {volume} に設定されています")

画面の一括更新(form、submit_button)

これまでに紹介してきたウィジェットは、ユーザーが操作するたびにイベントが発生し、ページが再描画されていました。
そのため、ちょっとした変更でもPythonスクリプトが毎回先頭から実行され、画面全体が更新されてしまう煩わしさがありました。

しかし、st.form() の中に配置されたウィジェットは、個別の操作に対してイベントを発生させません
唯一の例外は st.form_submit_button() で、この送信ボタンが押されたときだけ、フォーム全体の入力をまとめて処理するイベントが発生します。

実際には、エンターキーを押すことで、form_submit_button()が押されたような扱いになります。

この仕組みにより、ページ上のすべての入力が完了したタイミングでのみイベントがトリガーされるため、操作のたびにスクリプトが再実行される煩雑さから解放され、よりスムーズなユーザー体験を実現できます。

import streamlit as st

# フォームの開始
with st.form("profile_form"):
    name = st.text_input("あなたの名前は?")
    age = st.number_input("年齢を教えてください", min_value=0, max_value=120)

    # フォーム送信ボタン(イベントの発生ポイント)
    submitted = st.form_submit_button("送信")

# 送信後の処理
if submitted:
    st.success(f"{name} さんは {age} 歳ですね!")

ファイル選択(file_uploader)

ドラッグ&ドロップに対応したファイル選択が可能です。
accept_multiple_files Trueにすると複数ファイルを同時に選択できます。
ちなみに、"Drag and drop file here" や "Browse files" などの英語表記を日本語にすることはできません

import streamlit as st

uploaded_file = st.file_uploader("ファイルを選択",
                type=["png", "jpg", "pdf"],
                accept_multiple_files=False)
if uploaded_file is not None:
    st.write("ファイル名:", uploaded_file.name)

フォルダ選択(該当なし)

残念ながら、Streamlit ではフォルダ選択のUIを直接提供していません。
これは、Streamlitが「簡単にWebアプリを構築できる」ことを重視している設計ポリシーに基づいています。

Webブラウザを通じてユーザーのローカルフォルダへ直接アクセスすることは、セキュリティリスクが大きく、Web標準の制約にも抵触するため、OS依存のファイルダイアログなどは採用されていません。

また、選択したファイルからローカル上のフルパスが取得できないため、ファイル選択ダイアログで指定されたファイルから、フルパスを取得することもできません。

このため、フォルダ操作が必要な場面では「ファイル単位の複数アップロード」や「パス入力による指定」といった代替手段を取るのが一般的です。

import streamlit as st
import os

folder_path = st.text_input("📁 フォルダパスを入力してください", value="C:/Users/YourName/Documents")

if folder_path and os.path.isdir(folder_path):
    file_list = os.listdir(folder_path)
    st.success(f"{len(file_list)} 件のファイルを検出しました!")
    for f in file_list:
        st.write(f" - {f}")
else:
    st.warning("有効なフォルダパスを入力してください")

DataFrameの表示(dataframe)

width と height で横と縦のドット数が指定できます。指定した範囲を超える場合は、自動的にするロールバーが表示されます。

import streamlit as st
import pandas as pd
import numpy as np

# 横に長いデータを作成
df = pd.DataFrame({
    f"列{i}": [f"データ{i}" for _ in range(100)]
    for i in range(1, 50)  # 50列
})

# サイズ制限付きで表示
st.dataframe(df, width=300, height=200)

DataFrameの編集(data_editor)

DataFrameの内容を画面から編集できます。num_rowsに "dynamic" を指定すると、画面から新規行の対かも可能です。

import streamlit as st
import pandas as pd

# 初期データ
df = pd.DataFrame({
    "名前": ["太郎", "花子"],
    "年齢": [25, 30]
})

# 行追加を可能にする設定
edited_df = st.data_editor(df, 
              num_rows="dynamic")

画像の表示(image)

画像はローカルPC上のフルパス、インターネット上のURLの他、Pillow やOpenCV で読み込んだ画像も表示可能です。また、画像は1枚だけではなく、リスト形式で複数まとめて表示することもできます。

import streamlit as st

st.image(r"P:\sample\dog.png", 
        caption="サンプル画像",
        width=300)
import streamlit as st

st.image([r"P:\sample\dog.png",r"P:\sample\cat.png"], 
         caption=["犬の画像", "猫の画像" ],
         width=300)

imagedataframeを組み合わせることで、簡単にサムネイル表示が可能です。サムネイルをクリックすると、その画像が拡大表示されます。

DataFrameに格納した画像データは、Base64である必要があります。このため、image_to_base64 関数で画像ファイルをBase64に変換しています。

サムネイルに表示する画像サイズは、ImageColumnの設定用辞書の widthで、"small","mediam","large"の中から選択可能ですが、それほど大きく変化しませんので、割り切って使いましょう。

import streamlit as st
import pandas as pd
import base64
import os
from streamlit.column_config import ImageColumn

# 🔧 Base64変換関数
def image_to_base64(path):
    with open(path, "rb") as f:
        data = f.read()
        return "data:image/png;base64," + base64.b64encode(data).decode()

# 📁 画像フォルダのパス(例:P:\sample)
folder_path = r"P:\sample"
image_files = [f for f in os.listdir(folder_path) if f.lower().endswith((".png", ".jpg", ".jpeg"))]

# 📦 DataFrame作成
df = pd.DataFrame({
    "ファイル名": image_files,
    "画像": [image_to_base64(os.path.join(folder_path, f)) for f in image_files]
})

# 🖼️ ImageColumn設定
column_config = {
    "画像": ImageColumn(
        label="サムネイル",
        help="製品画像を表示します",
        width="large"
    )
}

# 📊 表示
st.dataframe(df, column_config=column_config)

グラフ表示

DataFrameに格納されたデータからグラフを簡単に描画できますが、デザインは変更できません。
ただ、matplotlibとは異なりマウスでグラフの拡大/縮小が行えるため、使い勝手は良好です。

import streamlit as st
import pandas as pd

df = pd.DataFrame({
    "日付": pd.date_range("2025-08-01", periods=7),
    "売上": [120, 150, 170, 130, 180, 200, 220],
    "件数": [130, 132, 134, 125, 133, 134, 133]
})

st.line_chart(df.set_index("日付"))

line_chartbar_chartに変更するだけで、棒グラフも描画できます。

import streamlit as st
import pandas as pd

df = pd.DataFrame({
    "日付": pd.date_range("2025-08-01", periods=7),
    "売上": [120, 150, 170, 130, 180, 200, 220],
    "件数": [130, 132, 134, 125, 133, 134, 133]
})

st.bar_chart(df.set_index("日付"))

plotly との連携

pip install plotly

plotly を使うことで、見栄えの良いグラフを作成することができます。

import streamlit as st
import pandas as pd
import plotly.graph_objects as go

# データ準備
df = pd.DataFrame({
    "日付": pd.date_range("2025-08-01", periods=7),
    "売上": [120, 150, 170, 130, 180, 200, 220],
    "件数": [130, 132, 134, 125, 133, 134, 133]
})

# グラフ作成
fig = go.Figure()

# 売上の折れ線
fig.add_trace(go.Scatter(
    x=df["日付"],
    y=df["売上"],
    mode="lines+markers",
    name="売上",
    line=dict(width=4, color="royalblue"),
    marker=dict(size=8, color="lightblue")
))

# 件数の折れ線
fig.add_trace(go.Scatter(
    x=df["日付"],
    y=df["件数"],
    mode="lines+markers",
    name="件数",
    line=dict(width=4, color="orange"),
    marker=dict(size=8, color="gold")
))

# レイアウト調整
fig.update_layout(
    title="日別 売上と件数の推移",
    xaxis_title="日付",
    yaxis_title="値",
    legend_title="項目",
    hovermode="x unified"
)

# 表示
st.plotly_chart(fig, use_container_width=True)
import streamlit as st
import pandas as pd
import plotly.graph_objects as go

# データ準備
df = pd.DataFrame({
    "日付": pd.date_range("2025-08-01", periods=7),
    "売上": [120, 150, 170, 130, 180, 200, 220],
    "件数": [130, 132, 134, 125, 133, 134, 133]
})

# グラフ作成
fig = go.Figure()

# 売上バー
fig.add_trace(go.Bar(
    x=df["日付"],
    y=df["売上"],
    name="売上",
    marker_color="royalblue"
))

# 件数バー(横に並べる)
fig.add_trace(go.Bar(
    x=df["日付"],
    y=df["件数"],
    name="件数",
    marker_color="orange"
))

# レイアウト調整
fig.update_layout(
    barmode="group",  # 横並び(stackなら積み上げ)
    title="日別 売上と件数",
    xaxis_title="日付",
    yaxis_title="値",
    legend_title="項目",
    bargap=0.2
)

# 表示
st.plotly_chart(fig, use_container_width=True)

Uploadの容量制限を緩和する

Cドライブのユーザーフォルダ(環境変数:userprofile で参照可能)の直下にある .streamlit フォルダに移動します。

c:
cd %userprofile%.streamlit\config.toml

config.toml という名前で下記の要領で最大アップロードサイズを指定し、保存します(下記の例では5GB)。

[server]
maxUploadSize = 5120 # MB単位

Webページをリロードすると、変更内容がすぐに反映されます。
ただし、アップロード可能なファイルサイズは、PCのメモリ搭載量や Python の実行環境に依存します。
そのため、設定値どおりにアップロードできるとは限らない点にご注意ください。

まとめ

本記事では、Pythonだけで手軽にWebアプリを構築できる「Streamlit」について、基本的な使い方から注意点、便利なウィジェットの活用例までを一通り解説しました。

CustomTkinterなどのデスクトップGUIツールと比べ、StreamlitはHTMLやJavaScriptの知識が不要で、数行のPythonコードからインタラクティブなWebアプリが作れるという大きな利点があります。
一方で、「フォルダ選択ができない」「スクリプトが毎回再実行される」「状態保持に工夫が必要」などの制約もあるため、用途に応じて適切に選択することが大切です。

特に、テーブル形式のデータ表示・編集やグラフ描画、画像の一覧表示といった処理には非常に相性が良く、データ分析や社内ツール開発などで大いに力を発揮します。

初めてUI開発に挑戦する方、あるいはTkinterの限界に悩んでいた方は、この機会にぜひStreamlitを試してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次