例: カウントダウンタイマー

スクリーンショット

カウントダウンタイマー

プロジェクトレイアウト

countdown_timer/
├── CMakeLists.txt
└── main.cpp

CMakeファイル

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(countdown_timer LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(FLTK 1.4 REQUIRED CONFIG)

add_executable(countdown_timer main.cpp)

target_link_libraries(countdown_timer PRIVATE fltk::fltk)

プログラムのソースコード

main.cpp:

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Window.H>

#include <format>
#include <string>

struct AppContext {
  int start = 10;
  int count = 0;
  Fl_Box *digits;
  Fl_Button *start_button;
  Fl_Button *reset_button;
  std::string sbuf;
};

AppContext *as_app_context(void *ptr) { return static_cast<AppContext *>(ptr); }

void update_digits_label(AppContext *ctx) {
  ctx->sbuf.clear();
  std::format_to(std::back_inserter(ctx->sbuf), "{}", ctx->count);
  ctx->digits->label(ctx->sbuf.c_str());
}

void timeout_cb(void *data) {
  auto ctx = as_app_context(data);

  if (ctx->count <= 0) {
    // Finished
    ctx->start_button->label("スタート");
    return;
  }

  --ctx->count;

  update_digits_label(ctx);

  Fl::repeat_timeout(1.0, timeout_cb, ctx);
}

void start_button_cb(Fl_Widget *w, void *data) {
  if (!Fl::has_timeout(timeout_cb, data)) {
    // Start button pressed
    Fl::add_timeout(1.0, timeout_cb, data);
    w->label("一時停止");
  } else {
    // Pause button pressed
    Fl::remove_timeout(timeout_cb, data);
    w->label("スタート");
  }
}

void reset_button_cb(Fl_Widget *w, void *data) {
  auto ctx = as_app_context(data);
  ctx->count = ctx->start;
  update_digits_label(ctx);
}

int main() {
  auto window = new Fl_Window(300, 300, "Countdown Timer");

  auto digits = new Fl_Box(10, 10, 280, 240);
  digits->box(FL_DOWN_BOX);
  digits->labelfont(FL_BOLD);
  digits->labelsize(80);
  digits->labeltype(FL_SHADOW_LABEL);

  auto start_button = new Fl_Button(10, 260, 140, 30, "スタート");
  auto reset_button = new Fl_Button(150, 260, 140, 30, "リセット");

  int const countdown_start = 10;

  AppContext ctx{
      .start = countdown_start,
      .count = countdown_start,
      .digits = digits,
      .start_button = start_button,
      .reset_button = reset_button,
  };

  update_digits_label(&ctx);
  start_button->callback(start_button_cb, &ctx);
  reset_button->callback(reset_button_cb, &ctx);

  window->end();
  window->show();
  return Fl::run();
}

文書の編集
文書の先頭へ