はじめに
前回、MATLABでのデジタル時計アプリの作成方法を紹介しました。
デジタル時計は、数字を表示するだけなので、次は、針を持つアナログ時計を作成しています。
figureの作成
まず、figureを作成します。こちらはアナログ時計とほぼ変わりません
%% Figureの表示
figH = figure(); % figH: Figureオブジェクト
figH.MenuBar = 'none'; % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle = 'off'; % 番号表示なし
figH.Name = 'Analog Clock'; % タイトル
axes の作成
アナログ時計では、針を描画したいので、figure全体に表示するaxes(軸)を準備します。
%% Axesの表示
axH = axes(figH); % axH: 軸オブジェクト
axH.Units = 'normalized'; % Positionの単位指定
axH.Position = [0,0,1,1]; % Figure全体にAxesを表示
時計の枠の表示
時計の枠を作成します。最も一般的な時計ということで、次のように円を表示します。
%% 時計枠(丸) を表示
x = linspace(0,2*pi,100); % 1周を100分割(単位:ラジアン)
plot(axH,sin(x),cos(x),'LineWidth',5); % 円を描画
axis(axH,'equal'); % 縦横比を合わせる
hold(axH,'on'); % plot追加のためhold
数字を表示
時計の時刻を表す数字を text で表示します。
各時刻に対応する角度を計算して、sin/cos で座標を決定します。
%% 数字を表示
for h1=1:12
radh = -h1/12*2*pi+pi/2; % 角度の計算
textH = text(axH,0.8*cos(radh),0.8*sin(radh),num2str(h1)); % テキスト作成
textH.HorizontalAlignment = 'center'; % 中央寄せ
textH.FontSize = 30; % フォントサイズ
textH.FontWeight = 'bold'; % 太字指定
end
数字が入って少し時計らしくなってきました。
時計の針の表示
plot で針を表示します。'k' は色を黒に指定することを意味します。太さは、LineWidth で指定します。
%% 長針/短針 のデフォルト表示 (6:00)
hourLineH = plot(axH,[0,0],[0,-0.6],'k','LineWidth',10);
minuteLineH = plot(axH,[0,0],[0,1], 'k','LineWidth',5);
secondLineH = plot(axH,[0,0],[0,1], 'k','LineWidth',1);
一応、時計と認識できる絵になりました。
針の位置の設定(timerのコールバック関数)
timer のコールバック関数では、その時間での針の位置を計算して表示を更新します。
now は、現在のシリアル時刻(datenum: 0年1月0日0:00を0とした日数の表現)を得ることができます。
単位は、'日'なので、例えば、606024 を乗算すると、単位が秒になります。
これを使って計算すると、現在の時刻に相当する針の角度を求めることができます。
グラフィックスとして、針の位置を変更するためには、それぞれの lineオブジェクトの XData, YData を更新します。
function updateClock(~,~)
%% Timerコールバック: 表示の更新
% 各針の角度の計算
sec = now*60*60*24; % 現在時刻の経過秒
rad1 = -fix(sec)/60*2*pi+pi/2; % 秒針の角度
rad2 = -sec/60/60*2*pi+pi/2; % 長針(分)の角度
rad3 = -sec/60/60/12*2*pi+pi/2; % 短針(時間)の角度
% 各針の描画の更新
secondLineH.XData = [0,cos(rad1)];
secondLineH.YData = [0,sin(rad1)];
minuteLineH.XData = [0,cos(rad2)];
minuteLineH.YData = [0,sin(rad2)];
hourLineH.XData = [0,0.6*cos(rad3)];
hourLineH.YData = [0,0.6*sin(rad3)];
end
完成したプログラム
前回と同じところは省略して、プログラム全体を示します。
function simple_analogclock()
%% Figureの表示
figH = figure(); % figH: Figureオブジェクト
figH.MenuBar = 'none'; % メニューをオフ
figH.CloseRequestFcn = @CloseRequestFcn_figH; % クローズ時のコールバック関数
figH.NumberTitle = 'off'; % 番号表示なし
figH.Name = 'Analog Clock'; % タイトル
%% Axesの表示
axH = axes(figH); % axH: 軸オブジェクト
axH.Units = 'normalized'; % Positionの単位指定
axH.Position = [0,0,1,1]; % Figure全体にAxesを表示
%% 時計枠(丸) を表示
x = linspace(0,2*pi,100); % 1周を100分割(単位:ラジアン)
plot(axH,sin(x),cos(x),'LineWidth',5); % 円を描画
axis(axH,'equal'); % 縦横比を合わせる
hold(axH,'on'); % plot追加のためhold
%% 数字を表示
for h1=1:12
radh = -h1/12*2*pi+pi/2; % 角度の計算
textH = text(axH,0.8*cos(radh),0.8*sin(radh),num2str(h1)); % テキスト作成
textH.HorizontalAlignment = 'center'; % 中央寄せ
textH.FontSize = 30; % フォントサイズ
textH.FontWeight = 'bold'; % 太字指定
end
%% 長針/短針 のデフォルト表示 (6:00)
hourLineH = plot(axH,[0,0],[0,-0.6],'k','LineWidth',10);
minuteLineH = plot(axH,[0,0],[0,1], 'k','LineWidth',5);
secondLineH = plot(axH,[0,0],[0,1], 'k','LineWidth',1);
% 現在時刻に合わせる
updateClock();
%% 軸表示の調整
axH.XTick = []; % X軸目盛をオフ
axH.YTick = []; % Y軸目盛をオフ
%% Timerの設定
timerH = timer(); % timeH: タイマーオブジェクト
timerH.ExecutionMode = 'FixedRate'; % 定期的に実行するよう指定
timerH.Period = 1; % 1秒間隔
timerH.TimerFcn = @updateClock; % コールバック関数指定
% 開始時刻の調整(秒が変わる瞬間にできるだけ合わせる。※処理時間の若干の遅延は許容する)
curTime = datetime(now,'ConvertFrom','datenum'); % 現在時刻
delayTime = ceil(curTime.Second)-curTime.Second; % 次に秒が変わる時間との差分(ミリ秒)を計算
timerH.StartDelay = delayTime; % Timerの開始時刻までの遅延を指定
%% timerの開始
start(timerH);
%% コールバック関数
function CloseRequestFcn_figH(~,~)
%% Figureを閉じたときのコールバック:timerをStopしてからクローズ
stop(timerH);
delete(timerH);
delete(figH);
end
function updateClock(~,~)
%% Timerコールバック: 表示の更新
% 各針の角度の計算
sec = now*60*60*24; % 現在時刻の経過秒
rad1 = -fix(sec)/60*2*pi+pi/2; % 秒針の角度
rad2 = -sec/60/60*2*pi+pi/2; % 長針(分)の角度
rad3 = -sec/60/60/12*2*pi+pi/2; % 短針(時間)の角度
% 各針の描画の更新
secondLineH.XData = [0,cos(rad1)];
secondLineH.YData = [0,sin(rad1)];
minuteLineH.XData = [0,cos(rad2)];
minuteLineH.YData = [0,sin(rad2)];
hourLineH.XData = [0,0.6*cos(rad3)];
hourLineH.YData = [0,0.6*sin(rad3)];
end
end
実行例
実行してみます。
終わりに
シンプルな時計アプリの例を紹介しました。
GUIやアニメーションのプログラムの勉強にはいい題材で、好みでいろんな時計アプリを作成できると思いますので、チャレンジしてみてください。
ちなみに、MATLAB Central にもいろいろな例がありますよ。