C++ Gtkmm Tutorial 5

C++ Gtkmm Tutorial 5

8 Comments on C++ Gtkmm Tutorial 5

Introduction
In part 5 of this Gtkmm tutorial I will be showing you how to use the treeview control and markup in a label. In this simple application there is a text entry used for entering text into a treeview. The label next to the text entry will turn red if there is no text entered in the text entry when the button is pressed.

TreeView
The Gtk treeview control is a very powerful way of displaying data to the user. It can display data in a columned list or in groups known as a tree. You would have seen one in your file management application such as nautilus or dolphin. To create a treeview control you need to also create a tree model and define the model columns. In this tutorial I will be demonstrating a columned list. I will also be demonstrating how to dynamically add rows to the treeview at run time.

Markup
Adding markup to labels is quite simple and is achieved by setting the text using the set_markup() function of the label class. This will be demonstrated in the following code example.

The Code
You can edit the 3 files from tutorial 4.

main.cpp

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

int main(int argc, char *argv[])
{
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "com.gtkmm.tutorial5.base");

    mywindow window;

    return app->run(window);
}

mainwindow.h

class mywindow : public Gtk::Window
{
    public:
        mywindow();
        virtual ~mywindow();
        Gtk::TreeView *treeview;
        Gtk::Label *label;
        Gtk::Entry *text;
    protected:
        void on_quit_click();
        void on_button_click();

        class ModelColumns : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ModelColumns()
                { add(col_cnt); add(col_text); }

                Gtk::TreeModelColumn<int> col_cnt;
                Gtk::TreeModelColumn<Glib::ustring> col_text;
        };

        ModelColumns columns;
        Glib::RefPtr<Gtk::ListStore> refTreeModel;
        int rowcount = 0;
    private:
};

mainwindow.cpp

#include "mywindow.h"
#include <iostream>
mywindow::mywindow()
{
    set_default_size(400, 400);
    set_title("Tutorial 5");

    Gtk::Box *vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0));
    add(*vbox);

    Gtk::MenuBar *menubar = Gtk::manage(new Gtk::MenuBar());
    vbox->pack_start(*menubar, Gtk::PACK_SHRINK, 0);

    Gtk::MenuItem *menuitem_file = Gtk::manage(new Gtk::MenuItem("_File", true));
    menubar->append(*menuitem_file);
    Gtk::Menu *filemenu = Gtk::manage(new Gtk::Menu());
    menuitem_file->set_submenu(*filemenu);
    Gtk::MenuItem *menuitem_quit = Gtk::manage(new Gtk::MenuItem("_Quit", true));
    menuitem_quit->signal_activate().connect(sigc::mem_fun(*this, &mywindow::on_quit_click));
    filemenu->append(*menuitem_quit);

    Gtk::Grid *grid = Gtk::manage(new Gtk::Grid);
    grid->set_border_width(10);
    grid->set_row_spacing(5);
    vbox->add(*grid);

    Gtk::TreeView *treeview = Gtk::manage(new Gtk::TreeView);
    treeview->set_hexpand(true);
    treeview->set_vexpand(true);
    grid->attach(*treeview, 0, 0, 3, 1);

    refTreeModel = Gtk::ListStore::create(columns);
    treeview->set_model(refTreeModel);
    treeview->append_column("Cnt", columns.col_cnt);
    treeview->append_column("Text", columns.col_text);

    label = Gtk::manage(new Gtk::Label);
    label->set_markup("<b>Text To Add: </b>");
    grid->attach(*label, 0, 1, 1, 1);

    text = Gtk::manage(new Gtk::Entry);
    grid->attach(*text, 1, 1, 2, 1);

    Gtk::Button *button = Gtk::manage(new Gtk::Button("Add Text"));
    button->signal_clicked().connect(sigc::mem_fun(*this, &mywindow::on_button_click));
    grid->attach(*button, 2, 2, 1, 1);

    vbox->show_all();
}

mywindow::~mywindow()
{
//dtor
}

void mywindow::on_button_click()
{
    if(text->get_text_length() == 0)
        label->set_markup("<b><span color='red'>Text To Add: </span></b>");
    else
    {
        label->set_markup("<b><span color='black'>Text To Add: </span></b>");

        rowcount++;

        Gtk::TreeModel::Row row = *(refTreeModel->append());
        row[columns.col_cnt] = rowcount;
        row[columns.col_text] = text->get_text();
    }
}

void mywindow::on_quit_click()
{
    hide();
}

Gtkmm_Tutorial5_Img1Gtkmm_Tutorial5_Img2
The “Text To Add:” label turns red when the button is pressed with no text is entered.

Explaining The Code
In main.cpp nothing has really changed since tutorial 4.

