[C++]108 FLTK : 表示色カウンターと履歴消去機能追加 

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

表示色が履歴の何番目かを示したカウンターと履歴消去機能を追加しました。カウンターのFl_Inputを右揃えにできず、やむなく左揃えで妥協しました。

これで搭載したい機能は全て実装完了です。後は配布に耐えうる堅牢性への強化でしょうか。

// counter
counter = new Fl_Input(625, 89, 27, 10,"");
counter->box(FL_FLAT_BOX);
counter->align(FL_ALIGN_INSIDE|FL_ALIGN_RIGHT); // 設定は効かず
counter->color(fl_rgb_color(238,238,238));
counter->textsize(10);

// 色表示関数内
string count = to_string(color_index) + "/" + to_string(selectColorList.size());
counter->value("");
counter->value(count.c_str());

[C++]107 FLTK : 表示色の履歴管理および順逆送り new演算子

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

手掛けてみたら予想通りのややこしさでしたが、運良くすんなり書けました。

C/C++ユーザーの方々には釈迦に説法ですが、変数やポインタのvectorを無処理で作成し履歴データとして蓄積しても勝手に上書きされるので失敗します。

new演算子でメモリを確保し、そこにデータを入れてからvectorを作成します。

確保したメモリをdelete演算子でどのようにどのタイミングで解放するのか、についてはこれから考えます。

vector<vector<const char*>> selectColorList;
const char *name_c, *roma_c, *code_c;
int color_index;

void selectColorListMake(const char* name, const char* roma, const char* code){
    color_index = selectColorList.size();

    vector<const char*> selectColor = {name, roma, code};
    selectColorList.push_back(selectColor);
    color_index += 1;
}

void prevColor(Fl_Widget*, void*){
    if (!(color_index < 2)){
        vector<const char*> prev_color = selectColorList[color_index -1 -1];
        name_c = prev_color[0];
        roma_c = prev_color[1];
        code_c = prev_color[2];
        cout << "name:" << name_c;
        cout << " roma:" << roma_c;
        cout << " code:" << code_c;
        color_index -= 1;
        cout << " index:" << (to_string(color_index)).c_str() << endl;;

        name_input->value("");
        name_input->insert(name_c);
        roma_input->value("");
        roma_input->insert(roma_c);
        code_input->value("");
        code_input->insert(code_c);

        output_line->insert(name_c);
        output_line->insert(" ");

        showColor();
    } else {
        cout << "記録はありません" << endl;
    }
}

void nextColor(Fl_Widget*, void*){
    if (!(color_index >= selectColorList.size())){
        vector<const char*> next_color = selectColorList[color_index -1 + 1];
        name_c = next_color[0];
        roma_c = next_color[1];
        code_c = next_color[2];
        cout << "name:" << name_c;
        cout << " roma:" << roma_c;
        cout << " code:" << code_c;
        color_index += 1;
        cout << " index:" << (to_string(color_index)).c_str() << endl;

        name_input->value("");
        name_input->insert(name_c);
        roma_input->value("");
        roma_input->insert(roma_c);
        code_input->value("");
        code_input->insert(code_c);

        output_line->insert(name_c);
        output_line->insert(" ");

        showColor();
    } else {
        cout << "記録はありません" << endl;
    }
}

色表示する関数内
// selectColor追加
const char* name_c2 = name_input->value();
char* name_c3 = new char[strlen(name_c2) + 1];
strcpy(name_c3, name_c2);

const char* roma_c2 = roma_input->value();
char* roma_c3 = new char[strlen(roma_c2) + 1];
strcpy(roma_c3, roma_c2);

const char* code_c2 = code_input->value();
char* code_c3 = new char[strlen(code_c2) + 1];
strcpy(code_c3, code_c2);

selectColorListMake(name_c3, roma_c3, code_c3);

[C++]105 FLTK : クリアボタンの配置 value関数

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

Window右側上下欄のクリアボタンを配置しました。Fl_Inputなどのvalue関数を使います。

開発は佳境に入っていて残すは表示色の記録および順送り、逆送りになります。

せっかくここまで作ったのですから、どこか国内向けの配布サイトに登録しようかと思っています。Microsoft StoreのJava版はスキル維持のためそのまま残すつもりです。

// C1ボタン
void clearUpper(Fl_Widget*, void*){
    name_input->value("");
    roma_input->value("");
    code_input->value("");
    location_input->value("");
}

// C2ボタン
void clearLower(Fl_Widget*, void*){
    output_line->value("");
    output_line2->value("");
}

[C++]104 FLTK : 正規表現におけるトラブル regex_search バイト列調査

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

appファイルではregex_searchを使ったひらがな抽出がうまくできないため、バイト列として何が抽出されているのか調べました。

その結果、常に2バイトのデータが返ってきていることが分かりました。本来は3バイト×ひらがな文字数のはずです。実行ファイルでは何の問題もないのに不思議な現象です。

これは仕様の問題にも思えますので、深入りしない方が良さそうです。ひらがな検索は保留としてローマ字検索に方向転換します。

