Accueil > Linux / Logiciels Libres > Logiciels Libres > Programmation Gtk3/Gtkmm/Glade/Gtkbuilder avec Eclipse

Programmation Gtk3/Gtkmm/Glade/Gtkbuilder avec Eclipse

samedi 9 février 2013, par Yann

 Programme minuteur en Gtk3/Gtkmm/GtkBuilder

Retrouvez les explications complètes dans GNU/Linux Magazine France

http://www.ed-diamond.com/feuille_lmag159/index.html

Téléchargez la dernière version de ce programme qui se trouve sur GitHub master.zip

Un minuteur pour vous aidez à surveiller la cuisson de vos pâtes ou de vos œufs ;-).

 Archive du programme timer_gtkmm

Archive tar.gz
Projet Eclipse Juno de timer_gtkmm

 Intégration dans Eclipse

Décompressez l’archive dans votre « workspace » Eclipse.

tar xzf timer_gtkmm.tar.gz

Vous obtenez un répertoire timer_gtkmm. Lancer Eclispe, puis faites « File->Import->General->Existing Projects into Workspace », ensuite choisissez le répertoire « timer_gtkmm ». C’est terminé.

 Codes source du programme

Vue Glade de l’interface

Fichier XML de l’interface

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="xpad">5</property>
    <property name="stock">gtk-media-play</property>
  </object>
  <object class="GtkImage" id="image2">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="xpad">5</property>
    <property name="stock">gtk-media-stop</property>
  </object>
  <object class="GtkWindow" id="window_timer">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkBox" id="box3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkBox" id="box4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkLabel" id="label_set_hours">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Set Hours</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label_set_minute">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Set Minutes</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label_set_seconds">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Set Seconds</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="box5">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkSpinButton" id="spinbutton_hours">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="invisible_char">•</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkSpinButton" id="spinbutton_minutes">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="invisible_char">•</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkSpinButton" id="spinbutton_seconds">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="invisible_char">•</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox" id="box6">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkBox" id="box7">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkLabel" id="label_remain_hours">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Remaining Hours</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label_remain_minutes">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Remaining Minutes</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label_remaining_seconds">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes"> Remaining_seconds</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkEventBox" id="eventbox_labels">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkBox" id="box8">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <child>
                      <object class="GtkLabel" id="label_remain_hours_value">
                        <property name="height_request">80</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">00</property>
                        <attributes>
                          <attribute name="font-desc" value="Sans Bold 40"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="expand">True</property>
                        <property name="fill">True</property>
                        <property name="position">0</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="label_ddot">
                        <property name="height_request">80</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">:</property>
                        <attributes>
                          <attribute name="font-desc" value="Sans Bold 40"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">True</property>
                        <property name="position">1</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="label_remain_minutes_value">
                        <property name="height_request">80</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">00</property>
                        <attributes>
                          <attribute name="font-desc" value="Sans Bold 40"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="expand">True</property>
                        <property name="fill">True</property>
                        <property name="position">2</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="label_ddot1">
                        <property name="height_request">80</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">:</property>
                        <attributes>
                          <attribute name="font-desc" value="Sans Bold 40"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">True</property>
                        <property name="position">3</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="label_remain_seconds_value">
                        <property name="height_request">80</property>
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">00</property>
                        <attributes>
                          <attribute name="font-desc" value="Sans Bold 40"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="expand">True</property>
                        <property name="fill">True</property>
                        <property name="position">4</property>
                      </packing>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox" id="box2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkButton" id="button_start">
                <property name="label" translatable="yes">Start</property>
                <property name="use_action_appearance">False</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_action_appearance">False</property>
                <property name="image">image1</property>
                <property name="image_position">right</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="button_stop">
                <property name="label" translatable="yes">Stop</property>
                <property name="use_action_appearance">False</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_action_appearance">False</property>
                <property name="image">image2</property>
                <property name="image_position">right</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkStatusbar" id="statusbar_timer">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <property name="spacing">2</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">3</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Classe Timer
Fichier entête classe Timer.h