In mywindow.h all of the controls and functions that need to be accessed globally are defined here which is not very different from previous tutorials. What is new in this file is the lines needed to define the treeview control. The treeview control itself is not defined in the header as there is no need keep the pointer to it after it is displayed.

        class ModelColumns : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ModelColumns()
                { add(col_cnt); add(col_text); }

                Gtk::TreeModelColumn<int> col_cnt;
                Gtk::TreeModelColumn<Glib::ustring> col_text;
        };

        ModelColumns columns;
        Glib::RefPtr<Gtk::ListStore> refTreeModel;

Above is the class that defines the columns used in the treeview, below the class is the columns object and the treemodel.

        int rowcount = 0;

This is the rowcount integer that is used to count the number of rows added to the treeview.

In mywindow.cpp the vbox menubar and grid is the same as in previous tutorials.

    Gtk::TreeView *treeview = Gtk::manage(new Gtk::TreeView);
    treeview->set_hexpand(true);
    treeview->set_vexpand(true);
    grid->attach(*treeview, 0, 0, 3, 1);

This code creates the treeview and expands it horizontally and vertically.

    refTreeModel = Gtk::ListStore::create(columns);
    treeview->set_model(refTreeModel);

This code creates the model and adds it to the treeview.

    treeview->append_column("Cnt", columns.col_cnt);
    treeview->append_column("Text", columns.col_text);

This code adds the columns to the treeview.

    label = Gtk::manage(new Gtk::Label);
    label->set_markup("<b>Text To Add: </b>");
    grid->attach(*label, 0, 1, 1, 1);

This code creates a label and adds markup to display the text as bold.

    if(text->get_text_length() == 0)
        label->set_markup("<b><span color='red'>Text To Add: </span></b>");
    else
    {
        label->set_markup("<b><span color='black'>Text To Add: </span></b>");

        rowcount++;

        Gtk::TreeModel::Row row = *(refTreeModel->append());
        row[columns.col_cnt] = rowcount;
        row[columns.col_text] = text->get_text();
    }

This code is called when the button is pressed. If the length of the text in the entry is 0 it changes the label text to bold and red. if the text length is not 0 it sets the text to bold and black in case it is red, adds 1 to the rowcount and adds a row to the treeview. It adds a row by appending a row and getting the pointer to it in “row” and than setting the values of the 2 columns. columns.col_cnt and columns.col_text is defined in the ModelColumns class.

To Come
We will be using what we have learnt to create a simple number guessing game and using the treeview to keep track of the guesses. I will also show you how to use a spin button to set the number of guesses and how many numbers to guess from.

About the author:

Bill Payne started working as a paid professional software developer at the young age of 12 years old developing simple games and other applications for pre-packaged computers. Bill has since developed software for many industries such as direct sales and the the stock market. Bill has now started sharing his many years of software development experience through a blog on the MPSHouse website and one on one lessons.

8 Comments

  1. Etadaferua  - 13 January , 2014 - 6:46 pm
    Reply /

    Very nice Best gtkmm tutorial on the internet !

  2. Filip  - 17 February , 2014 - 12:47 am
    Reply /

    Agree. Thank you very much

  3. Wilfred  - 24 April , 2014 - 3:29 am
    Reply /

    hello i using your tutorial and its very helpful :) I want ask some maybe simple question the next one :

    i want to make something like this :
    http://postimg.org/image/tidrm8tmx/

    so its changing content box
    which way i have to research to make this menu system i thinking about something like window in window

    • bill  - 24 April , 2014 - 9:08 am
      Reply /

      I think the Gtk NoteBook will do what you want. It you want it to look different you can re draw the tabs or even put close buttons on them.

  4. Joe W.  - 19 June , 2014 - 9:17 am
    Reply /

    How to change the color of the button text to red? I tried but couldn’t figure it out.

    • bill  - 19 June , 2014 - 6:50 pm
      Reply /

      Try using a GtkLabel as a child inside the button. You can change the color of that the same way I did in this tutorial.

      • Joe W.  - 20 June , 2014 - 8:42 am
        Reply /

        [Email Request by Joe W.]

        Can you post a tutorial that includes pop-up a child window? That is, if I clicked a button a new window come up with other widgets on it. I also tried to look your mentioned source code of Notebook, but there is no Makefile and seem the code style is different than your tutorial one. If there is a Makefile, I would like look into it.
        One more time Thank you for writing up these tutorials.

        • bill  - 20 June , 2014 - 8:43 am
          Reply /

          My tutorial series is starts (part 1) by teaching you how to set up Code::Blocks IDE for Gtkmm development. I only use Makefiles when doing cross platform development where there is 2 different GUI’s such as Gtk and Windows Forms. I then use make Windows or Make Linux. For development on 1 platform it is easier to just use an IDE that will take care of that for you such as Code::Blocks.

          I will try to find the time to find the time to make a tutorial with a popup window. I will put a button on the parent window and a label on the child (popup) window. I will change the color of the button text for you as well. I will try to do this today or on the weekend.

Leave a comment

Back to Top