retireSakiの日記

たぶん引退した?ソフトウエアエンジニアのブログ

GTKmm (3.0) と glade によるアプリ (12) - ステータスバーの表示 & 遅延時間でクリア処理

 これまでは前回のソースをベースにしてきましたが、少しソースも大きくなってきましたので新たに作ります。
今回は、ステータスバーの表示とそのステータスバーを遅延時間経過後にステータスバーをクリアします。これに伴いスピンボタンの設定を行っています。

f:id:retireSaki:20181119143947j:plain

チェックボタンをチェックしている時は、ラインテキストで入力したテキストをステータスバーに表示後、スピンボタンで設定した遅延時間経過後にステータスバーをクリアします。
チェックボタンをチェックしていない時は、ラインテキストで入力したテキストをステータスバーに表示したままにします。

ソースコードは最後に両方の機能を含めたものを公開。(zipダウンロードできます)

A. glade の編集

f:id:retireSaki:20181119144010j:plain

今回はメインウィンドウのみの構成です。
詳細はダウンロードして、paned_test.glade を確認してください。


B. MainWindow.h の編集


● MainWindow.h

class MainWindow : public Gtk::ApplicationWindow
{
public:
    MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& m_builder_)
        : Gtk::ApplicationWindow(obj)
        , m_builder{m_builder_}
    {
        setInit_display();
    }

    virtual ~MainWindow() = default;

protected:

    Gtk::MenuBar *m_menu = nullptr;
    Gtk::MenuItem *m_menuitem_quit = nullptr;
    Gtk::Box *m_vbox = nullptr;
    Gtk::Statusbar *m_status_bar = nullptr;

    Gtk::Button *m_btn1 = nullptr;
    Gtk::Entry * m_edit1 = nullptr;
    Gtk::CheckButton *m_chk_use_timer = nullptr;
    Gtk::SpinButton *m_spin_delay_time = nullptr;

    unsigned int untimer_interval = 3000; // msec
    std::map<int, sigc::connection> m_timers;

    virtual void on_btn1_clicked(){

        untimer_interval = (unsigned int)m_spin_delay_time->get_value();

        if ( !m_timers.empty() ){
	    m_timers[m_timers.begin()->first].disconnect();
            m_timers.clear();
        }

        if (m_chk_use_timer->get_active()){

            sigc::connection conn = Glib::signal_timeout().connect(
                sigc::mem_fun(*this, &MainWindow::on_timeout_status), untimer_interval*1000);
            m_timers[untimer_interval] = conn;
        }

        m_status_bar->push( m_edit1->get_text(), 2 );
    }

    bool on_timeout_status(){
        m_timers[m_timers.begin()->first].disconnect();
        m_timers.clear();

        m_status_bar->remove_all_messages(2);

        return false;
    }

private:
    Glib::RefPtr<Gtk::Builder> m_builder;

    void set_AppIcon();
    void setInit_display();

    void on_click_quit()
    {
        delete m_status_bar;
        hide();
    }

};
#endif

 初期設定以外の関数以外は全てヘッダー内で処理しています。

1) on_btn1_clicked() 関数
 "display message"ボタンのクリック処理です。

 get_value(); でスピンボックスの値を取得し、メッセージクリアタイマーのインターバル値とします。
 タイマーが稼働中であればタイマーを停止後します。 

 チェックボックス m_chk_use_timer がチェック( get_active() )されていたら、インターバルタイマーを起動します。

 ステータスバーに edit1 の内容を出力します。

2) on_timeout_status() 関数
 インターバルタイムアウト時にステータスバーのクリアします。

 remove_all_messages() でステータスバーの内容をクリアします。

 retern false; によりタイマーをていします。


C. MainWindow.cc の編集


● MainWindow.cc