/*
 ============================================================================
 Name        : Timer.h
 Author      : Yann
 Version     :
 Copyright   : Your copyright notice
 Description : Simpler timer in gttkmm Header class file
 ============================================================================
 */
#ifndef GTKMM_TIMER_H
#define GTKMM_TIMER_H

#include <gtkmm.h>
#include <iostream>
#include <map>

class Timer : public Gtk::Window
{
public:
  Timer();
  Gtk::Window * GetMainWindow();

protected:
  // signal handlers
  bool on_window_timer_destroy_cb(GdkEventAny * event);
  void on_Button_Timer_Start_release_cb();
  void on_Button_Timer_Stop_release_cb();
  bool on_timeout();

  // Member data:
  Glib::RefPtr<Gtk::Builder> m_refBuilder;
  Gtk::Window *m_window_timer;
  Gtk::Button *m_Button_Timer_Start, *m_Button_Timer_Stop;
  Gtk::SpinButton * m_spinbutton_hours, * m_spinbutton_minutes, * m_spinbutton_seconds;
  Gtk::Label * m_label_hours, * m_label_minutes, *m_label_seconds;
  Gtk::EventBox * m_eventbox_labels;
  Glib::RefPtr<Gtk::Adjustment> m_spinbutton_hours_adj, m_spinbutton_minutes_adj,m_spinbutton_seconds_adj;
  // Keep track of the timer added
  sigc::connection m_connection_id_timeout;
  //current values
  gint m_hours, m_minutes, m_seconds;
};

#endif // GTKMM_TIMER_H

Fichier classe Timer.cc

/*
 ============================================================================
 Name        : Timer.cc
 Author      : Yann
 Version     :
 Copyright   : Your copyright notice
 Description : Simpler timer in gttkmm class file
 ============================================================================
 */
#include "Timer.h"
#include <iomanip>

using namespace std;

Timer::Timer() :
m_spinbutton_hours_adj( Gtk::Adjustment::create(0.0, 0.0, 23.0, 1.0, 5.0, 0.0)),
m_spinbutton_minutes_adj( Gtk::Adjustment::create(0.0, 0.0, 59.0, 1.0, 5.0, 0.0)),
m_spinbutton_seconds_adj( Gtk::Adjustment::create(0.0, 0.0, 59.0, 1.0, 5.0, 0.0))
{

	  //Load the GtkBuilder file and instantiate its widgets:
	  m_refBuilder = Gtk::Builder::create();
	  try
	  {
	    m_refBuilder->add_from_file("/home/yann/gtk_workspace/timer_gtkmm/src/timer.glade");
	  }
	  catch(const Glib::FileError& ex)
	  {
	    std::cerr << "FileError: " << ex.what() << std::endl;
	  }
	  catch(const Glib::MarkupError& ex)
	  {
	    std::cerr << "MarkupError: " << ex.what() << std::endl;
	  }
	  catch(const Gtk::BuilderError& ex)
	  {
	    std::cerr << "BuilderError: " << ex.what() << std::endl;
	  }

	  //Get the GtkBuilder-instantiated Dialog:
	  m_refBuilder->get_widget("window_timer", m_window_timer);
	  if(m_window_timer)
	  {
		  m_window_timer->signal_delete_event().connect(sigc::mem_fun(*this,&Timer::on_window_timer_destroy_cb));
	  }

	  m_refBuilder->get_widget("button_start", m_Button_Timer_Start);
	  if(m_Button_Timer_Start)
	  {
		  m_Button_Timer_Start->signal_released().connect(sigc::mem_fun(*this,&Timer::on_Button_Timer_Start_release_cb));

	  }

	  m_refBuilder->get_widget("button_stop", m_Button_Timer_Stop);
	  if(m_Button_Timer_Stop)
	  {
		  m_Button_Timer_Stop->signal_released().connect(sigc::mem_fun(*this,&Timer::on_Button_Timer_Stop_release_cb));

	  }

	  m_refBuilder->get_widget("spinbutton_hours", m_spinbutton_hours);
		if(m_spinbutton_hours)
		{
			m_spinbutton_hours->configure(m_spinbutton_hours_adj,1.0,0);
		}
	  m_refBuilder->get_widget("spinbutton_minutes", m_spinbutton_minutes);
		if(m_spinbutton_minutes)
		{
			m_spinbutton_minutes->configure(m_spinbutton_minutes_adj,1.0,0);
		}
	  m_refBuilder->get_widget("spinbutton_seconds", m_spinbutton_seconds);
		if(m_spinbutton_seconds)
		{
			m_spinbutton_seconds->configure(m_spinbutton_seconds_adj,1.0,0);
		}
	  m_refBuilder->get_widget("label_remain_hours_value", m_label_hours);
	  m_refBuilder->get_widget("label_remain_minutes_value", m_label_minutes);
	  m_refBuilder->get_widget("label_remain_seconds_value", m_label_seconds);
	  m_refBuilder->get_widget("eventbox_labels", m_eventbox_labels);

}

