wxGrid: как разместить внешнее окно вокруг маленькой сетки?

Сводка: я не знаю, как установить размеры главного окна, чтобы полосы прокрутки не использовались вокруг wxGrid без изменения ширины столбцов по умолчанию.

Я хочу написать простое приложение, в котором пользователь может видеть ограниченное количество чисел, и она может внести исправления в некоторые из них и сохранить новый контент. Приложение должно быть своего рода минималистичным. Количество строк и ячеек достаточно мало, чтобы поместиться в окне без использования полос прокрутки. Вот упрощенный код:

wxGrid *grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
grid->CreateGrid(21, 12);

// Setting the column labels and filling the grid with some numbers.

grid->Fit();

Там будет какая-то кнопка под сеткой. На данный момент единственный sizer содержит единственный элемент управления - сетку:

wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
topSizer->Add(grid, 1, wxEXPAND);
SetSizer(topSizer);

Код помещается в конструктор моего AppFrame учебный класс. Наконец, я называю следующее:

topSizer->Fit(this);
topSizer->SetSizeHints(this);

Это делает почти точно то, что мне нужно, но некоторые столбцы имеют более длинные метки и Fit изменяет ширину столбцов. Это не приятно визуально. Что я должен позвонить вместо Fit получить тот же эффект, но без изменения одинаковой ширины столбца?

Обновление: На самом деле, я не заметил ранее, что также grid->Fit(); был вызван в моем коде (теперь добавлен в приведенный выше пример). После его удаления сетка не устанавливает внутренние размеры, и окно очень маленькое (даже верхнее левое угловое окно не полностью видно по высоте и только немного больше, чем по ширине. Затем я добавил также SetColSize для каждого столбца (в том же месте, где я устанавливаю формат для столбцов):

for (int i = 0; i < 12; ++i)
{
    grid->SetColSize(i, WXGRID_DEFAULT_COL_WIDTH);
    grid->SetColFormatFloat(i, -1, 3);
}

Это не помогло, и окно меньше, чем хотелось. Итак, вопрос, вероятно, следует перефразировать: как заполненная сетка может захватывать свои собственные измерения, чтобы сообщать их внешней оболочке?

Обновление 2: все равно не работает. Полный код конструктора. (Я знаю, где-то между креслом и клавиатурой...:) Лично я считаю немного грязный код (по крайней мере, для магических чисел) - возможно, убранный позже:

AppFrame::AppFrame() :
    wxFrame(NULL, wxID_ANY, "Month rates of Euro")
{
    InitDefaultRates();

    wxGrid *grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);

    // Fixed grid for 12 months (columns) and the years 2000 to 2020 (rows).
    //
    grid->CreateGrid(21, 12);

    grid->BeginBatch();

    // Set the column labes (in Czech -- to lazy to translate).
    //
    grid->SetColLabelValue(0,  "leden");
    grid->SetColLabelValue(1,  "únor");
    grid->SetColLabelValue(2,  "březen");
    grid->SetColLabelValue(3,  "duben");
    grid->SetColLabelValue(4,  "květen");
    grid->SetColLabelValue(5,  "červen");
    grid->SetColLabelValue(6,  "červenec");
    grid->SetColLabelValue(7,  "srpen");
    grid->SetColLabelValue(8,  "září");
    grid->SetColLabelValue(9,  "říjen");
    grid->SetColLabelValue(10, "listopad");
    grid->SetColLabelValue(11, "prosinec");

    // Float with 3 decimal places for each of the columns.
    //
    for (int i = 0; i < 12; ++i)
    {
        grid->SetColFormatFloat(i, -1, 3);
    }

    // Filling with the default values calculated from 
    // http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.zip.
    // Index zero is for the year 2000.
    //
    for (int year = 0; year < 21; ++year)
    {
        ostringstream oss;
        oss << 2000 + year;
        grid->SetRowLabelValue(year, oss.str().c_str());

        for (int month = 0; month < 12; ++month)
        {
            double default_value = default_rates[year][month];
            double value = default_value;

            oss.str("");
            oss << setprecision(3) << fixed << value;

            // Problem with decimal point separator. Replace the locale
            // comma by dot.
            //
            wxString s(oss.str().c_str());
            string::size_type pos = s.find_first_of('.');
            if (pos != string::npos)
                s[pos] = ',';

            grid->SetCellValue(year, month, s);

            if (value == 0.0)
                grid->SetCellTextColour(year, month, *wxLIGHT_GREY);
            else if (value == default_value)
                grid->SetCellTextColour(year, month, *wxBLUE);
        }
    }

    // Setting the initial size of the grid.
    //
    grid->SetInitialSize(grid->GetBestSize());

    // Vertical size will be the top one.
    //
    wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
    topSizer->Add(grid, 1, wxEXPAND);
    SetSizer(topSizer);

    // I do not understand this (could be a problem). From wxBook p. 196.
    //
    topSizer->Fit(this);
    topSizer->SetSizeHints(this);

    // Allow redraw.
    //
    grid->EndBatch();

    // Set cursor to the current month.
    //
    int year = wxDateTime::GetCurrentYear() - 2000;
    int month = wxDateTime::GetCurrentMonth();
    grid->GoToCell(year, month);
}

Спасибо за ваше время и опыт, Петр

1 ответ

Решение

Вот полная рабочая программа:

#include "wx/app.h"
#include "wx/frame.h"
#include "wx/grid.h"
#include "wx/datetime.h"

class MyFrame : public wxFrame
{
public:
    MyFrame()
        : wxFrame(NULL, wxID_ANY, "Chronological data")
    {
        wxGrid *grid = new wxGrid(this, wxID_ANY);
        grid->CreateGrid(21, 12);

        for ( wxDateTime::Month m = wxDateTime::Jan; m < wxDateTime::Inv_Month; wxNextMonth(m) )
        {
            grid->SetColLabelValue(m, wxDateTime::GetMonthName(m));
            for ( int y = 0; y < 21; y++ )
            grid->SetCellValue(y, m, wxString::Format("%.2f", (float)rand() / RAND_MAX));
        }

        grid->InvalidateBestSize();
        SetClientSize(grid->GetBestSize());
    }
};

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        (new MyFrame)->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

Обратите внимание, что для меня "сентябрь" не вписывается в ширину столбца по умолчанию, либо вызовите AutoSizeColumns() (но вам это не нравится) или просто равномерно увеличивайте ширину столбца.

Другие вопросы по тегам