【C#】【ピクロス】【ALTSEED】サイズ変更ダイアログのUIを作成

前回までの状況はこちら。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

サイズ変更ダイアログにラベルとテキストボックスを追加します。

これらは新規クラスですね。

なので、ラベルクラスとテキストボックスクラスを作成します。

class Label : ObjectBase
{
    private string _text;
    private int fontOffsetX = 9;
    private int fontOffsetY = 4;
    private bool _isShow = false;

    public Label(int x, int y, string text)
    {
        width = 128;
        height = 32;
        _x = x;
        _y = y;
        _text = text;

        _valueText = new asd.TextObject2D();
        _valueText.Text = _text;
        _valueText.Font = null;
        _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
    }

    public void SetFontOffset(int x, int y)
    {
        fontOffsetX = x;
        fontOffsetY = y;
        _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
    }

    public void Show()
    {
        _isShow = true;
        _valueText.Font = Resource.getFont();
    }

    public void Hide()
    {
        _isShow = false; ;
        _valueText.Font = null;
    }
}
class TextBox : ObjectBase
{
    private string _text;
    private int fontOffsetX = 9;
    private int fontOffsetY = 4;
    protected bool enable = true;
    private Action _action = null;
    private bool _isShow = false;

    public TextBox(int x, int y, string text)
    {
        width = 128;
        height = 32;
        _x = x;
        _y = y;
        _text = text;

        _backTexture = new asd.TextureObject2D();
        _backTexture.Position = new asd.Vector2DF(_x, _y);

        _valueText = new asd.TextObject2D();
        _valueText.Text = _text;
        _valueText.Font = null;
        _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
    }

    public void SetFontOffset(int x, int y)
    {
        fontOffsetX = x;
        fontOffsetY = y;
        _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
    }

    public void UpdateTexture(asd.Vector2DF pos)
    {
        if (pos.X > _x && pos.X < _x + width
            && pos.Y > _y && pos.Y < _y + height)
        {
            _backTexture.Texture = Resource.getSelectedTextTexture();
        }
        else
        {
            _backTexture.Texture = Resource.getTextTexture();
        }
    }

    public void Show()
    {
        _isShow = true;
        _backTexture.Texture = Resource.getTextTexture();
        _valueText.Font = Resource.getFont();
    }

    public void Hide()
    {
        _isShow = false; ;
        _backTexture.Texture = null;
        _valueText.Font = null;
    }

    public void SetAction(Action action)
    {
        _action = action;
    }

    public void SetEnable(bool enable)
    {
        this.enable = enable;
    }

    public virtual void OnClick()
    {
        if (enable)
        {
            if (_action != null)
            {
                _action.Invoke();
            }
        }
    }
}

OnClick処理は後々修正するかもしれない。

そして、ほとんどはButtonクラスのアレンジ。

これをDialogクラスで使用します。

class Dialog
{
    private asd.TextureObject2D _texture;
    private bool _isShow;
    private Button _button = null;
    private TextBox _rowText = null;
    private TextBox _colText = null;
    private Label _label1 = null;
    private Label _label2 = null;
    private int _x = 300;
    private int _y = 300;
    private int _width = 400;
    private int _height = 200;
    private Action _action = null;

    public Dialog()
    {
        _isShow = false;

        // 確定ボタン
        _button = new Button(436, 400, "確定");
        _button.SetFontOffset(46, 4);
        _button.SetAction(() =>
        {
            if(_action != null)
            {
                _action.Invoke();
            }
        });
        // ラベル
        _label1 = new Label(320, 330, "↓");
        _label2 = new Label(490, 330, "→");
        // Row入力エリア
        _rowText = new TextBox(350, 330, "0");
        // Col入力エリア
        _colText = new TextBox(520, 330, "0");

        _texture = new asd.TextureObject2D();
        _texture.Position = new asd.Vector2DF(_x, _y);
    }