void MainWindow::setInit_display()
{
    refBuilder->get_widget("VBox", m_vbox);

    m_status_bar = new Gtk::Statusbar;

    Gtk::Widget* w_status_bar_area = m_status_bar->get_message_area();
    Gdk::RGBA m_color;
    m_color.set_rgba(0.0,0.0,1.0,1.0);
    w_status_bar_area->override_color( m_color );
    w_status_bar_area->override_font( Pango::FontDescription( "Sans 10" ) );

    m_vbox->pack_start(*m_status_bar, Gtk::PackOptions::PACK_SHRINK );
    m_status_bar->show();

    // get menu widget
    refBuilder->get_widget("menuBar", m_menu);
    refBuilder->get_widget("menu_quit", m_menuitem_quit);

    // get widget
    refBuilder->get_widget("btn1", m_btn1);
    refBuilder->get_widget("edit1", m_edit1);
    refBuilder->get_widget("chk_use_timer", m_chk_use_timer);
    refBuilder->get_widget("spin_delay_time", m_spin_delay_time);

    // connect menu signals
    m_menuitem_quit->signal_activate().connect(
        sigc::mem_fun(*this, &MainWindow::on_click_quit) );

    // button signals
    m_btn1->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn1_clicked));

    // set spin button
    m_spin_delay_time->set_range(1.0, 10.0);
    m_spin_delay_time->set_increments(1.0,3.0);
    m_spin_delay_time->set_value(3.0);

    m_status_bar->push("ready", 2);
}
…

 今までさんざんやってきたことなので、詳しい説明は必要ないですね。

1) ステータスバー

 最初に説明したように、今回は glade でステータスバーを設置していないので、ステータスバーを作成し、ウィンドウにパックしてます。
 テストサンプルなので、フォントの色とサイズの変更をしています。

(1) new Gtk::Statusbar; でステータスバーを作成

(2) メッセージ表示色を変更する場合

 m_status_bar->get_message_area(); でステータスバーの表示エリアを取得します。
 override_color();override_font(); を使って、フォントカラーとフォントを指定します。

(3) ウィンドウに表示する

 pack_start(); を使って、ウィンドウにどうのようにパッキングするか指定します。
 show(); で作成したステータスバーを表示します。

2) スピンボタン

 Qt と同じです。
 set_range(); で下限上限を設定します。
 set_increments(); でインクリメント値とページのインクリメント値を設定します。
 set_value(); で初期値を設定します。


D. ステータスバーについて

 ステータスバーへのメッセージはプッシュされ、メッセージスタックにポップされます。
 テキストがプッシュされると、古い内容が置き換えられ、古いテキストはポップ時に復元されます。
 メッセージはコンテキストID単位で管理されることに注意してください。

 以下によく使うであろう関数を説明します。

1) get_context_id
 guint Gtk::Statusbar::get_context_id (
   const Glib::ustring & context_description )

 実際のコンテキストの記述があれば、新しいコンテキスト識別子を返します。


2) push
 guint Gtk::Statusbar::push (
   const Glib::ustring & text,
   guint context_id = 0 )

 新しいメッセージをステータスバーの指定されたコンテキストIDのスタックにプッシュします。

3) pop
 void Gtk::Statusbar::pop (
   guint context_id = 0 )

 指定されたコンテキストIDのスタック内の最初のメッセージを削除します。
 スタックの最上部にあるメッセージが異なるコンテキストIDを持つ場合、表示されたメッセージは変更されません。

4) remove_message
 void Gtk::Statusbar::remove_message (
   guint message_id,
   guint context_id = 0 )

 ステータスバーの指定されたコンテキストIDのスタックからメッセージIDのメッセージを強制的に削除します。

5) remove_all_messages
 void Gtk::Statusbar::remove_all_messages (
   guint context_id = 0 )

 ステータスバーの指定されたコンテキストIDのスタックからメッセージを強制的に削除します。


以上、簡単でしたね!


最後に、全てのファイルを圧縮したファイル(zip)を載せます。

●ソース一式

www.mediafire.com

GTKプログラミングを学習するなら!

Gtk+3入門

Gtk+3入門

GTK+・GDKによるLinuxアプリケーション開発 (New riders)

GTK+・GDKによるLinuxアプリケーション開発 (New riders)

Learn GTK# Programming

Learn GTK# Programming

注目記事

「Amazon.co.jpアソシエイト」または「[乙の名称を挿入]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。