Являются ли сайзеры хорошим способом работы с формой?

Я перемещаю свое приложение из старого графического интерфейса (где я использовал фиксированные размеры) в wxWidgets (где я пытаюсь изучить основы сайзеров).

Внутри приложения у меня есть несколько форм с довольно сложной структурой. Природа данных и рабочий процесс предлагают мне хранить все эти данные вместе на одном экране. Но этот экран должен быть правильно спроектирован, чтобы его можно было использовать.

Вот старая версия формы...

форма с исправленным макетом

... и вот более-менее, что я смог придумать с помощью сайзеров...

форма с wxSizers

Обратите внимание, что я не мог просто использовать wxGridSizer, так как некоторые виджеты охватывают всю строку, некоторые выходят за пределы фиксированной сетки и т. д.

Очевидно, я мог бы продолжать работать над этим, чтобы сделать его менее уродливым, но я поймал себя на мысли, что, возможно, сайзеры не являются правильным инструментом для этого. Чтобы достичь того, что я хочу, мне понадобится что-то похожее на wxGridSizer с каким-то механизмом colspan/rowspan, и, возможно, этого будет недостаточно.

Поэтому я начал думать о том, чтобы самостоятельно создать «Размер форм», который мог бы работать примерно так:

int w,h;
GetClientSize(&w,&h);
MyFormSizer *formSizer(w,h);
formSizer->SetDimension( widget1, 100, 20 );
formSizer->SetDimension( widget2, 500, 20 );
formSizer->newRow();
formSizer->SetDimension( widget3, 100, 20 );
formSizer->SetDimension( widget4, 250, 20 );
formSizer->SetDimension( widget5, 250, 20 );
formSizer->Layout();

Пользователь должен установить относительные размеры каждого виджета, чтобы полностью заблокировать геометрию формы. Чтобы сделать эту геометрию подходящей, wxPanel при изменении размера Layout() вычислит соответствующий коэффициент масштабирования f, а затем установит все размеры и позиции, выполнив что-то вроде

widget1->SetSize(CalculatedX, CalculatedY, 100/f, 20/f);
CalculatedX+=100/f;
widget2->SetSize(CalculatedX, CalculatedY, 500/f, 20/f);
CalculatedX+=0;
CalculatedY+=20/f;

и т. д. (это всего лишь царапина, примите это как грубую идею; должны быть механизмы, чтобы не делать все слишком маленьким, чтобы поместиться в текст в виджетах и ​​/ или соответствующим образом масштабировать размер шрифта и тому подобное).

Это кажется разумным? Как бы вы ответили на эту тему? Этот выбор во многом повлияет на мое будущее развитие, поэтому любые ответы, критика и комментарии будут очень кстати.


person dirluca    schedule 18.11.2014    source источник


Ответы (2)


wxGridSizer может не соответствовать вашим потребностям, но более гибкие классы, такие как wxGridBagSizer, должны делать то, что вам нужно. Этот класс позволяет вам устанавливать элементы для охвата нескольких строк и столбцов, устанавливая wxGBSpan при вызове wxGridBagSizer::Add.

person sjdowling    schedule 18.11.2014
comment
Супер! Мне немного стыдно, что я так и не нашел этого при просмотре и чтении, похоже, это действительно мое решение. Дайте мне немного, чтобы проверить, и я приму этот ответ. - person dirluca; 18.11.2014
comment
Я столкнулся с некоторыми трудностями при реализации того, что вы предложили, но я не могу сказать, что это из-за инструмента или из-за моего неуверенности в нем. А именно, у меня большие трудности с управлением шириной столбцов: они, как правило, одинаковы, даже если содержимое разное, и у меня нет параметра пропорции для работы с ними. wxSizer::SetItemMinSize() выполняет часть работы, но, например, у меня есть столбец, который содержит столбцы во всех строках, кроме одной, где у меня есть кнопка 20X20. Вы ожидаете, что он будет шириной 20 пикселей, вместо этого он такой же, как и у других столбцов. Я продолжаю тестировать! - person dirluca; 19.11.2014
comment
После еще нескольких тестов я решил принять ваш ответ. wxGridBagSizer не идеален, но, похоже, лучше всего подходит для моих нужд. - person dirluca; 21.11.2014

Как упоминалось в ответе @sjdowling, вы можете использовать wxGridBagSizer. Однако я не рекомендую использовать этот класс, поскольку он страдает от некоторых проблем с абсолютным позиционированием, в частности, из-за него очень сложно перемещать элементы вокруг него или добавлять их, кроме как в самом конце.

Это правда, что сайзеры wxWidgets не имеют возможности выравнивать элементы по разным размерам, а это то, что вам нужно, если вы используете обычные разместители блоков или сетки, и это раздражает. Однако вы можете обойти это, зафиксировав размеры столбцов явно, либо просто жестко запрограммировав их (пожалуйста, по крайней мере, используйте диалоговые единицы, а не пиксели, чтобы избежать неправильных макетов, особенно в ситуациях с высоким DPI), или путем итерации по всем метки и вызов GetTextExtent() для всех из них и выбор самого длинного (это намного надежнее, особенно при использовании переводов, которые могут резко изменить ширину строки в пикселях). Затем просто назначьте эту ширину созданным вами меткам: поскольку исходная ширина также является минимальной шириной, это гарантирует, что все они будут иметь эту ширину и, следовательно, будут выровнены, даже если они имеют разные размеры.

Как я уже писал, это несколько раздражает, но на самом деле не так уж плохо, если вы создаете макет в коде. Если вы делаете это в дизайнере графического интерфейса, это еще уродливее, но вы все равно можете вызывать wxSizer::SetItemMinSize() из кода. Конечно, единственным реальным решением было бы добавить поддержку межразмерного выравнивания, но пока это все же предпочтительнее использования wxGridBagSizer IMO.

person VZ.    schedule 18.11.2014
comment
Не знаю, я столкнулся с некоторыми трудностями при реализации того, что предложил @sjdowling, но я не могу сказать jet, если это из-за инструмента или из-за моего неуверенности в нем. Обратите внимание, что я не планирую использовать абсолютное позиционирование. То, что вы предлагаете, интересно, но похоже, что мне нужно создать оболочку сайзера (у меня около 30 форм, и я не хочу повторять процесс 30 раз) и наложить на нее столько ограничений, что я задаюсь вопросом, почему использовать сайзеры в этой ситуации - пожалуйста, не заносите меня в список людей, которые отчаянно хотят изобретать велосипед для этого :-) - person dirluca; 19.11.2014