    public void SetEngine()
    {
        asd.Engine.AddObject2D(_texture);
        asd.Engine.AddObject2D(_label1.getTextObject());
        asd.Engine.AddObject2D(_label2.getTextObject());
        asd.Engine.AddObject2D(_rowText.getBackTexture());
        asd.Engine.AddObject2D(_rowText.getTextObject());
        asd.Engine.AddObject2D(_colText.getBackTexture());
        asd.Engine.AddObject2D(_colText.getTextObject());
        asd.Engine.AddObject2D(_button.getBackTexture());
        asd.Engine.AddObject2D(_button.getTextObject());
    }

    public void SetAction(Action action)
    {
        _action = action;
    }

    public void Show()
    {
        _isShow = true;
        _texture.Texture = Resource.getDialogTexture();
        _label1.Show();
        _label2.Show();
        _rowText.Show();
        _colText.Show();
        _button.Show();
    }

    public void Hide()
    {
        _isShow = false;
        _texture.Texture = null;
        _label1.Hide();
        _label2.Hide();
        _rowText.Hide();
        _colText.Hide();
        _button.Hide();
    }

    public bool IsShow()
    {
        return _isShow;
    }

    public void UpdateTexture(asd.Vector2DF pos)
    {
        _rowText.UpdateTexture(pos);
        _colText.UpdateTexture(pos);
        _button.UpdateTexture(pos);
    }

UI自分で作るのってめんどくさいね。

こんなのもう二度とやらない。

首コリ改善が社会復帰のカギとなるかも

整体に行く度に首コリが気になってしまうので、

首コリ改善のためにネックマッサージャーという物を購入しました。

これが効果テキメンで、

首を温熱で温めると同時に、EMSで首の筋肉にも刺激を与えてくれて、

これまでは午後になると脳みそ機能不全になるのですが、

ここ最近は午後になっても脳みそが機能しています。

そのおかげで午後以降もパソコン作業できるようになりました。

少しずつパソコン作業時間を増やしていって、そのうちフルタイム(午後6時まで)稼働できれば、社会復帰も可能になるかもしれません。

しかし、残念なことに。

水没で壊れた。

保証書無い。

安い買い物では無い事と知りつつ、今後頑張れるかどうかの重要アイテムとみているので、速攻再購入。

ああ、早く届かないだろうか。

【ラズパイ】温度計などを使用してみる

最新ソースを置きました(gitHub)。

https://github.com/takishita2nd/pi

下段の左から温度、気圧、湿度です。

温度が38℃と灼熱になっていますが、

うちわで扇いだら33℃下がりました。

ラズパイ本体が熱くなっているんでしょう。

温度計の説明はこちらにあります。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/sensors/temperature.md

英語だよ。

単位は℃で、-40℃~120℃まで計れるみたいです。

温度でLEDの色を変えるとかやってみようかな。

【C#】【ピクロス】【ALTSEED】サイズ変更ダイアログを大幅に修正

前回までの状況はこちら。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

ダイアログ処理を大幅に修正しました。

具体的には、ボタン押下処理をラムダ式で与える、という形にしました。

    class Button : ObjectBase
    {
        private Action _action = null;

        public void SetAction(Action action)
        {
            _action = action;
        }

        public virtual void OnClick()
        {
            if(_action != null)
            {
                _action.Invoke();
            }
        }
        sizeButton.SetAction(() => {
            dialog.Show();
        });

ダイアログも同じように、

    class Dialog
    {
        private Action _action = null;

        public Dialog()
        {
            _isShow = false;
            _button = new Button(436, 450, "確定");
            _button.SetFontOffset(46, 4);
            _button.SetAction(() =>
            {
                if(_action != null)
                {
                    _action.Invoke();
                }
            });

            _texture = new asd.TextureObject2D();
            _texture.Position = new asd.Vector2DF(_x, _y);
        }

        public void SetAction(Action action)
        {
            _action = action;
        }

