Wiki

Мультистраничные Диалоги

Jasmin Blanchette

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

QTabWidget с Автоматическим Изменением размеров

Стандартный способ представлять много информации в одном окне состоит в том, чтобы использовать QTabWidget. Большинство пользователей знакомо с диалогами вкладок, и нет, вероятно, никакого более лучшего способа скрыть дополнительные параметры от случайных пользователей.

По умолчанию, QTabWidget::minimumSizeHint() возвращает максимальный размер всех существующих страниц, а не только видимой страницы. Например, в диалоге "Find & Replace", приведённом ниже, страница "Replace" задаёт размер целого диалога:

Find-Wrong

Когда экранное пространство ограничено, возможно, было бы предпочтительнее для диалога изменить свои размеры автоматически, чтобы занять как можно меньше места:

Find-Right

Qt требует довольно небольшого кода, чтобы осуществить автоматическое изменение размеров. Сначала нам необходимо "ignored" и "preferred" размер стратегии на некоторое время, так что давайте сразу объявим, их как глобальные константы:

const QSizePolicy ignored(QSizePolicy::Ignored, QSizePolicy::Ignored);
const QSizePolicy preferred(QSizePolicy::Preferred, QSizePolicy::Preferred);

Затем мы реализуем слот currentChanged() в нашем диалоге и подключаем его к сигналу currentChanged() объекта класса QTabWidget:

void FindDialog::currentChanged(QWidget *newPage)
{
  if (newPage == pageFind) {
      pageFind->setSizePolicy(preferred);
      pageReplace->setSizePolicy(ignored);
  } else {
      pageFind->setSizePolicy(ignored);
      pageReplace->setSizePolicy(preferred);
  }
  layout()->activate();
  setFixedSize(minimumSizeHint());
}

Если новая страница "Find", мы устанавливаем размер её стратегии в "Preferred", а размер стратегии "Replace" в "Ignored"; иначе делаем наоборот. Устанавливая размер скрытой стратегии в "ignored", мы гарантируем, что скрытая страница не участвует в формировании минимально рекомендуемого размера QTabWidget.

В конце функции, мы вызываем QLayout::activate(), чтобы повторно вычислить расположение, и устанавливаем размер приложения в минимально рекомендуемый размер. Минимально рекомендуемый размер управляемого расположения приложения вычислен расположением; без вызова QLayout::activate(), minimumSizeHint() возвратил бы значение, основанное на предварительно показанной странице.

Другим подходом к подклассу QTabWidget и повторному осуществлению minimumSizeHint(), может быть уклонение от манипуляций со страничным размером стратегии. Это - вероятно лучший подход, если Вы часто нуждаетесь в многостраничных диалогах. Вы могли бы тогда сделать ваш подкласс, как специфическое дополнение к приложению, чтобы спокойно использовать его в Qt Designer.

LayoutHint и updateGeometry()

Всякий раз, когда стратегия размера приложения, рекомендуемый размер или минимально рекомендуемый размер изменяется, приложение непосредственно вызывает QWidget::updateGeometry(), который посылает событие LayoutHint в исходное приложение. QLayout ловит такие события и непосредственно вызывает activate(). Все это происходит автоматически, так что мы не должны думать об этом.

В нашем примере FindDialog, приведённом выше, мы явно вызывали activate(), потому что мы хотели, чтобы размещение непосредственно вычисляло себя. Мы, возможно, достигнем того же самого результата, вызывая QApplication::sendPostedEvents(0, QEvent:: LayoutHint),гарантирующее, что события LayoutHint непосредственно обработаны и что activate() вызван.

QWidgetStack с Кнопками

Ещё одна проблема изменения размеров, расмотренная выше, происходит при подключении управляемого кнопкой QWidgetStack. Приложение объединяет кнопки и QWidgetStack. Клик по кнопке переносит связанную страницу на передний план и изменяет размеры диалога до минимума, требуемого новой страницей. В отличие от основанных на QTabWidget диалогов, эти диалоги обычно постоянно используются пользователем и должны быть небольшими и быстродействующими в использовании.

Вот скриншот из диалога Tool3D с тремя страницами (A, B и C):

Tool3D

Диалог состоит из QButtonGroup (слева) и QWidgetStack (справа). Он был разработан, используя Qt Designer , который представляет "родную" поддержку QWidgetStack в Qt 3.1.

Designer

Снова мы создаем хитрый автоматический диалог, изменяющий размеры, используя тот же самый способ, который мы применяли к QTabWidget: установили размеры стратегии скрытых страниц в "ignored".

Вот функция init(), вызываемая конструктором приложения. Имена buttonA, pageA и т.д., были введены в Qt Designer:

void Tool3D::init()
{
  connect(buttonA, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
  connect(buttonB, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
  connect(buttonC, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
  pageA->setSizePolicy(ignored);
  pageB->setSizePolicy(ignored);
  pageC->setSizePolicy(ignored);
  buttonA->toggle();
}

Мы подключаем эти три переключаемых сигнала QToolButtons к слоту диалога buttonToggled; мы устанавливаем размер стратегии всех страниц "ignored"; и мы програмно нажимаем первую кнопку, чтобы перенести страницу A на передний план.

Вот слот buttonToggled(), вызываемый каждым сигналом кнопки toggled():

void Tool3D::buttonToggled(bool on)
{
  if (on) {
      QToolButton *buttonX = (QToolButton *)sender();
      QWidget *newPage;
      if (buttonX == buttonA)
          newPage = pageA;
      else if (buttonX == buttonB)
          newPage = pageB;
      else
          newPage = pageC;
      QWidget *oldPage = widgetStack->visibleWidget();
      if (oldPage != 0)
          oldPage->setSizePolicy(ignored);
      newPage->setSizePolicy(preferred);
      widgetStack->raiseWidget(newPage);
      layout()->activate();
      setFixedSize(minimumSizeHint());
  }
}

Мы выясняем, какая страница соответствует нажатой кнопке (используя QObject::sender() , модифицируем размер стратегии и переносим новую страницу в начало QWidgetStack, чтобы сделать её видимой. Вызовы activate() и setFixedSize() идентичны тем, что мы сделали для QTabWidget ранее.

Примеры QTabWidget и QWidgetStack имеют много общего - и, фактически, может быть другой пример QWizard. Qt пытается сделать программирование общепринятым, насколько это возможно, так, чтобы знания накопленные вами в использовании одного класса, могли быть использованы снова в других классах.


Copyright © 2003 Trolltech.

Trademarks