Auto size (stretch) last column of a wxGrid

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
iwbnwif
Super wx Problem Solver
Super wx Problem Solver
Posts: 274
Joined: Tue Mar 19, 2013 8:52 pm

Auto size (stretch) last column of a wxGrid

Post by iwbnwif » Mon Jun 01, 2015 8:32 pm

One of the nice features of a wxDataViewCtrl and its derivatives is that the last column automatically resizes so that there is no blank space.

Unfortunately the wxGrid doesn't have a similar feature. Whilst this is somewhat understandable because the intended use of wxGrid is not really to display a list of data, it is a very flexible control and implements some features (notably displaying tooltips on cell hovering) that are useful for lists.

The following is a simple way of stretching the last column of a wxGrid to fill the full width.

I have only been able to test it so far on wxGTK (Ubuntu 14.04) and welcome any improvements, in particular the bind / unbind calls. There are also a few oddities, such as it doesn't always size properly on first creation and it will probably try to unhide the last column if it is hidden.

StretchGrid.h

Code: Select all

#include <wx/grid.h>

class StretchGrid : public wxGrid
{
public:
    StretchGrid (wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
	       long style = wxWANTS_CHARS, const wxString& name = wxGridNameStr);
    ~StretchGrid ();
    
protected:
    void OnGridWindowSize (wxSizeEvent& event);
    void OnColHeaderSize (wxGridSizeEvent& event);
    void AutoSizeLastCol ();
};
StretchGrid.cpp

Code: Select all

StretchGrid::StretchGrid (wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) :
			wxGrid (parent, id, pos, size, style, name)
{
    GetGridWindow()->Bind (wxEVT_SIZE, &StretchGrid::OnGridWindowSize, this);
    Bind (wxEVT_GRID_COL_SIZE, &StretchGrid::OnColHeaderSize, this);
}

StretchGrid::~StretchGrid()
{
    GetGridWindow()->Unbind (wxEVT_SIZE, &StretchGrid::OnGridWindowSize, this);
    Unbind (wxEVT_GRID_COL_SIZE, &StretchGrid::OnColHeaderSize, this);
}

void StretchGrid::OnGridWindowSize (wxSizeEvent& event)
{
    if (GetNumberCols() > 0)
        AutoSizeLastCol ();
}

void StretchGrid::OnColHeaderSize (wxGridSizeEvent& event)
{
    if (GetNumberCols() > 0)
        AutoSizeLastCol ();
}

void StretchGrid::AutoSizeLastCol ()
{
    int colWidths = 0;
    
    for (int i = 0; i < GetNumberCols() - 1; i++)
        colWidths += GetColWidth (i);
    
    int finalColWidth = GetGridWindow()->GetSize().x - colWidths;
    
    if (finalColWidth > 80)
        SetColSize (GetNumberCols() - 1, finalColWidth);
    else
        SetColSize (GetNumberCols() - 1, 80);
}
wxWidgets 3.1.2, MinGW64 8.1.0, g++ 8.1.0, Ubuntu 19.04, Windows 10, CodeLite + wxCrafter
Some people, when confronted with a GUI problem, think "I know, I'll use Eclipse RCP". Now they have two problems.

User avatar
Asimov
Earned some good credits
Earned some good credits
Posts: 144
Joined: Tue Nov 17, 2020 6:43 pm

Re: Auto size (stretch) last column of a wxGrid

Post by Asimov » Tue Dec 15, 2020 10:24 am

Hi iwbnwif,
Thankyou for your code. I needed my wxGrid to stretch also, and I used your code as a basis for mine. My only problem was that I had a hidden column and your code would unhide my column, so I had to make a few adjustments, Like I had to set my max columns 1 (as I only had 2 columns and 1 hidden column at the end), and so here is how I adjusted your code to work for me.

Code: Select all

  int colWidths = 0;
  int myCol=1;
    for (int i = 0; i < myCol - 1; i++)
        colWidths += GetColWidth (i);
    int finalColWidth = GetGridWindow()->GetSize().x - colWidths;
    finalColWidth=finalColWidth-155;// Remove hidden column width.
    std::cout << finalColWidth << std::endl;
    if (finalColWidth > 80)
        SetColSize (myCol , (finalColWidth));
    else
        SetColSize (myCol , 80);
Now this worked, but because I only had two columns, it looked odd to have a really long right column and a really short left, and so I decided to work my wxGrid into percentages. I have also given my first column a minimum value that it can go down to as well, and if it hits that minimum then it sets the right hand column to fill in the rest. I suppose with a bit more work I could make this work for more columns too, but I only need two columns in my app,
Thank you.

Code: Select all

void tameMywxGrid::AutoSizeLastCol ()
{
    int panelWidth = GetGridWindow()->GetSize().x;
    SetColSize(0,getPercentage(panelWidth,30));
    SetColSize(1,getPercentage(panelWidth,70));
    int firstColMinWidth=140;
    int secondColWidth = panelWidth-firstColMinWidth;
    if(getPercentage(panelWidth,30) < firstColMinWidth)
    {
        SetColSize(0,firstColMinWidth);
        if(secondColWidth>0) SetColSize(1,secondColWidth);
    }
}

int tameMywxGrid::getPercentage(int number,int percent)
{
    return (number / 100.0) * percent;
}
Attachments
stretch.jpg
stretch.jpg (43.83 KiB) Viewed 1588 times

Post Reply