        public void OnClick(asd.Vector2DF pos)
        {
            if (_button.isClick(pos))
            {
                _button.OnClick();
            }
        }
            Dialog dialog = new Dialog();
            dialog.SetEngine();
            dialog.SetAction(() =>
            {
                dialog.Hide();
            });

特にUI周りは、オブジェクトが持つデータの引き渡しをどうするか、で頭を悩ませてしまいます。

こういうときは、慣れないと見た目複雑に見えてしまいますが、慣れればラムダ式にしてしまった方が、返ってコードがスッキリするんです。

実際、こうすることで、クラスの数を削減できました。

ボタン押下時の処理もラムダ式にすることで、実際の処理は作成元で定義すれば良いので、Buttonクラス一個で済んでしまいます。

UI周り自作するって予想以上に難しいね。

この調子でどんどん作ってきましょう。

【ラズパイ】ジャイロセンサーを使ってみる その2

その1はこちら

というか、print()で出力させても良く見えないので、TKライブラリを使って表示させてみました。

from tkinter import *
from tkinter import ttk
from sense_hat import SenseHat
import threading

sense = SenseHat()

root = Tk()
frame1 = ttk.Frame(root)
frame1.grid()

label1 = ttk.Label(frame1, text='pitch', width=10)
label1.grid(row=1, column=1)

label_pitch = ttk.Label(frame1, width=10)
label_pitch.grid(row=1, column=2)

label2 = ttk.Label(frame1, text='yaw', width=10)
label2.grid(row=1, column=3)

label_yaw = ttk.Label(frame1, width=10)
label_yaw.grid(row=1, column=4)

label3 = ttk.Label(frame1, text='roll', width=10)
label3.grid(row=1, column=5)

label_roll = ttk.Label(frame1, width=10)
label_roll.grid(row=1, column=6)

def scheduler():
    t = threading.Timer(0.1, scheduler)
    t.start()
    orientation_data = sense.get_orientation()
    label_pitch.configure(text=f'{orientation_data["pitch"]:.4f}')
    label_yaw.configure(text=f'{orientation_data["yaw"]:.4f}')
    label_roll.configure(text=f'{orientation_data["roll"]:.4f}')

t = threading.Thread(target = scheduler)
t.start()

root.mainloop()

【C#】【ピクロス】【ALTSEED】サイズ変更ダイアログを表示する

前回までの状況はこちら。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

ダイアログを表示するところまで行きたいのですが、

まず、ダイアログを表示するボタンを作成しなくちゃいけないので、

    class Button : ObjectBase
    {
        private string _text;
        private const int fontOffsetX = 9;
        private const int fontOffsetY = 4;
        protected bool enable = true;

        public Button(int x, int y, string text)
        {
            width = 256;
            height = 64;
            _x = x;
            _y = y;
            _text = text;

            _backTexture = new asd.TextureObject2D();
            _backTexture.Position = new asd.Vector2DF(_x, _y);

            _valueText = new asd.TextObject2D();
            _valueText.Text = _text;
            _valueText.Font = Resource.getFont();
            _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
        }

        public void updateTexture(asd.Vector2DF pos)
        {
            if (pos.X > _x && pos.X < _x + width
                && pos.Y > _y && pos.Y < _y + height)
            {
                _backTexture.Texture = Resource.getButtonTexture();
            }
            else
            {
                _backTexture.Texture = null;
            }
        }

        public void setEnable(bool enable)
        {
            this.enable = enable;
        }

        public virtual void onClick()
        {
            throw new NotImplementedException();
        }
    }

Buttonクラスを作成。ほぼほぼ数独解析ツールのコードをコピーしました。

座標とかサイズは微調整していますが。

これを継承してサイズ変更ボタンを作成。

class SizeButton : Button
{
    public SizeButton() : base(10, 10, "サイズ変更")
    {

    }

    public override void onClick()
    {
        Dialog dialog = Controll.GetDialog();
        dialog.Show();
    }
}
class Controll
{
    private static Dialog _dialog = null;

    public static Dialog GetDialog()
    {
        if(_dialog == null)
        {
            _dialog = new Dialog();
            _dialog.SetEngine();
        }
        return _dialog;
    }
}

各種コントロールもシングルトン形式にすれば、アクセスが簡単になるかと思って。

class Dialog
{
    private asd.TextureObject2D _texture;

    public Dialog()
    {
        _texture = new asd.TextureObject2D();
        _texture.Position = new asd.Vector2DF(300, 300);
    }

    public void SetEngine()
    {
        asd.Engine.AddObject2D(_texture);
    }

