質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GTK+

GTK+とはGUIを作るために作られた、とても使いやすく機能に富んだツールキットです。クロスプラットフォームによる互換性と、使いやすいAPIを備えています。

Q&A

1回答

3521閲覧

gtkでアニメーション

Tack

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GTK+

GTK+とはGUIを作るために作られた、とても使いやすく機能に富んだツールキットです。クロスプラットフォームによる互換性と、使いやすいAPIを備えています。

0グッド

0クリップ

投稿2017/10/03 04:49

gtkで写真をコマ送り表示でするプログラムを作成しています。
しかし、ループ文が上手く動作しません。
お力を貸してください。

やりたいことは以下の通りです。
boxに写真を表示し、timeout_addで1秒毎に写真を更新。

写真はOpenCVを使用して、USBカメラから100fpsでキャプチャした画像を同じファイル名で保存し、上書きし続けるようになっています。

以下に私の書いたソースコードを添付します。

#include <gtk/gtk.h>

GtkWidget *window;
GtkWidget *vbox;
GtkWidget *image;
GtkWidget *button;

static void cb_button_clicked (GtkWidget *button, gpointer user_data) /ボタン押下で終了する関数/
{
gtk_main_quit ();
}

static gboolean capture_loop(GtkWidget *box) /t/
{
image = gtk_image_new_from_file ("/home/pi/project/cam3/Capture.jpg"); /ファイルから画像を読み込んでイメージの作成/
gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); /イメージをボックスに配置/
return (TRUE);
}

int
main(int argc, char** argv)
{
gtk_init (&argc, &argv); /GTK初期化/
window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /ウィンドウの作成/
gtk_widget_set_size_request (window, 500,400); /大きさ設定/

{ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); /*縦にウィジェットを配置するボックスの作成*/ gtk_container_add (GTK_CONTAINER (window), vbox); /*ボックスをウィンドウに配置*/ button = gtk_button_new_with_label ("✕"); /*終了ボタン作成*/ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); /*ボタンをboxに配置*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cb_button_clicked), NULL); /*ボタンに関数リンク*/ g_timeout_add(1000, (GSourceFunc)capture_loop, NULL); /*ループ文*/ } g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /*ウィンドウを閉じる際にプログラム終了*/ gtk_widget_show_all (window); /*ウィンドウの表示*/ gtk_main (); /*メインループ(ユーザーからの操作待ち)*/ return 0;

}

実行すると、写真は表示されず、終了ボタンのみ表示されます。
どこがおかしいのでしょうか。
ご回答よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

こんにちは。

※ご提示のコード中にUSBカメラでjpegの静止画ファイルを保存している処理が無いので、
それは別のプログラムがやっている、との前提で回答させてもらっています。

gtkを試せる環境にないので想像なのですが、こちらの情報を見ると、

gtk - Image not showing when loaded from file

capture_loop()中のgtk_image_new_from_file() の呼び出しは1回だけが有効で、それ以降
ウィジェットに画像をセットするのは gtk_image_new_from_file()が必要な気もします。

gtk-image-set-from-file

capture_loop() 自体が確実に呼び出され、2回目以降をスキップさせるようにして
最初の1回だけは確実に表示されることを確認してみると良いと思います。(これはOKでしょうか?)

あと、この手のGUIモノで良くあるのは、「表示はGUI用のスレッドで実行しなければならない」
と言うものがあります。g_timeout_add()で登録されたコールバック関数が
別のスレッドで実行される場合、描画処理を行うのは問題があるかもしれません。
(想像なので、外していたらすみません)

投稿2017/10/03 08:51

編集2017/10/03 08:53
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tack

2017/10/04 05:19

ご回答ありがとうございます。 早速ご指摘の通り修正したところ、画像が表示され1秒毎に更新されるようになりました。 しかし、OpenCVで元の画像ファイルを書き換えている瞬間に、GTKで画像を取りに行ってしまうと、画像が正常に読み込めずチラついてしまいます。 そこで、画像ファイルを書き換えている瞬間にGTKで画像を取りに行ってしまった時は、再度画像を取りにいき、チラつきを無くしたいのですが、どういった条件処理をしたらよいでしょうか。 アイデアがあれば提供していただければと思います。
dodox86

2017/10/04 08:15

OpenCVで画像を保存するのが「保存PGM」、GTKの表示用プログラムは 「表示PGM」と、2つのプログラム(実行ファイル)であることを前提で お話を進めます。本来であれば保存PGMと表示PGM間でプロセス間通信で 同期を取り、「画像ファイル作成〜保存終了」をイベントとして 表示用プログラムが読み取り開始するような作りにすると思います。 ですが今回はそれはやり過ぎだと思うので、もう少し簡単にいきます。 1. 保存PGMで、静止画を撮り、保存するときのファイル名を 「filenameA」とします。 2. 表示PGMでは読み出す時のファイル名を「filenameB」とします。 3. 表示PGMは今まで通り、1000ミリ秒周期でfilenameBを読みに行きます。 読めなければ何もせず、前の表示のまま終わります。 読めれば表示して、表示が終わったらfilenameBのファイルを deleteします。(大事) 4. 保存PGMでは、filenameAで開いたファイルを書き終わり、closeしたら、 filleameBへrenameします。もしここでrenameに失敗したら、 filenameBはまだ表示PGMで表示処理中です。この場合、放置します。 5. 保存PGMでは前のfillenameAが存在してもしなくても、新たに静止画を 撮影してfilenameAに上書き保存します。filenameAの持ち主は常に 保存PGMなので、影響しません。最後にfilenameBへrenameすることが キモになります。rename が正常終了してfilenameBが出現したとき、 ファイルは表示PGMの、いうなれば所有物になります。 これで基本的に競合しないはずです。 上記は一例です。ファイルのrenameやdeleteの挙動はWindouxと Linuxで異なるので、思い通りにいかない可能性も少しありますが、 おおむねこのような排他処理が必要になるかと思います。 あとは、有名な「ロックファイルによる排他」制御があります。 それを使ってもできます。「linux ロックファイル 排他」 などでググってみてください。ものの考え方はWindowsでも使えます。
dodox86

2017/10/04 08:22

一部修正:”3. 表示PGMは今まで通り、1000ミリ秒周期でfilenameBを読みに行きます。”の部分ですが、gtk-image-set-from-file()で読み取ってしまうと表示がブランクになってしまうと思うので、fopen()やopen()等でのファイルの存在確認だけにしてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問