4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flet】ヘッダ表示固定の簡易DataTableを作ってみました

Last updated at Posted at 2024-06-28

概要

FletのDataTableですが、表をスクロールするとヘッダもスクロールされて見えなくなってしまいます。
これを改善するために、ヘッダ表示固定の簡易DataTableを作ってみました。

解決したいこと

Flet標準のDataTableは、ヘッダごとスクロールされます。
ヘッダが見えなくなっちゃうので、ヘッダが固定されたデータ表を作りたい。

↓Flet標準のDataTable
datatable.gif

ヘッダ固定のデータ表を作ってみました

イメージ図は以下になります。

FixedHeaderDataTableクラスは、Columnコントロールを継承しています。
その中でヘッダ部分とスクロール可能なデータ部を配置しています。
そのFixedHeaderDataTableクラスをPageへ配置しています。

名称未設定ファイル.drawio.png

コード
import flet as ft

# 簡易DataTableのクラス、Columnコントロールを継承
class FixedHeaderDataTable(ft.Column):

    def __init__(self, headers, rows, column_widths):
        super().__init__()
        self.headers = headers
        self.rows = rows
        self.column_widths = column_widths
        self.expand = True  # ページに対して自動伸縮

        # ヘッダ部の作成
        header_controls = [
            ft.Container(ft.Text(header, weight=ft.FontWeight.BOLD), width=width, alignment=ft.alignment.center, bgcolor=ft.colors.GREY_200) \
                for header, width in zip(self.headers, self.column_widths)
        ]
        header_row = ft.Row(header_controls, alignment=ft.alignment.center, height=50)

        # データ部の作成
        row_controls = []
        for row in self.rows:
            row_cells = [
                ft.Container(ft.Text(cell), width=width, alignment=ft.alignment.center) \
                    for cell, width in zip(row, self.column_widths)
            ]
            row_controls.append(ft.Row(row_cells, alignment=ft.alignment.center))
        # スクロールできるようにColumnコントロールを用意
        scrollable_data = ft.Column(
            controls=row_controls,
            scroll=ft.ScrollMode.ALWAYS,
            expand=True  # 親のColumn内で自動伸縮
        )

        # ヘッダ部とデータ部を配置
        self.controls =[
            header_row,
            scrollable_data
        ]
        

def main(page: ft.Page):
    page.title = "固定行のデータ表"
    page.window_top = 100
    page.window_left = 200
    page.window_width = 1000
    page.window_height = 600

    # ヘッダのリストを用意
    headers = ["名前","射程","サブ","スペシャル","SPポイント"]
    # 列幅のリストを用意
    column_widths = [200, 100, 200, 200, 100]
    # データ部で表示したい2次元配列を用意
    rows = [
        ["ボールドマーカー","1.6","カーリングボム","ウルトラハンコ","180"],
        ["ボールドマーカーネオ","1.6","ジャンプビーコン","メガホンレーザー5.1ch","170"],
        # 更に行を追加
    ]

    # 簡易DataTableを生成しページへ配置、ヘッダ/列幅/データのリストを渡します
    data_table = FixedHeaderDataTable(headers, rows, column_widths)
    page.add(data_table)

# アプリ開始
ft.app(target=main)

完成形

データ部分だけスクロールされるデータ表が完成しました。
datatable.gif

テストデータは以下を整形しました。https://wikiwiki.jp/splatoon3mix/%E3%83%96%E3%82%AD/%E3%82%B7%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%BC%E5%B1%9E

課題

  • 列幅が事前指定となっている(DataTableは文字内容で幅が動的に変わる)
  • 並び替えに対応できていない
  • ヘッダ/列幅/データの列数があっていないなどのエラーハンドリングができていない
    などなど

まとめ

色々物足りない部分は多いですが、Fletコントロールのクラスとレイアウトの基本が学べました。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?