// stringのバイト列への変換
void binary_convert(string str){
	for (int i = 0; i < str.length(); ++i) {
		bitset<8> bs(str[i]);
        string bs_str = bs.to_string();
		cout << str << " " << i+1 << "番目 " << bs << endl;

        output_line2->insert(bs_str.c_str());
        output_line2->insert("\n");
	}
	cout << "end"<< endl;
}

[C++]103 FLTK : 開発モードの設定 Fl_Sys_Menu_Bar

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

前回記事のFL_Window 2窓設定を開発モードとしてMacOSのシステムメニューから選択できるようにしました。配置していたトグルボタンを削除し、普段は通常モードとして使用します。

開発モードを選択する度にトグルボタンの様に表示/非表示が切り替わります。

Fl_Window *window2;
int mode = 0; // 0:通常モード, 1:開発モード

int main(int argc, char **argv) {

    static Fl_Menu_Item	items[] = {
    { "設定", 0, 0, 0, FL_SUBMENU },
    { "開発モード", 0, showSubWindow, 0, 0 },
    { 0 },
    { 0 }
    };
    Fl_Sys_Menu_Bar *menubar;
    menubar = new Fl_Sys_Menu_Bar(0, 0, 60, 20);
    menubar->box(FL_FLAT_BOX);
    menubar->menu(items);

    Fl_Window *window = new Fl_Window(50,50,660,480,"Color Sample");
    window->color(fl_rgb_color(238,238,238));

    <中略>
    
    window->end();
    window->show(argc, argv);
    
    // サブWindow
    window2 = new Fl_Window(750,50,360,480,"出力用");
    window2->color(fl_rgb_color(238,238,238));

    // output
    output_line2 = new Fl_Multiline_Output(0,0,360,480,"");
    output_line2->textsize(12);

    window2->end();

    return Fl::run();
}
extern Fl_Window *window2;
extern int mode;

void showSubWindow(Fl_Widget*, void*){
    if (mode == 1){
        mode = 0;
    } else {
        mode = 1;
    }

    if (mode == 1){
        window2->show();
    } else {
        window2->hide();
    }
}

[C++]102 FLTK : Fl_Windowの複数表示

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

コンソールが表示される実行ファイルとappファイルで挙動が異なることが多いため、appファイルで出力を確認できる2窓の開発用アプリを用意しました。

Name欄から取得した文字列からひらがなを抽出してGUI内位置検索したものの、結果を表示させても該当なしになる現象を動画に収めています。右Windowから分かるように抽出したひらがなは文字化けしています。

Fl_Window *window2;
Fl_Toggle_Button *tgl_btn;

int main(int argc, char **argv) {

    Fl_Window *window = new Fl_Window(50,50,660,480,"Color Sample");
    window->color(fl_rgb_color(238,238,238));

    <中略>

    // サブWindow表示切り替え用トグルボタン
    tgl_btn = new Fl_Toggle_Button(602,227,50,15,"W表示");
    tgl_btn->labelsize(12);
    tgl_btn->callback(showSubWindow);

    window->end();
    window->show(argc, argv);
    
    // サブWindow
    window2 = new Fl_Window(750,50,360,480,"出力用");
    window2->color(fl_rgb_color(238,238,238));

    // output
    output_line2 = new Fl_Multiline_Output(0,0,360,480,"");
    output_line2->textsize(12);

    window2->end();
    window2->show(argc, argv);

    return Fl::run();
}
extern Fl_Window *window2;
extern Fl_Toggle_Button *tgl_btn;

void showSubWindow(Fl_Widget*, void*){
    int onoff_btn = tgl_btn->value();
    
    if (onoff_btn == 1){
        window2->hide();
    } else {
        window2->show();
    }
}

[C++]101 FLTK : 同名関数の使用

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

製作中のカラーアプリはCode欄から取得したカラーコードの有無を検索し、ボタンのタブ内位置を表示する機能を搭載していますが、その際にFl_Boxのカラー表示も反映するようにしました。

callback用のshowColor関数を使い回します。引数が異なるのであれば同名の関数設定が可能です。知ってはいましたが初めて使います。もちろん関数の内容が違っていても構いません。

本当はJava(Swing)のdoClickメソッドのようにプログラムから表示ボタンを押させたかったのですが、FLTKドキュメントを隅々まで調べても方法が見つかりませんでした。

// コールバック用
void showColor(Fl_Widget*, void*){
	onoff_zero = zero_rbtn->value();
    onoff_sharp = sharp_rbtn->value();
    onoff_hex = hex_rbtn->value();
    onoff_rgb = rgb_rbtn->value();
    
    if (onoff_zero == 1){
        ToZeroConvert();
    } else if (onoff_sharp == 1){
        ToSharpConvert();
    } else if (onoff_hex == 1){
        ToHexConvert();
    } else {
        ToRGBConvert();
    }
}

// 通常用
void showColor(){
	onoff_zero = zero_rbtn->value();
    onoff_sharp = sharp_rbtn->value();
    onoff_hex = hex_rbtn->value();
    onoff_rgb = rgb_rbtn->value();
    
    if (onoff_zero == 1){
        ToZeroConvert();
    } else if (onoff_sharp == 1){
        ToSharpConvert();
    } else if (onoff_hex == 1){
        ToHexConvert();
    } else {
        ToRGBConvert();
    }
}

