LoginSignup
2
7

More than 1 year has passed since last update.

Flet - アイコンブラウザの改良

Last updated at Posted at 2023-02-02

はじめに

Fletの公式サイトにアイコン検索ができるサイトがあるのですが、いつの間にか使えなくなっていました。(2/2現在)
恐らくメモリ不足になっているのではないかと思います。
サイト:https://flet-icons-browser.fly.dev/#/

そこで、公開されているソースをもとに少し改良したものを作ってみたので、その内容をまとめておきます。
公式のソース:https://github.com/flet-dev/examples/tree/main/python/apps/icons-browser

ちなみにアイコンの検索は↓できます。(たぶんFlutter用を探せば使える)
https://fonts.google.com/icons?selected=Material+Icons&icon.platform=flutter&icon.set=Material+Icons

2023/2/4 に公式サイトの変更があったようです。
いまはアイコン検索のURLが↓になっていて動きます。
https://flet-icons-browser.pages.dev/

作ったもの

作ったアイコンブラウザはこちら。良ければ試してみてください。

image.png

改良ポイント

  • googleを参考に4分類して検索するようにした
    • 確かに4種類を一緒に出す必要もないと思うのでそうした
    • これにより、全アイコン表示しても2千ほどになって軽くなった
    • fly.ioでメモリ不足にもならなくなった
  • DARKモードの表示も見れるようにSwitchを追加した
    • page.theme_modeを変えてるだけ
  • 検索文字列なしの時は全部のアイコンを表示するようにした
    • サンプルだとこれができなかった
    • 目視になるけど全体を見れるのは個人的には必要

経緯まとめ

  • 公式サイトのアイコンブラウザを使おうとしたら使えなかった(応答がない状況)
  • しょうがないので、公開されているソースをローカルで動かしてみる
  • なんか使い勝手がいまいちなので改良してみることに
  • サンプルソースがyieldを使ってややこしいつくりになっているのを確認
  • 全部のアイコンが見れないのが嫌だったのでその辺を変更
  • アイコンを大量に表示すると結構遅いけどローカルでは動くのを確認
  • fly.ioにアップしたらメモリ不足で動かないことを確認(サンプルでyieldを使っているのはこのためか?)
  • 中身はFlutterなので、Flutterのアイコンを検索
  • これを発見 https://fonts.google.com/icons?selected=Material+Icons&icon.platform=flutter&icon.set=Material+Icons
  • ↑を参考にさらに改良
  • 改良によってfly.ioでも動くようになった

ソース

ソースはこちら。
150行程度でここまでできるのは楽だと思います。

import flet as ft


class IconBrowser(ft.UserControl):
    def __init__(self, expand=False, height=500):
        super().__init__()
        if expand:
            self.expand = expand
        else:
            self.height = height

    def build(self):

        def copy_to_clipboard(e):
            icon_key = e.control.data
            print("Copy to clipboard:", icon_key)
            self.page.set_clipboard(e.control.data)
            self.page.show_snack_bar(
                ft.SnackBar(ft.Text(f"Copied {icon_key}"), open=True))

        def search_icons(type: str, search_term: str):
            if self.page != None:
                search_results.clean()

            count = 0
            for icon_name in icons_list:
                icon_key = f"icons.{icon_name.upper()}"
                if type == "" \
                    and ("OUTLINED" in icon_key or
                         "ROUNDED" in icon_key or
                         "SHARP" in icon_key):
                    # Filledは↑の文字列を含む場合はスキップ
                    continue
                elif type not in icon_key:
                    # タイプの文字列を含まない場合はスキップ
                    continue
                if search_term.upper() not in icon_key:
                    # 入力値を含まない場合はスキップ
                    continue

                search_results.controls.append(
                    ft.TextButton(
                        content=ft.Container(ft.Column(
                            [
                                ft.Icon(name=icon_name),
                                ft.Text(
                                    value=f"{icon_name}",
                                    size=12,
                                    width=120,
                                    no_wrap=True,
                                    text_align="center",
                                    color=ft.colors.ON_SURFACE_VARIANT,
                                ),
                            ],
                            spacing=0,
                            alignment="center",
                            horizontal_alignment="center",
                        ),
                            alignment=ft.alignment.center,
                        ),
                        tooltip=f"{icon_key}\nClick to copy to a clipboard",
                        on_click=copy_to_clipboard,
                        data=icon_key,
                    )
                )
                count += 1

            if self.page != None:
                message = f"{count} icons found"
                if count == 0:
                    message = "No icons found"
                self.page.show_snack_bar(
                    ft.SnackBar(ft.Text(message), open=True))
                self.update()

        def change_theme_mode(e: ft.UserControl):
            value = e.control.value
            if value:
                self.page.theme_mode = ft.ThemeMode.DARK
            else:
                self.page.theme_mode = ft.ThemeMode.LIGHT
            self.page.update()

        # fetch all icon constants from icons.py module
        icons_list = []
        list_started = False
        for key, value in vars(ft.icons).items():
            if key == "TEN_K":
                list_started = True
            if list_started:
                icons_list.append(value)

        # I/O Controls
        search_txt = ft.TextField(
            expand=1,
            hint_text="Enter keyword and press search button",
            autofocus=True,
            on_submit=lambda _: search_icons(
                select_type_group.value, search_txt.value),
        )
        search_query = ft.Row([
            search_txt,
            ft.IconButton(icon=ft.icons.SEARCH,
                          on_click=lambda _: search_icons(
                              select_type_group.value, search_txt.value))
        ])
        select_type_group = ft.RadioGroup(
            ft.Row([
                ft.Radio(label="Outlined", value="OUTLINED"),
                ft.Radio(label="Filled", value=""),
                ft.Radio(label="Rounded", value="ROUNDED"),
                ft.Radio(label="Sharp", value="SHARP"),
            ]),
            value="OUTLINED",
            on_change=lambda _: search_icons(
                select_type_group.value, search_txt.value),
        )
        select_type = ft.Row([
            select_type_group
        ])
        select_theme_mode = ft.Row([
            ft.Switch(
                label="DARK",
                on_change=change_theme_mode
            )
        ])
        search_results = ft.GridView(
            expand=1,
            runs_count=10,
            max_extent=120,
            run_spacing=0,
            child_aspect_ratio=1,
        )
        status_bar = ft.Text()

        search_icons(select_type_group.value, search_txt.value)

        return ft.Column(
            [
                search_query,
                select_type,
                select_theme_mode,
                search_results,
                status_bar,
            ],
            expand=True,
        )


def main(page: ft.Page):
    page.theme_mode = ft.ThemeMode.LIGHT
    page.title = "My Flet icons browser"
    page.add(IconBrowser(expand=True))


ft.flet.app(target=main)
2
7
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
2
7