[Rust] 05 FLTK_RS : ランチャーアプリ製作 ButtonのBool値

[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]

ButtonのON/OFF状態は本家FLTKと同様にvalue()関数で取得できます。ボタン群を波カッコで囲むとスコープが閉ざされてしまうので削除しました。end()関数で閉じていれば問題ありません。

関数外での変数の設定が簡単にはできず、データの改ざんなどがしにくいようスコープを狭くする傾向があるようです。

あとはPythonスクリプトを実行できるようにして仮完成です。

今後FLTKアプリを配布することがあればRustで書こうかと考えています。

まあ重大な不具合を発生させるほど複雑なアプリをC++で作っているわけではないですが、RustがこれからもC/C++の代替言語として影響力を拡げていく可能性もありますし、今から慣れておくのも悪くないでしょう。

コンパイラから細かいところで指導が入るのがうっとうしいものの、C++の影響をかなり受けていて頻出するletとmut以外そんなに違和感はないです。

use fltk::{app, prelude::*, button::*, window::Window, group::{Group}};

fn main() {
    let app = app::App::default();
    let mut window = Window::new(100, 100, 360, 190, "Tool Launcher");
 
    let grp = Group::new(15, 15, 285 , 160, "");
    let mut _btn1= RadioRoundButton::new(15, 15, 140, 20, "PhotoSorting");
    _btn1.set(true);
    let mut _btn2= RadioRoundButton::new(15, 50, 140, 20, "");
    let mut _btn3= RadioRoundButton::new(15, 85, 140, 20, "");
    let mut _btn4= RadioRoundButton::new(15, 120, 140, 20, "");
    let mut _btn5= RadioRoundButton::new(15, 155, 140, 20, "");
    let mut _btn6= RadioRoundButton::new(160, 15, 140, 20, "");
    let mut _btn7= RadioRoundButton::new(160, 50, 140, 20, "");
    let mut _btn8= RadioRoundButton::new(160, 85, 140, 20, "");
    let mut _btn9= RadioRoundButton::new(160, 120, 140, 20, "");
    let mut _btn10= RadioRoundButton::new(160, 155, 140, 20, "");
    grp.end();

    let mut _btn = Button::new(300, 15, 50, 25, "実行");
    _btn.set_callback(move |_| {
        let _onoff1 = _btn1.value();let _onoff2 = _btn2.value();let _onoff3 = _btn3.value();
        let _onoff4 = _btn4.value();let _onoff5 = _btn5.value();let _onoff6 = _btn6.value();
        let _onoff7 = _btn7.value();let _onoff8 = _btn8.value();let _onoff9 = _btn9.value();
        let _onoff10 = _btn10.value();

        if _onoff1 == true{
            println!("onoff1");
        }
    });

    window.end();
    window.show();
    app.run().unwrap();
}

[Rust] 04 FLTK_RS : ランチャーアプリ製作 set_callback

[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]

ボタンの動作設定は本家FLTKとは異なる方法でした。

.cargoディレクトリにあるfltk-1.3.10のexamples内custom_widgets.rsでようやく分かりました。なぜそうなるのかについてはこれから調べます。move |_|とはいったい何なんでしょう。DOCS.RSを読んでもset_callback関数の存在が分かるだけでした。

use fltk::{app, prelude::*, button::*, window::Window, group::{Group}};

fn main() {
    let app = app::App::default();
    let mut window = Window::new(100, 100, 360, 190, "Tool Launcher");
    
    let mut _btn = Button::new(300, 15, 50, 25, "実行");
    _btn.set_callback(move |_| {
        println!("test");
    });
 
    let  grp = Group::new(15, 15, 285 , 160, "");{
        let mut _btn1= RadioRoundButton::new(15, 15, 140, 20, "PhotoSorting");
        _btn1.set(true);
        let mut _btn2= RadioRoundButton::new(15, 50, 140, 20, "");
        let mut _btn3= RadioRoundButton::new(15, 85, 140, 20, "");
        let mut _btn4= RadioRoundButton::new(15, 120, 140, 20, "");
        let mut _btn5= RadioRoundButton::new(15, 155, 140, 20, "");
        let mut _btn6= RadioRoundButton::new(160, 15, 140, 20, "");
        let mut _btn7= RadioRoundButton::new(160, 50, 140, 20, "");
        let mut _btn8= RadioRoundButton::new(160, 85, 140, 20, "");
        let mut _btn9= RadioRoundButton::new(160, 120, 140, 20, "");
        let mut _btn10= RadioRoundButton::new(160, 155, 140, 20, "");
    }
    grp.end();

    window.end();
    window.show();
    app.run().unwrap();
}