bool Timer::on_window_timer_destroy_cb(GdkEventAny * event)
{
	m_window_timer->hide();
	std::cout << "Hello on_window_timer_destroy_cb" << std::endl;
	return true;
}

void Timer::on_Button_Timer_Start_release_cb()
{
	//todo
	std::cout << "Hello on_Button_Timer_Start_release_cb" << std::endl;
	m_hours = m_spinbutton_hours->get_value();
	m_minutes = m_spinbutton_minutes->get_value();
	m_seconds = m_spinbutton_seconds->get_value();
	std::cout << m_hours << ":" << m_minutes << ":" << m_seconds << std::endl;

//	// need iomanip cf. https://github.com/vickenty/tomator/blob/master/states.cc
//	m_label_hours->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_hours));
//	m_label_minutes->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_minutes));
//	m_label_seconds->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_seconds));
	//http://developer.gnome.org/gtk3/3.0/gtk-question-index.html
	m_eventbox_labels->override_background_color(Gdk::RGBA("green"));

	//Add a timer callback to update the values
	//http://developer.gnome.org/gtkmm-tutorial/3.3/sec-timeouts.html.en
	m_connection_id_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Timer::on_timeout), 1000 );

}

void Timer::on_Button_Timer_Stop_release_cb()
{
	std::cout << "Hello on_Button_Timer_Stop_release_cb" << std::endl;
	//http://developer.gnome.org/gtkmm-tutorial/3.3/sec-timeouts.html.en
	m_connection_id_timeout.disconnect();
}

bool Timer::on_timeout()
{
	m_label_seconds->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_seconds));
	m_label_minutes->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_minutes));
	m_label_hours->set_text(Glib::ustring::format(setfill(L'0'), std::setw(2), m_hours));
	// time management
	m_seconds --;
	if (m_seconds<0)
	{
		m_seconds=59;
		m_minutes --;
		if (m_minutes < 0)
		{
			m_minutes = 59;
			m_hours --;
			if (m_hours < 0)
			{
				m_connection_id_timeout.disconnect();
				std::cout << "Hello m_connection_id_timeout.disconnect" << std::endl;
				//http://developer.gnome.org/gtk3/3.0/gtk-question-index.html
				m_eventbox_labels->override_background_color(Gdk::RGBA("red"));

			}
		}
	}

  //As this is a timeout function, return true so that it
  //continues to get called
  return true;
}

Gtk::Window* Timer::GetMainWindow()
{
	return this->m_window_timer;
}

Programme principal

Fichier programme principal timer_gtkmm.cc

/*
 ============================================================================
 Name        : timer_gtkmm.cc
 Author      : Yann
 Version     :
 Copyright   : Your copyright notice
 Description : Simpler timer in gttkmm
 ============================================================================
 */

#include "Timer.h"
#include <gtkmm.h>

int main (int argc, char *argv[])
{
	  Gtk::Main kit(argc, argv);

	  Timer timer;
	  Gtk::Window * win = timer.GetMainWindow();
	  //Shows the window and returns when it is closed.
	  Gtk::Main::run((*win));
}