C++ Gtkmm Tutorial 5

13 January , 2014 bill C++ Programming

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.

callback, gui, how to, linux, programming,

8 Responses to “C++ Gtkmm Tutorial 5”


Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Powered by WordPress. Designed by elogi.