[C++]100 FLTK : ラジオボタンの逆送り

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

とりあえずJavaからの移植が完了しましたが、色々物足りない箇所が出てきたので手を加えていきます。

まずはカラーコードのタイプを順送りで変えているところに逆送りボタンを追加しました。

次はカラー表示の履歴を記録し、進む、戻るボタンで変えられるようにします。

void prevType(Fl_Widget*, void*){
	onoff_zero = zero_rbtn->value();
    onoff_sharp = sharp_rbtn->value();
    onoff_hex = hex_rbtn->value();
    onoff_rgb = rgb_rbtn->value();

    if (onoff_zero == 1){
        onoff_zero = zero_rbtn->value(false);
        onoff_rgb = rgb_rbtn->value(true);
        ToRGBConvert();
    } else if (onoff_sharp == 1){
        onoff_sharp = sharp_rbtn->value(false);
        onoff_zero = zero_rbtn->value(true);
        ToZeroConvert();
    } else if (onoff_hex == 1){
        onoff_hex = hex_rbtn->value(false);
        onoff_sharp = sharp_rbtn->value(true);
        ToSharpConvert();
    } else {
        onoff_rgb = rgb_rbtn->value(false);
        onoff_hex = hex_rbtn->value(true);
        ToHexConvert();
    }
}

[C++] 99 FLTK : カラーコードからGUI内ボタン位置検索

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

カラーコードからGUI内ボタン位置を検索できるようにしました。カラー名からの検索は前回記事で書いたようにappファイルでひらがなの抽出ができずに難航しているため、一旦これで仮完成とします。

ひらがな抽出はPythonモジュールでもうまくいかないので、C++で再挑戦してみます。

// CEクラスとfindIndex関数は自製

void searchLocation(Fl_Widget*, void*){
    string name_alpha, name_hira;
    string location;
    int column,row;

    input_name = name_input->value();
    input_code = code_input->value();

	onoff_name = name_rbtn->value();
    onoff_code = code_rbtn->value();

    if (onoff_name == 1){
        cout << "Name検索" << endl;

        name_hira = CE.extract(input_name, HIRAGANA);
        name_alpha = CE.extract(input_name, ALPHABET);
        
        cout << "Alphabet " << name_alpha << endl;
        cout << "ひらがな " << name_hira << endl;

        if (name_alpha != ""){
            cout << "140色検索" << endl;

            auto index = findIndex(colorList_name, name_alpha);
            if (index != -1){
                column = index/28 + 1;
                row = index%28 + 1;
                
                location = "140色 " + to_string(column) + "列 " + to_string(row) + "行";
                roma_input->value("");
                code_input->value("");
                location_input->value("");
                location_input->insert(location.c_str());
            } else{
                location_input->value("");
                location_input->insert("該当なし");
            }
            
        } else if (name_hira !=""){
            cout << "和色検索" << endl;

            int process = 0; // 検索状態 0:検索中, 1:検索終了
            int tab_num = 1;
            for (vector<string> list:colorList2_name){
                auto index = findIndex(list, name_hira);
                if (index != -1){
                    column = index/30 + 1;
                    row = index%30 + 1;
                    
                    location = tab_names[tab_num] + " " + to_string(column) + "列 " + to_string(row) + "行";
                    roma_input->value("");
                    code_input->value("");
                    location_input->value("");
                    location_input->insert(location.c_str());
                    process = 1;
                    break;
                }
                tab_num += 1;
            }
            if (process==0){
                location_input->value("");
                location_input->insert("該当なし");
            }
            
        } else {
            cout << "検索文字列なし" << endl;
        }

    } else {
        cout << "Code検索" << endl;
        int process = 0;
        // input_codeを0xへ変換
        code_zero = ToZeroConvert2();

        cout << "code 140色検索" << endl;

        auto index = findIndex(colorList_code, code_zero);
        if (index != -1){
            column = index/28 + 1;
            row = index%28 + 1;
            
            string result_name = colorList_name[index];
            location = "140色 " + to_string(column) + "列 " + to_string(row) + "行 " + result_name;
            string name = colorList_name[index];
            name_input->value("");
            roma_input->value("");
            location_input->value("");
            location_input->insert(location.c_str());
            process = 1;
        }

        cout << "code 和色検索" << endl;

        if (process == 0){
            int tab_num = 1;
            for (vector<string> list:colorList2_code){
                auto index = findIndex(list, code_zero);
                if (index != -1){
                    column = index/30 + 1;
                    row = index%30 + 1;
                    
                    string result_name = colorList2_name[tab_num -1][index];
                    location = tab_names[tab_num] + " " + to_string(column) + "列 " + to_string(row) + "行 " + result_name;
                    name_input->value("");
                    roma_input->value("");
                    location_input->value("");
                    location_input->insert(location.c_str());
                    process = 1;
                    break;
                }
                tab_num += 1;
            }
            if (process==0){
                location_input->value("");
                location_input->insert("該当なし");
            }
        }
    }