How to create a multicolumn table using virtual wxListCtrl

How to create a multicolumn table using virtual wxListCtrl

 

Yuriy Pigovsky,
Ternopil, Ukraine, pigovsky@gmail.com

 

This tutorial describes how to create and use a multicolumn wxListCtrl in a model-view-controller fashion using wxLC_VIRTUAL style. The example was implemented as a simple program, which collects information about movies.

The data model is a collection of Movie objects, which are collected in a singleton class AllMovies. The AllMovies class provides content for the MovieTableViewer, which is derived from wxListCtrl.

First part “Designing GUI in wxDev-C++” guides a novice through process of designing of a simple form with wxListCtrl, four static labels, text boxes and a button.

Second part “Implementation of a multicolumn table using virtual wxListCtrl” will guide a reader through creation of model and viewer classes. Resulting application will be able to add information about a movie to the multicolumn table when the button is pressed.

 

Table of content

Designing GUI in wxDev-C++

Implementation of a multicolumn table using virtual wxListCtrl

 

 

Designing GUI in wxDev-C++

If not installed, then install wxDev-C++. It can be installed under regular user account, i.e. without administrative privilegies. These instructions were prepared for wxDev-C++ build 7.3.1.3.

The wxDev-C++ is fine, free C++ IDE with GUI designer. It is suitable for industrial use to produce both commercial and free software. So it is good idea to get practical skills using it.

Execute wxDev-C++ (in Windows click Start->All programs-> wxDev-C++-> wxDev-C++). After several preparing steps you will obtain the main window of wxDev-C++

 

Create new project clicking File->New->Project… as in picture below

 

In the window, which will appear select wxWidgets Frame as the type of the project and enter its name “Movie Catalogue by <Your surname>” as in

 

Click OK.

 

In the file save dialog create new folder for your project. Remember, that this folder must be in proper place, because all the project files will be there.

 

Click “Save” and you will obtain a dialog

 

leave everything untouched and click Create.

The main window will look something like

 

If you can’t see Components window than go to “View->Show Plugin Panels”, uncheck and check again both Show property inspector and show component palette as in figure

 

Look for wxListCtrl component under Common Controls branch of the Component Palette:

 

Select it and move the mouse pointer into GUI designer area, click there and you will obtain something like

 

Rename the component using property inspector window

 

changing  property from “WxListCtrl1” to “moviesTable”: . Push “Enter” and changes will take effect.

Increase the size of designed window area dragging its rightmost side to obtain something that looks like

 

Right-click on an empty area of the designed window and select Align->To Grid:

it will facilitate you resizing and moving the components over the window area during design.

Move the “moviesTable” component and increase its size to obtain

Add four wxStaticText components to the right side of the designed window

 

to have following picture

 

 

Change their “Label” properties in the Property inspector

 

to “Movie name”, “Genre”, “Actors” and “Rating” to have next picture

 

Add four wxEdit components near the labels as in picture

 

Rename them to editName, editGenre, editActors and editRating changing their 'name' property in the Property inspector. Their label properties will be changed as well, so as the result you can see the following

 

Below all the components in the right side of the designed window, place a button control wxButton as in picture

 

Change its size, positions, label and name (using property inspector) to “Add new movie” and “AddNewMovie”:

 

 

Select the table component at the left of the designed window and look for its Columns property:

 

Click on “…” sign at the right of “Edit Columns” text. You will obtain the following dialog

Place the cursor to the field at the right of “Caption:” label and type: “Name”, then click “Add” button at the left side of the dialog window

 

Appearance of the dialog window will be updated to

 

Do the same adding the rest of columns to obtain following picture

 

Finally click OK closing the dialog.

 

Designed window will be updated as well

 

Try to run the application clicking  at the top of the IDE window or pressing the <F8> key.

Following window will appear showing you the process of compilation

 

After a while you will receive the following confirmation dialog:

 

Click “Yes” and wait again till compilation will be done. Finally you should be able to see something like

 

But interaction with any control including the “Add new movie” button will have no useful effect. To make the program useful you must do some hand typing work during implementation of the second part of this tutorial.

 


Implementation of a multicolumn table using virtual wxListCtrl

Double-click on “Add new movie” component at the designer’s area

 

and you will be placed to code editor

 

Change combos at the top of the window to “Movie_Catalogue_by_<Your surname>Frm” and “CreateGUIControls()” as follows

 

Find and cut to clipboard following text:

new wxListCtrl(this, ID_MOVIESTABLE, wxPoint(4, 4), wxSize(414, 297), wxLC_REPORT, wxDefaultValidator, wxT("moviesTable"));

     moviesTable- >InsertColumn(0,wxT("Rating"),wxLIST_FORMAT_LEFT,50 );

     moviesTable- >InsertColumn(0,wxT("Actors"),wxLIST_FORMAT_LEFT,50 );

     moviesTable- >InsertColumn(0,wxT("Genre"),wxLIST_FORMAT_LEFT,50 );

     moviesTable- >InsertColumn(0,wxT("Name"),wxLIST_FORMAT_LEFT,50 );

 