[Rust] 03 FLTK_RS : ランチャーアプリ製作 RadioRoundButton

[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]

RoundButtonがただの丸いボタンであることを忘れていました。今回必要なのはRadioRoundButtonです。

本家FLTKとほぼ同じ書き方でOKです。

use fltk::{app, prelude::*, button::*, window::Window, group::{Group, Pack}};

fn main() {
    let app = app::App::default();
    let mut window = Window::new(100, 100, 360, 190, "Tool Launcher");
    
    let _btn = Button::new(300, 15, 50, 25, "実行");

    let grp = Group::new(15, 15, 285 , 160, "");{
        let mut _btn1= RadioRoundButton::new(15, 15, 140, 20, "PhotoSorting");
        _btn1.set(true);
        let mut _btn2= RadioRoundButton::new(15, 50, 140, 20, "");
        let mut _btn3= RadioRoundButton::new(15, 85, 140, 20, "");
        let mut _btn4= RadioRoundButton::new(15, 120, 140, 20, "");
        let mut _btn5= RadioRoundButton::new(15, 155, 140, 20, "");
        let mut _btn6= RadioRoundButton::new(160, 15, 140, 20, "");
        let mut _btn7= RadioRoundButton::new(160, 50, 140, 20, "");
        let mut _btn8= RadioRoundButton::new(160, 85, 140, 20, "");
        let mut _btn9= RadioRoundButton::new(160, 120, 140, 20, "");
        let mut _btn10= RadioRoundButton::new(160, 155, 140, 20, "");
    }
    grp.end();

    window.end();
    window.show();
    app.run().unwrap();
}

[Rust] 02 FLTK_RS : ランチャーアプリ製作 RoundButton

[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]

各種Pythonスクリプトを実行するランチャーアプリをRustで製作しています。

RoundButtonを10個並べたものの、まだ一つだけ選べるようにはなっていません。

FLTK_RSライブラリの中に一応作例はありますが、本家FLTKほど充実はしていないのでさらに情報を集める必要があります。

Rustはプロジェクト名をスネークケース(小文字の単語を_でつなぐ命名規則)にしろだとか、オブジェクト名には先頭に_を付けろ等々、色々細かい注文をつけてきますね。

Makefileではなくcargoコマンドでコンパイルしますが、ブラックボックスになっていてライブラリのバージョンをこちらで指定できないのが不満です。

use fltk::{app, prelude::*, button::*, window::Window, group::Group};

fn main() {
    let app = app::App::default();
    let mut window = Window::new(100, 100, 360, 190, "Tool Launcher");

    let grp1 = Group::new(15, 15, 285 , 160, "");

    let _btn = Button::new(300, 15, 50, 25, "実行");

    let _btn1= RoundButton::new(15, 15, 140, 20, "PhotoSorting");
    let _btn2= RoundButton::new(15, 50, 140, 20, "");
    let _btn3= RoundButton::new(15, 85, 140, 20, "");
    let _btn4= RoundButton::new(15, 120, 140, 20, "");
    let _btn5= RoundButton::new(15, 155, 140, 20, "");
    let _btn6= RoundButton::new(160, 15, 140, 20, "");
    let _btn7= RoundButton::new(160, 50, 140, 20, "");
    let _btn8= RoundButton::new(160, 85, 140, 20, "");
    let _btn9= RoundButton::new(160, 120, 140, 20, "");
    let _btn10= RoundButton::new(160, 155, 140, 20, "");
    
    grp1.end();

    window.end();
    window.show();
    app.run().unwrap();
}

[Rust] 01 インストール

[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]

公式ページからインストールしてみました。

1.以下コマンドでインストール。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

2.以下の行を.bash_profileに追加

export PATH=$PATH:$HOME/.cargo/bin