    public void Show()
    {
        _texture.Texture = Resource.getDialogTexture();
    }

    public void Hide()
    {
        _texture.Texture = null;
    }
class PicrossUI
{
    public void Run()
    {
        asd.Engine.Initialize("ピクロス解析ツール", 1000, 800, new asd.EngineOption());

        List<Button> buttons = new List<Button>();
        var sizeButton = new SizeButton();
        asd.Engine.AddObject2D(sizeButton.getBackTexture());
        asd.Engine.AddObject2D(sizeButton.getTextObject());
        buttons.Add(sizeButton);

        while (asd.Engine.DoEvents())
        {
            asd.Vector2DF pos = asd.Engine.Mouse.Position;
            foreach (Button button in buttons)
            {
                button.updateTexture(pos);
            }

            if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
            {
                foreach (Button button in buttons)
                {
                    if (button.isClick(pos))
                    {
                        button.onClick();
                    }
                }
            }
            asd.Engine.Update();
        }
        asd.Engine.Terminate();
    }
}

ダイアログ表示とか、ボタン押下時の処理とか、本来ウインドウシステムがやっていることを、全て自前でやらなくちゃ行けないので、ちょっと面倒な事になっています。

頭がごっちゃになりそう。

デリゲートとか上手に使うと上手くいきそうな気もするんですが。

もうちょっと考えてみます。

【ラズパイ】ジャイロセンサーを使ってみる その1

このサンプルを参考にプログラムを与えてみます。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/files/SenseHAT-Cheatsheet.pdf

from sense_hat import SenseHat
sense = SenseHat()
while True:
    orientation_data = sense.get_orientation()
    pitch = orientation_data['pitch']
    yaw = orientation_data['yaw']
    roll = orientation_data['roll']
    print(f'{pitch:.4f} {yaw:.4f} {roll:.4f}')

get_orientation()を使うと、本体の傾きを得ることができます。

pitch,yaw,rollとはなんぞや?なんですが、この絵に説明が描いてありました。

https://projects.raspberrypi.org/en/projects/getting-started-with-the-sense-hat/8

水平、北向きを0度として、傾いた方向の角度が出力されます。

本体アッツ!

【C#】【ピクロス】【ALTSEED】絵を描画するエリアを作成する

前回までの状況はこちら。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

今回は、前回のソースコードを元に、クラス構成を変えて作り直していきます。

まずはリソースを管理するクラス。

class Resource
{
    private static asd.Texture2D _picrossTexture = null;
    public static asd.Texture2D GetPicrossTexture()
    {
        if (_picrossTexture == null)
        {
            _picrossTexture = asd.Engine.Graphics.CreateTexture2D("square.png");
        }
        return _picrossTexture;
    }
}

数独の時と同じです。

画像などの外部リソースは、読み込んだ一個のオブジェクトをみんなで使い回すような仕組みにしています。

こうすることで、外部リソース読み込み速度が向上し、使用メモリも少なくなります。

シングルトンに近いイメージですね。

絵を構成するオブジェクトのベース部分を作成します。

class ObjectBase
{
    protected int _x;
    protected int _y;
    protected asd.TextureObject2D _backTexture;
    protected asd.TextObject2D _valueText;
    protected int width;
    protected int height;

    public asd.TextureObject2D getBackTexture()
    {
        return _backTexture;
    }

    public asd.TextObject2D getTextObject()
    {
        return _valueText;
    }