changing the window appearance from

 

to

 

 

Create new file pressing <Ctrl>+<N> and attach it to current project answering “Yes” to the following dialogue

Paste the content of clipboard to the newly created window as in example

 

Save the file pressing <Ctrl>+<S> and typing “MovieTableViewer.h” as the name of it.

 

Modify the text as follows

#include "AllMovies.h"

#include <wx/listctrl.h>

 

#ifndef __MOVIE_TABLE_VIEWER_H__

#define __MOVIE_TABLE_VIEWER_H__

 

class MovieTableViewer : public wxListCtrl{

 

protected:

    // return the text for the given column of the given item

    virtual wxString OnGetItemText(long item, long column) const{

        return AllMovies::getInstance()->get(item)->getAllPropertiesAsOneRow()[column];

    }

 

public:MovieTableViewer (wxFrame* frm, long id):

        wxListCtrl(frm, id, wxPoint(4, 4), wxSize(414, 297), wxLC_REPORT | wxLC_VIRTUAL, wxDefaultValidator, wxT("moviesTable"))

    {

        InsertColumn(0,wxT("Rating"),wxLIST_FORMAT_LEFT,50 );

        InsertColumn(0,wxT("Actors"),wxLIST_FORMAT_LEFT,50 );

        InsertColumn(0,wxT("Genre"),wxLIST_FORMAT_LEFT,50 );

        InsertColumn(0,wxT("Name"),wxLIST_FORMAT_LEFT,50 );       

    }

};

#endif

 

Be careful when writing method signatures, because if you will loose some of keywords declaring OnGetItemText, the overriding of the virtual method won’t work and the table will be permanently empty.

Preprocessing keywords #ifndef, #define and finally #endif are vital for compilation avoiding double declaration of the class.

 

Create new file <Ctrl>+<N> attached to the project and write

#include <vector>

#include "Movie.h"

 

#ifndef __ALL_MOVIES_H__

#define __ALL_MOVIES_H__

 

using namespace std;

 

class AllMovies {

    private:

        vector<Movie*> moviesCollection;

        static AllMovies* instance ;

        AllMovies(){}

   

    public:

        static AllMovies* getInstance(){

            if (instance == NULL)

                instance = new AllMovies;

            return instance;

        }

       

        void add(Movie* m){           

            moviesCollection.push_back(m);

        }

        Movie* get(long i){

            return moviesCollection[i];

        }

        long size(){

            return moviesCollection.size();

        }

};

 

#endif

Save it under “AllMovies.h”.

 

The same way create file “Movie.h” with following content:

#include <wx/wx.h>

 

class Movie{

    private:

        wxString name,

                actors,

                genre;

        float rating;

       

    public:

        wxString* getAllPropertiesAsOneRow(){

            wxString* r = new wxString[4];

            r[0]=name;

            r[1]=genre;

            r[2]=actors;

            r[3]<< rating;

            return r;

        }

       

        Movie(wxString n, wxString a, wxString g, float r){

            name = n;

            actors = a;

            genre = g;

            rating = r;

        }

           

};

 

Go to AddNewMovieClick method setting combos to

 at the top of the IDE window.

Modify it as follows

void Movie_Catalogue_by_PigovskyFrm::AddNewMovieClick(wxCommandEvent& event)

{

     // insert your code here

     double d;

     editRating->GetValue().ToDouble(&d);

     Movie * m = new Movie(editName->GetValue(), editActors->GetValue(), editGenre->GetValue(), d);

     AllMovies::getInstance()->add(m);

     moviesTable->SetItemCount(AllMovies::getInstance()- >size());

}

 

The call to SetItemCount is necessary to view virtual wxListCtrl list, without this call list will remain empty.

 

Go to CreateGUIControls() setting combos to

 

 

look for line “moviesTable =”, which we left unready, and change it to

 

moviesTable = new MovieTableViewer(this, ID_MOVIESTABLE);

 

Go to the top of the file and add include directive as follows

///-------------------------------------------------------------- ---

///

/// @file      Movie Catalogue by PigovskyFrm.cpp

/// @author    yp

/// Created:   05.09.2011 9:11:41

/// @section   DESCRIPTION

///            Movie_Catalogue_by_PigovskyFrm class implementation

///

///-------------------------------------------------------------- ----

 

#include "MovieTableViewer.h"

#include "Movie Catalogue by PigovskyFrm.h"

 

Create new source file pressing <Ctrl>+<N>, attach it to current project and type there:

#include "AllMovies.h"

AllMovies* AllMovies::instance = NULL;

 

Save the file as “AllMovies.cpp”.

Try to compile project pressing at  or <F8>. Now you should be able to add information about movies:


Conclusion. We have created a simple program, that displays our data in a multicolumn table.