Wiki

Расширенные диалоги

Автор: Reginald Stadlbauer
Перевод: Andi Peredri

Неофициальный перевод статьи Extension Dialogs выполнен с любезного разрешения Trolltech.

Расширенный диалог - это диалоговое окно, имеющее два различных интерфейсных вида: 'простой' и более крупный 'расширенный'. Расширенные диалоги позволяют скрыть многочисленные опции от неквалифицированных и небрежных пользователей и, в то же время, не ограничивать в возможностях настройки опытных пользователей. Такие диалоги можно легко создавать с помощью Qt и Qt Designer.

Изначально расширенный диалог представлен своим 'простым' видом с кнопкой Details >>>. При нажатии на эту кнопку диалоговое окно сменяет свой вид на расширенный, предоставляя доступ к многочисленным опциям, а надпись кнопки сменяется на Details <<<. При повторном нажатии на кнопку диалоговое окно возвращается к своему первоначальному виду.

Ручное управление расположением интерфейсных элементов расширенного диалога является нетривиальной задачей. К счастью, класс QDialog обеспечивает автоматическую компоновку интерфейсных элементов и предлагает функции QDialog::setExtension(), QDialog::showExtension() и QDialog::setOrientation() для поддержки расширенных диалогов.

Создание диалога

Создание расширенного диалога в Qt Designer начните с создания простого. Затем, используя шаблон

QWidget, создайте отдельную форму, которая будет использоваться, как расширенная часть диалога. В нашем примере мы назовем ее Extension и сохраним в файле extension.ui. В 'простой' диалог необходимо добавить кнопку Details >>>. В нашем примере мы назовем ее detailsPushButton и свяжем ее сигнал clicked() со слотом toggleExtension().


Затем мы, используя вкладку Source окна Object Explorer, добавим переменную bool extensionShown и включим в исходный код формы файл extension.h.

Если для реализации функциональности диалога вы используете механизм наследования, добавьте следующий код в конструктор подкласса. Если вы пишите код в среде Qt Designer, добавьте этот код в исходный код слота init().

extensionShown = FALSE;
setExtension( new Extension( this ) );
setOrientation( Vertical );

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

Теперь мы реализуем слот toggleExtension(), который вызывается при нажатии на кнопку detailsPushButton:

extensionShown = !extensionShown;
showExtension( extensionShown );
QString text = tr( "&Details " );
text += extensionShown ? "<<<" : ">>>";
detailsPushButton->setText( text );

Этот код инвертирует состояние диалога и в зависимости от него показывает или прячет расширение. Затем происходит смена текста на кнопке.

Использование диалога


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

void MainForm::init()
{
    sessions = FALSE;
    logging = FALSE;
    log_filename = QString::null;
    log_acts = TRUE;
    log_errs = TRUE;
}
 
void MainForm::optionsDlg()
{
    MyDialog *dlg = new MyDialog( this, "dialog", TRUE );
    Extension *ext = (Extension*)dlg->extension(); 
    dlg->sessionsCheckBox->setChecked( sessions );
    dlg->loggingCheckBox->setChecked( logging );
    ext->logfileLineEdit->setText( log_filename );
    ext->logActionsCheckBox->setChecked( log_acts );
    ext->logErrorsCheckBox->setChecked( log_errs );
    if ( dlg->exec() ) {
        sessions = dlg->sessionsCheckBox->isChecked();
        logging = dlg->loggingCheckBox->isChecked();
        log_filename = ext->logfileLineEdit->text();
        log_acts = ext->logActionsCheckBox->isChecked();
        log_errs = ext->logErrorsCheckBox->isChecked();
    }
    delete dlg;
}

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

Преобразование типов в Qt

В представленном выше коде мы использовали явное преобразование типа для большей ясности кода. Стандарт C++ требует, чтобы преобразование типа в таких случаях осуществлялось следующим образом:

Extension *ext = dynamic_cast<Extension*>(dlg->extension());
if ( !ext ) 
    return;

Некоторые компиляторы не поддерживают dynamic_cast, поэтому для объектов QObject мы используем следующий переносимый вариант:

Extension *ext = (Extension*)dlg->extension()->qt_cast("Extension");
if ( !ext ) 
    return;