    public bool isClick(asd.Vector2DF pos)
    {
        if (pos.X > _x && pos.X < _x + width
            && pos.Y > _y && pos.Y < _y + height)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

これは、数独のObjectBaseクラスと全く同じです。

これをベースにして、絵を書く部分と、数字を入力する部分とで、クラスを派生させて行きます。

絵を書く部分は以下の様に派生させました。

class DrawSquare : ObjectBase
{
    protected int _row;
    protected int _col;
    protected const int setPositionX = 200;
    protected const int setPositionY = 200;

    public DrawSquare(int row, int col)
    {
        width = 32;
        height = 32;
        _row = row;
        _col = col;
        _x = col * width + setPositionX;
        _y = row * height + setPositionY;

        _backTexture = new asd.TextureObject2D();
        _backTexture.Texture = Resource.GetPicrossTexture();
        _backTexture.Position = new asd.Vector2DF(_x, _y);
    }
}

これを使用して実装します。

class PicrossUI
{
    private List<List<DrawSquare>> drawSquares = new List<List<DrawSquare>>();

    public PicrossUI()
    {

    }

    public void Run()
    {
        asd.Engine.Initialize("ピクロス解析ツール", 1000, 800, new asd.EngineOption());

        // 下地
        var background = new asd.GeometryObject2D();
        asd.Engine.AddObject2D(background);
        var bgRect = new asd.RectangleShape();
        bgRect.DrawingArea = new asd.RectF(0, 0, 1000, 800);
        background.Shape = bgRect;

        for(int row = 0; row <10; row++)
        {
            List<DrawSquare> rowList = new List<DrawSquare>();
            for(int col = 0; col <10; col++)
            {
                var square = new DrawSquare(row, col);
                asd.Engine.AddObject2D(square.getBackTexture());
                rowList.Add(square);
            }
            drawSquares.Add(rowList);
        }

        while (asd.Engine.DoEvents())
        {
            asd.Engine.Update();
        }
        asd.Engine.Terminate();
    }
}

今回色を書く部分のマスの数は可変になるので、二次元配列ではなく、Listを使います。

実行結果はこんな感じになりました。

当然、見た目は何も弄っていないので、前回と同じですね。

次回はサイズを変更するダイアログを作成していきます。

【テイクアウト】居酒屋 炎 福住店の生つくねでオンライン飲み会

前々からテイクアウトを利用しようと思っていて。

これで500円よ。

お得すぎる。

営業時間もランチタイムに臨時で対応しているので、大助かりです。

昨日はこれをつまみにオンライン飲み会に参加しました。

初めてのオンライン飲み会だったけど普段とは違ってなかなか面白かったよ。

ただ、誰がしゃべっているのか分からない・・・w

あと、お酒の飲むスピードが一人飲みよりゆっくりなので、ビール4本で2時間ぐらい過ごせた。

体重もそんなに増えてなかった。

たまにはアリね。オンライン飲み会。

【ラズパイ】ディスプレイにいろいろ表示させてみる

こちらのサンプルプログラムを入力します。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/files/SenseHAT-Cheatsheet.pdf

8×8のLEDディスプレイにいろいろ表示させてみましょう。

ドット点灯

from sense_hat import SenseHat
sense = SenseHat()
sense.set_pixel(0, 0, 255, 0, 0)

インターフェースは(x, y, R, G, B)。

これは(0,0)に赤を点灯します。

色を変えてみます。

sense.set_pixel(0, 0, 155, 100, 10)

表示位置を変えてみます。

sense.set_pixel(1, 1, 155, 100, 10)

1文字表示

from sense_hat import SenseHat
sense = SenseHat()
sense.show_letter("J", text_colour=[155, 100, 10])

ピクチャ表示

このような絵を作成。

from sense_hat import SenseHat
sense = SenseHat()
sense.load_image("creeper.gif", redraw=True)

一応256階調に調整できるので、フルカラー表示できるはずなんですが、あまり細かい違いは分かりません。

回転

from sense_hat import SenseHat
sense = SenseHat()
sense.load_image("creeper.gif", redraw=True)
sense.set_rotation(r=90, redraw=True)

ピクセルマップ

from sense_hat import SenseHat
sense = SenseHat()

R = [255, 0, 0]
W = [255, 255, 255]

pixel_list = [W, W, W, R, R, W, W, W,
              W, W, R, W, W, R, W, W,
              W, W, W, W, W, R, W, W,
              W, W, W, W, R, W, W, W,
              W, W, W, R, W, W, W, W,
              W, W, W, R, W, W, W, W,
              W, W, W, W, W, W, W, W,
              W, W, W, R, W, W, W, W]

sense.set_pixels(pixel_list)

次はセンサーを弄ってみましょう。

自分、ぼっちですが何か?