[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
ボタンのラベルを左寄せにし、はみ出した部分は表示しないようにしました。
JavaのSwingでしたら、中央揃え・はみ出し非表示にしてなおかつ左の文字が切れないようにしてくれます。FLTKではそのような芸当はできないようなので左寄せにしました。

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
ボタンのラベルを左寄せにし、はみ出した部分は表示しないようにしました。
JavaのSwingでしたら、中央揃え・はみ出し非表示にしてなおかつ左の文字が切れないようにしてくれます。FLTKではそのような芸当はできないようなので左寄せにしました。
[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
Javaアプリの移植に着手しました。
このアプリを完成させた1月下旬時点と比べてプログラミングスキルはアップしているので、成果を反映させながらグレードアップさせたいです。
まずは配列を3次元にして各要素にアクセスできるようにしました。
[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
Fl_buttonのFl_BoxtypeはデフォルトでFL_UP_BOXになっていて出っ張った形状になっています。
これをFl_Widgetから継承したbox関数で変更できます。FL_FLAT_BOXでボタン周囲の枠がなくなります。
この方法が分からなかったためにJava(Swing)で製作したカラーサンプルアプリの移植を進められなかったのですが、これで本格的に着手できます。
Swingの特徴であるLook & Feelは外観に統一感を持たせるのに便利なものの、その分自由度が抑えられてしまう点が引っかかってました。
Java版はサイズが45.6MBなので、どこまで軽量、高速化できるのか楽しみです。
Fl_Button *button = new Fl_Button(loc_x, loc_y, 75, 15);
button->box(FL_FLAT_BOX);
button->color(fl_rgb_color(red,green,blue));
button->labelcolor(fl_rgb_color(169,169,169));
button->labelsize(10);
[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
C++11から標準ライブラリに採用のiota関数を使って連続整数の文字列配列を作成しました。
GUIアプリで整数を表示させる際にこのような配列が必要になったりします。
なおiota関数を使った直後の変数 testはintの配列なので、これはこれで使い道はあります。
最近は変数に型を付けないと物足りなくなってきました。コードを量産するには型推論が便利でしょうが、趣味レベルで楽しむ分には型付けはあまり苦になりません。
C++のように確実に型付けするか、Pythonのようにいさぎよく何も書かないか、どちらもスタンスがハッキリしていて好みですね。
#include <iostream>
#include <numeric>
#include <array>
using std::cout;
// 11から連続整数10個の文字列リスト作成
int main(int argc, char **argv) {
int start_num = 11; // 開始数
const unsigned long nums = 10; // 個数
int test[nums];
std::iota(test, test + nums, start_num);
// 以下でも可能
// std::array<int, nums> test;
// std::iota(test.begin(), test.end(), start_num);
int i = 0;
for (int num : test){
if (i == 0){
cout << "{\"" << num << "\", " ;
} else if (i > 0 && i < (nums -1)){
cout << "\"" << num << "\", " ;
} else {
cout << "\"" << num << "\"}" ;
}
i++;
}
}
--------------------------------------------------
出力
--------------------------------------------------
{"11", "12", "13", "14", "15", "16", "17", "18", "19", "20"}
[M1 Mac, Big Sur 11.6.7, Python 3.10.4]
前回の改良版です。
前回のスクリプトでは、コピーした画像が3枚ある場合、三つ巴になって3枚全て削除対象になる可能性があるため、st_birthtime(元ファイル作成時刻)が同じケースではst_ctime(コピーした時刻)が古い方を削除対象にするようにしました。これで最も新しいコピー画像が残ります。
最初からst_ctimeを判断基準にするとスクリプトがよりシンプルになります。
このスクリプトは先日製作したRustアプリにツールとして登録しました。
import os,glob,itertools,cv2
import numpy as np
path_list = glob.glob("/Desktop/temp/*.png")
delete_list = []
for pair in itertools.combinations(path_list, 2):
path_pair = list(pair)
image1 = cv2.imread(path_pair[0])
stat1 = os.stat(path_pair[0])
btime1 = stat1.st_birthtime
ctime1 = stat1.st_ctime
image2 = cv2.imread(path_pair[1])
stat2 = os.stat(path_pair[1])
btime2 = stat2.st_birthtime
ctime2 = stat2.st_ctime
result_compare = np.array_equal(image1, image2)
if result_compare == True:
if btime1 > btime2:
delete_list.append(path_pair[1])
elif btime1 < btime2:
delete_list.append(path_pair[0])
else:
if ctime1 > ctime2:
delete_list.append(path_pair[1])
else:
delete_list.append(path_pair[0])
print(delete_list)
for file in delete_list:
try:
os.remove(file)
except FileNotFoundError:
pass
[M1 Mac, Big Sur 11.6.7, Python 3.10.4]
スクリーンショットを何枚も撮影していると全く同じ画像が混ざることがあります。
OpenCVを使って同一ディレクトリ内にある画像同士を比較し内容が同じ場合は作成日時が古い方を削除するスクリプトを作成しました。
ファイルパスのリストを作成し、要素数2の組み合わせについて画像を比較、同じであれば作成日時の古い方を削除リストに追加。全ての判定が終わってからまとめて削除します。同じ画像が3枚以上あっても対応できるようにしました。
前にも書きましたが作成日時 st_birthtimeはMacOS限定です。Windowsの場合はst_ctimeになります。
import os,glob,itertools,cv2
import numpy as np
path_list = glob.glob("/Desktop/temp/*.png")
delete_list = []
for pair in itertools.combinations(path_list, 2):
path_pair = list(pair)
image1 = cv2.imread(path_pair[0])
stat1 = os.stat(path_pair[0])
btime1 = stat1.st_birthtime
image2 = cv2.imread(path_pair[1])
stat2 = os.stat(path_pair[1])
btime2 = stat2.st_birthtime
result_compare = np.array_equal(image1, image2)
if result_compare == True:
if btime1 > btime2:
delete_list.append(path_pair[1])
else:
delete_list.append(path_pair[0])
print(delete_list)
for file in delete_list:
try:
os.remove(file)
except FileNotFoundError:
pass
220712追記:
スクリプトの改良版を作成しました。
[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]
FLTKはFl_Colorクラスで独自に256色を設定しています。
主要色やグレースケール等で構成する56色とRGB値を等分して作成した200色です。Fl_Color(色番号)で簡単に色付けできます。
ただ番号だけではどのような色か分からないので、FLTKが公開しているカラーマップをより見やすくするためにツールを作成しています。
[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]
DebugとReleaseのビルド時間を比較してみました。
Releaseモードで最適化レベルが最高の3(デフォルト)ならば、ファイルサイズが1/3削減になります。
Releaseモードの最適化なしで最もビルド時間が短いですが、コマンドが長いのでこの程度の差であれば使わなくてもいいでしょう。
# Debugモード
cargo build
# Releaseモード
cargo build --release
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]
Buttonの形を変えてみました。FrameTypeは60種類近くあります。fltk-rsのGitHubで形状を確認できます。
use fltk::{app, prelude::*, enums::*, button::*, window::Window, group::{Group}};
let mut _btn = Button::new(300, 15, 50, 50, "実行");
_btn.set_frame(FrameType::GleamUpBox);
_btn.set_color(Color::from_u32(0x4D5AAF));
_btn.set_label_color(Color::from_u32(0xFFFFFF));
[M1 Mac, Big Sur 11.6.7, Rust 1.62.0]
ランチャーアプリに色をつけて、さらにTooltipが表示されるようにしました。色設定にはenums::Colorを使います。
use fltk::{app, prelude::*, enums::*, button::*, window::Window, group::{Group}};
fn main() {
let app = app::App::default();
let mut window = Window::new(100, 100, 360, 190, "Tool Launcher");
window.set_color(Color::from_u32(0x00A381));
let grp = Group::new(15, 15, 285 , 160, "");
let mut _btn1= RadioRoundButton::new(15, 15, 140, 20, "OutingCosts");
_btn1.set(true);
_btn1.set_tooltip("OutingCosts.outingcosts");
_btn1.set_label_color(Color::from_u32(0xFFFFFF));
let mut _btn2= RadioRoundButton::new(15, 50, 140, 20, "PhotoSorting");
_btn2.set_label_color(Color::from_u32(0xFFFFFF));
let mut _btn3= RadioRoundButton::new(15, 85, 140, 20, "Scraping");
_btn3.set_label_color(Color::from_u32(0xFFFFFF));
let mut _btn4= RadioRoundButton::new(15, 120, 140, 20, "ScrapingJP");
_btn4.set_label_color(Color::from_u32(0xFFFFFF));
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_color(Color::from_u32(0x4D5AAF));
_btn.set_label_color(Color::from_u32(0xFFFFFF));
_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{
pythonmodule1();
} else if _onoff2 == true{
pythonmodule2();
} else if _onoff3 == true{
pythonmodule3();
} else if _onoff4 == true{
pythonmodule4();
}
});
window.end();
window.show();
app.run().unwrap();
}