3.公式HPのナビゲートに沿って簡単なアプリを作成し、実行する。

Hello World
1.プロジェクトを作成するディレクトリをcdにする。
2.プロジェクトを作成する。
cargo new [プロジェクト名]
3.実行する
cargo run

続いて簡単なアプリ作成
1.Cargo.tomlに依存関係を追記
[dependencies]
ferris-says = "0.2"
2.ビルドする
cargo build
3.main.rsを書き換える
4.実行する

公式HPはじめに

4.以下のようなAAが表示されたら完了。

[C++] 79 FLTK : 画像加工アプリにPythonモジュール導入 / Pillow

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

画像加工アプリにPythonのライブラリPillowの機能を導入し、単色アイコンの色変更ができるようにしました。

今回で2度目のPythonモジュール導入になり、引数が1つから5つに増えています。比較的スムーズに実装できました。

OpenCVを使えばC++で同じ機能を実装できるはずですが、開発速度を優先しました。追々OpenCVに切り替えるつもりです。

久しぶりにFinal Cut Pro試用版を使いましたが、プロジェクトの再生時に画質が悪くなるのは仕様あるいはスペック不足のせいでしょうか。画面全体にモザイクが掛かったのかと勘違いしました。

ピクセル化を選択した後に範囲を狭めたにもかかわらずこうなってしまうのは明らかに不具合じゃないかと思います。3ヶ月後に36800円を払うか、無料のDaVinci Resolveに変更するか迷いどころです。

#define PY_SSIZE_T_CLEAN
#include "colorConvert.h"
#include </Library/Frameworks/Python.framework/Versions/3.10/include/python3.10/Python.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>

using std::string; using std::to_string;
using std::cout; using std::endl;

int colorConvert(const char* path, int red, int green, int blue, const char* name) {
    Py_Initialize();

    // pyファイルの指定(imageColorConvert.py)
    PyObject* myModuleString = PyUnicode_FromString((char*)"imageColorConvert");

    // pyファイルのモジュール化
    PyObject* myModule = PyImport_Import(myModuleString);

    // pyファイル内の関数を指定
    PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"color_convert");

    // 関数の引数を設定(5個)
    PyObject* args = PyTuple_Pack(5,PyUnicode_FromString(path),PyUnicode_FromString((to_string(red)).c_str()),PyUnicode_FromString((to_string(green)).c_str()),PyUnicode_FromString((to_string(blue)).c_str()),PyUnicode_FromString(name));

    // 関数を実行
    PyObject* myResult = PyObject_CallObject(myFunction,args);

    return 0;

    Py_Finalize();
}
#include "split.h" // 自製文字列分割関数を含むsplitクラス

class split spt; // 自製クラスのオブジェクト化

void color_convert_func(){
    const char *path = input_line->value();
    const char *name = name_input->value();
    const char *rgb = rgb_input->value();

    string rgb_str = string(rgb);
    vector<string> list_rgb = spt.splits(rgb_str, ',');
    
    string red0 = list_rgb[0];
    string green0 = list_rgb[1];
    string blue0 = list_rgb[2];

    cout << "red0 " << red0 << endl;
    cout << "green0 " << green0 << endl;
    cout << "blue0 " << blue0 << endl;

    vector<string> list_red = spt.splits(red0, '(');
    vector<string> list_blue = spt.splits(blue0, ')');

    int red = stoi(list_red[1]);
    int green = stoi(green0);
    int blue = stoi(list_blue[0]);

    cout << "red " << red << endl;
    cout << "green " << green << endl;
    cout << "blue " << blue << endl;

    colorConvert(path,red,green,blue,name); // Pythonモジュール

    output_line->insert("colorConvert is success!\n");
    cout << "colorConvert is success!" << endl;

}
--------------------------------------------------
出力例:
RGB(106,90,205)から数字を抽出しPythonモジュールの引数として使用
--------------------------------------------------
red0 RGB(106
green0 90
blue0 205)
red 106
green 90
blue 205
colorConvert is success!

[Python]333 pngファイルを単色で塗りつぶす / Pillow

[M1 Mac, Big Sur 11.6.7, Python 3.10.4]

