9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#NervesJPAdvent Calendar 2023

Day 22

ElixirでGUI・Scenic [新・入門編]

Posted at

1.はじめに

ElixirのGUIライブラリ「Scenic」を使って、簡単なウィンドウアプリを作ってみます。

scenicのバージョンが0.10系から0.11系になり、過去に記述した記事がそのままではビルドできなくなりました。

本記事では、2023年時点で最新のVer.0.11系でビルドする手順を示します。

実行環境

下記の環境で試しています。

OS Ubuntu Linux 22.04 LTS
Elixir Ver.1.15.5
ターミナル
$ uname -a
Linux hostname 6.2.0-37-generic #38~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov  2 18:01:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"

$ elixir -v
Erlang/OTP 25 [erts-13.2.2.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Elixir 1.15.5 (compiled with Erlang/OTP 25)

2.インストール

Elixirのインストールは下記を参照願います。

Scenicのインストールは下記を参考に進めます。

Scenicのビルドに必要なライブラリをインストールします。

ターミナル
$ sudo apt install libglfw3 libglfw3-dev libglew-dev -y

scenicライブラリをインストールします。

ターミナル
$ mix archive.install hex scenic_new

3.まずは"Hello World"を試す

ひな形のプロジェクトを作成して、とりあえず実行します。

ターミナル
$ cd (ご自身のワーキングディレクトリに移動)

# scenicプロジェクトを作成
$ mix scenic.new hmihello

#プロジェクトのディレクトリに移動
$ cd hmihello

# 必要なライブラリを取得
$ mix deps.get

# 実行
$ mix scenic.run
#(`iex -S mix`でもOK)

[Ctrl-C]の押下か、ウィンドウの閉じるボタンで終了できます。

image.png

4.テキストと図形を表示

hmihello/lib/scenes/home.ex
(・・・省略・・・)
  # ============================================================================
  # setup

  # --------------------------------------------------------
  def init(scene, _param, _opts) do
    # get the width and height of the viewport. This is to demonstrate creating
    # a transparent full-screen rectangle to catch user input
    {width, height} = scene.viewport.size

    # show the version of scenic and the glfw driver
    scenic_ver = Application.spec(:scenic, :vsn) |> to_string()
    driver_ver = Application.spec(:scenic_driver_local, :vsn) |> to_string()

    info = "scenic: v#{scenic_ver}\nscenic_driver_local: v#{driver_ver}"

    graph =
      Graph.build(font: :roboto, font_size: @text_size)
      |> add_specs_to_graph([
        # この4行をコメントアウト
        # text_spec(info, translate: {20, 40}),
        # text_spec(@note, translate: {20, 120}),
        # rect_spec({width, height})

        # ここから追記
        # テキスト
        text_spec("Hello World", t: {40, 40}),
        # 図形・丸
        #          直径 描画位置     塗りつぶし    輪郭
        circle_spec(10, t: {20, 30}, fill: :blue, stroke: {2, :white}),
        circle_spec(10, t: {220, 30}, fill: :yellow, stroke: {2, :red}),
        # 図形・直線
        #          対角左上 対角右下             太さ 色     先端形状
        line_spec({{10, 50}, {250, 50}}, stroke: {4, :cyan}, cap: :round)
      ])

    scene = push_graph(scene, graph)

    {:ok, scene}
  end
(・・・省略・・・)

書き換えたら、ビルド・実行します。

ターミナル
$ mix scenic.run

文字と、2つの丸、直線の図形が描画できました。

image.png

5.押しボタンの入力イベントでテキストと図形を書き換え

まずは描画内容を作ります

hmihello/lib/scenes/home.ex
defmodule Hmihello.Scene.Home do
  use Scenic.Scene
  require Logger

  alias Scenic.Graph

  import Scenic.Primitives
  import Scenic.Components          # ←ここのコメントアウトを外します

  # ↓ここは参照しないので、コメントアウトします
  # @note """
  #   This is a very simple starter application.

  #   If you want a more full-on example, please start from:

  #   mix scenic.new.example
  # """

  @text_size 24

  # ↓ウィンドウに描画する内容は、この関数にまとめます
  defp graph_build() do
    Graph.build(font: :roboto, font_size: @text_size)
    |> add_specs_to_graph(
      [
        # テキスト
        text_spec("Hello World", t: {40, 40}),
        # 図形・丸
        circle_spec(10, fill: :blue, stroke: {2, :white}, t: {20, 30}),
        circle_spec(10, fill: :yellow, stroke: {2, :red}, t: {220, 30}),
        # 図形・直線
        line_spec({{10, 50}, {250, 50}}, stroke: {4, :cyan}, cap: :round),
        # 押しボタン
        button_spec("ON", id: :btn_on, t: {40, 90}, theme: :success),
        button_spec("OFF", id: :btn_off, t: {120, 90}, theme: :danger),
        # テキスト・ON/OFF表示
        text_spec("---", t: {80, 80}, id: :event_text),
        # 図形・ランプ・ON/OFF表示
        circle_spec(10, id: :event_circle, fill: :grey, stroke: {2, :white}, t: {60, 70})
      ],
      # 全体の描画位置をオフセットする
      translate: {10, 10}
    )
  end

  # ============================================================================
  # setup

  # --------------------------------------------------------
  # ↓ここの関数はまるっと書き換えて、2行だけの内容にします
  def init(scene, _param, _opts) do
    scene = push_graph(scene, graph_build())
    {:ok, scene}
  end

  # ***あとでここに関数を書き足します***

  # ↓ここは変更なしです
  def handle_input(event, _context, scene) do
    Logger.info("Received event: #{inspect(event)}")
    {:noreply, scene}
  end
end

書き換えたら、ビルド・実行します。

ターミナル
$ mix scenic.run

先ほどの描画内容に対し、さらにON・OFFボタンと灰色のランプ、テキスト---が描画できました。

image.png

この時点では、ボタンイベントの処理を書いていないので、ボタンをクリックしても変化はありません。

続いて、イベント処理を追加します。

先ほどのコード中に # ***あとでここに関数を書き足します***と書かれた箇所に、関数を2つ追記します。

hmihello/lib/scenes/home.ex
(・・・省略・・・)

  def handle_event(event, _context, scene) do
    Logger.debug("Received handle_event: #{inspect(event)}")

    graph =
      case event do
        {:click, id} ->
          # 押しボタンのクリックイベントでマッチさせる
          graph_build()
          # 押しボタンの動作による画面更新処理に渡す
          |> on_click_button(id)

        _ ->
          # それ以外のときは書き換えなし
          graph_build()
      end

    # 描画内容を更新する
    scene =
      scene
      |> push_graph(graph)

    {:noreply, scene}
  end

  def on_click_button(graph, id) do
    case id do
      # 押しボタン・ONが押された
      :btn_on ->
        graph
        # テキストの表記を書き換え
        |> Graph.modify(:event_text, &text(&1, "ON"))
        # ランプの色を置き換え
        |> Graph.modify(:event_circle, &update_opts(&1, fill: :lawn_green))

      # 押しボタン・OFFが押された
      :btn_off ->
        graph
        |> Graph.modify(:event_text, &text(&1, "OFF"))
        |> Graph.modify(:event_circle, &update_opts(&1, fill: :grey))

      _ ->
        # それ以外のときは書き換えなし
        raise "not implimentation"
    end
  end

(・・・省略・・・)

書き換えたら、ビルド・実行します。

ターミナル
$ mix scenic.run

image.png

押しボタンのON・OFFを押下するごとに、テキストとランプが書き換わります。

6.まとめ

Ver.0.10系とVer.0.11系における変更点の気づきです。

  • マウスのカーソル移動、キーボードのキー入力単体のイベントが取れなくなった
  • push_graph関数で画面の更新をするようになった
  • (ほか、調査中)
9
2
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
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?