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()
(но вам это не нравится) или просто равномерно увеличивайте ширину столбца.