単色アイコンの色を変えるために関数を作成しました。

これで単色であれば一々Adobe XDを立ち上げアイコンを作らなくて済みます。

for文の内容を変えれば特定の色だけ変更することも可能です。

Pythonならスケッチ感覚でコーディングできるので本当に楽ですね。

from PIL import Image
import numpy as np

def color_convert(path,red,green,blue,name="color"):
    # pngファイルの色情報を読み込む [red, green, blue, alpha]
    img_array = np.array(Image.open(path))

    # 全画素のRGB値を変更
    for row in img_array:
        for pixel in row:
            np.put(pixel,0,red)
            np.put(pixel,1,green)
            np.put(pixel,2,blue)
                
    img = Image.fromarray(img_array)

    new_filename0 = path.split("/")[:-1]
    new_filename = '/'.join(new_filename0) + "/" + name + ".png"
    img.save(new_filename)
        
    return 0

if __name__ == '__main__':
    path = "umemurasaki.png"
    color_convert(path,173,255,47,"greenyellow")

[C++] 78 FLTK : OpenGLアニメーション glutSolidTeapot

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

glutSolidTeapotを回転させてみました。

ネット上に日本語情報が結構あるので、色々吸収したいです。

OpenGLの使い道の一つとして3D風アプリアイコンへの活用を考えています。

int main(int argc, char *argv[])
{
    Fl::scheme("gtk+");
    Fl::visual(FL_DOUBLE | FL_RGB);
    Fl::get_system_colors();

	glutInit(&argc, argv);

    GL_Graph *window = new GL_Graph(100, 100, 480, 480, "OpenGL Viewer");
	window->mode(FL_RGB | FL_ALPHA | FL_DOUBLE | FL_DEPTH);
	window->end();
    window->show(argc, argv);
    return Fl::run();
}

参考サイト

[C++] 77 FLTK : OpenGLグラフィックの切替

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

複数のOpenGLグラフィックをボタンで切替できるようにしました。

Windowに埋め込んだままでの切替は今の私のスキルではできず、2枚目からは別ウインドウになります。

glgraph= new GL_Graph(380, 10, 190, 190, nullptr);
        
next_btn = new Fl_Button(575,85,20,20,"[絵文字]");
next_btn->callback(next_cb);
int box_num = 0; グラフィック番号の初期値
int box_nums = 2; グラフィックの個数

void next_cb(Fl_Widget*, void*) {
    box_num +=1;
    if (box_num >= box_nums){
        box_num = 0;
    }

    switch(box_num){
        case 0:
        {
            delete(glgraph2);
            glgraph= new GL_Graph(380+100, 10+100, 190, 190, nullptr);
            glgraph->show(); // draw,redrawではうまくいかず
            break;
        }
        case 1:
        {
            delete(glgraph);
            glgraph2= new GL_Graph2(380+100, 10+100, 190, 190, nullptr);
            glgraph2->show();
            break;
        }
    }

    output_line->insert((to_string(box_num)).c_str());
    output_line->insert("\n");
}

[C++] 76 FLTK : OpenGLグラフィックの埋め込み

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

FLTKアプリにOpenGLグラフィックを埋め込みました。

アプリ開発の合間にグラフィックのコードを試し書きして描画したりできるので活用したいです。


#pragma once
#include <cppstd.h> //自製標準ヘッダファイル群
#include <FLstd.h> //自製FLヘッダファイル群
#include <GL/glew.h> //この順序で固定
#include <FL/glut.h> //この順序で固定

const GLfloat MY_LIGHT0_POS[4] = { 2.0f, 4.0f, 1.0f, 0.0f };
const GLfloat MY_LIGHT_AMBI[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
const GLfloat MY_LIGHT_DIFF[4] = { 0.9f, 0.9f, 0.9f, 1.0f };
const GLfloat MY_LIGHT_SPEC[4] = { 0.2f, 0.2f, 0.2f, 1.0f };

class GL_Box : public Fl_Gl_Window
{
    public:
    GL_Box(int x_, int y_, int w_, int h_, const char* l);
    ~GL_Box();

    void InitGL(void);
    void Resize(int w, int h);
    void Display(void);

    private:
    void draw(void);
};

参考サイト