LoginSignup
0
0

More than 5 years have passed since last update.

C++ Builder > TTrackBar > 値変更中にOnChange()が繰返し実行される > TTimer利用によるOnChange回数の緩和

Last updated at Posted at 2017-09-06
動作環境
C++ Builder XE4

TTrackBarで値変更中にOnChangeイベントが頻発する問題の対応を検討中。

背景

TTrackBarのOnChangeイベントの実行回数が多い問題において、以下ではOnChange最後に値が連続する振舞いを利用しようとした。
[廃版] C++ Builder > TTrackBar > 値変更中にOnChange()が繰返し実行される > 変更終了の検知案

しかしながら、上記の振舞いは「ビルド環境」「OSのバージョン」などの組合せで「たまたま」そうなっているのかもしれないと思い始めた。

その振舞いに依存したコードは将来のIDEバージョンアップやOSバージョンアップ時に「はまる」要因になる。将来の負債になりうる。

別の案を考えてみた。

TTimer使用

OnChangeイベント頻発をTTimerを使って緩和する。

TTimerはEnabledにした後にInterval後に処理される。その仕組みを使う。

code

Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TMemo *Memo1;
    TTrackBar *TrackBar1;
    TTimer *TimerChanged;
    void __fastcall TrackBar1Change(TObject *Sender);
    void __fastcall TimerChangedTimer(TObject *Sender);
    void __fastcall TrackBar1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift);

private:    // ユーザー宣言
public:     // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

static const int kUseTimer = true;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    TimerChanged->Enabled = false;
    TimerChanged->Interval = 300; // msec
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{

    if (kUseTimer) {
        if (TimerChanged->Enabled) {
            return;
        }
        TimerChanged->Enabled = true;
    } else {
        TimerChangedTimer(Sender);
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerChangedTimer(TObject *Sender)
{
    // 希望する処理を書く
    String msg = Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
    Memo1->Lines->Add(msg);

    // 連続実行を行わない
    TimerChanged->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::TrackBar1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
    /*
    for debug
    TTrackBar変更前に区切り線をつけるために使う
    */
    if (Key == 'V' && Shift.Contains(ssCtrl)) {
        Memo1->Lines->Add(L"-----");
    }
}
//---------------------------------------------------------------------------

結果 > TTimer不使用時

kUseTimer = false

qiita.png

  • (1)-(3): マウスドラッグ時 (短時間)
  • (4)-(6): カーソル使用時

それぞれ複数回イベントが発生している。

結果 > TTimer使用時

kUseTimer = true

qiita.png

  • (1)-(3): マウスドラッグ時 (短時間)
  • (4)-(6): カーソル使用時
  • (7): マウスドラッグ時 (1.2秒程度)

(1)-(6)ではそれぞれ一回に抑止された。
(7)では複数回実行されるが、間隔は300msec以上にはなる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0