Пример "Class Wizard"
Файлы:
Пример "Class Wizard" показывает, как реализовать линейный мастер используя QWizard.
Многие мастера имеют линейную структуру, со страницей 1, следом - страница 2 и так далее до последней страницы. Некоторые более сложные мастера, в которых разрешены разные пути прохождения на основе информации, предоставляемой пользователем. Пример "License Wizard" показывает, как создавать такие мастера.
Пример "Class Wizard" содержит следующие классы:
- ClassWizard унаследован от QWizard и предоставляет трехступенчатый мастер, который генерирует скелет класса C++ на основе пользовательского ввода.
- IntroPage, ClassInfoPage, CodeStylePage, OutputFilesPage и ConclusionPage являются подклассами QWizardPage, которые реализуют страницы мастера.
Определение класса ClassWizard
Му увидим как создать подкласс QWizard для реализации нашего собственного мастера. Класс конкретного мастера называется ClassWizard и представляет пять страниц:
- Первая страница - вводная страница, сообщающая пользователю что делает мастер.
- Вторая страница запрашивает имя класса и базовый класс, а также позволяет пользователю указать будет ли класс содержать макрос Q_OBJECT и что предоставят конструкторы.
- Третья страница позволяет пользователю установить некоторые опции, относящиеся к стилю кода, например, макрос используемый для защиты заголовочного файла от многократного включения (например, MYDIALOG_H).
- Четвёртая страница позволяет пользователю задать имена выходных файлов.
- Пятая страница - это итоговая страница.
Хотя программа - это только пример, если вы нажмёте кнопку Finish (Done в Mac OS X), реальные файлы исходного кода C++ будут действительно сгенерированы.
Класс ClassWizard
Вот определение ClassWizard:
class ClassWizard : public QWizard
{
Q_OBJECT
public:
ClassWizard(QWidget *parent = 0);
void accept();
};
Класс переопределяет слот QDialog'а, accept(). Этот слот вызывается, когда пользователь щелкает кнопку Finish.
Вот конструктор:
ClassWizard::ClassWizard(QWidget *parent)
: QWizard(parent)
{
addPage(new IntroPage);
addPage(new ClassInfoPage);
addPage(new CodeStylePage);
addPage(new OutputFilesPage);
addPage(new ConclusionPage);
setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
setWindowTitle(tr("Class Wizard"));
}
Мы создаём экземпляры пяти страниц и вставляем их в мастер, используя QWizard::addPage(). Порядок в котором они вставлены является также порядком, в котором они будут позднее показаны.
Мы вызываем QWizard::setPixmap(), чтобы установить растровые изображения шапки и фона для всех страниц. Шапка используется в качестве фона для заголовка страницы когда стиль мастера ModernStyle; фон используется в качестве фона диалога в MacStyle. (Для получения дополнительной информации смотрите Элементы страницы мастера.)
void ClassWizard::accept()
{
QByteArray className = field("className").toByteArray();
QByteArray baseClass = field("baseClass").toByteArray();
QByteArray macroName = field("macroName").toByteArray();
QByteArray baseInclude = field("baseInclude").toByteArray();
QString outputDir = field("outputDir").toString();
QString header = field("header").toString();
QString implementation = field("implementation").toString();
...
QDialog::accept();
}
Если пользователь щелкнет кнопку Finish, мы извлечём информацию из нескольких страниц используя QWizard::field() и сгенерируем файлы. Код длинный и утомительный (и просто что-нибудь делает с благородным искусством проектирования мастеров), поэтому большая его часть здесь опущена. Если вы заинтересовались, то за подробностями обращайтесь к реальному примеру из поставки Qt.
Класс IntroPage
Страницы определены в classwizard.h и реализованы в classwizard.cpp, вместе с ClassWizard. Начнём с самой лёгкой страницы:
class IntroPage : public QWizardPage
{
Q_OBJECT
public:
IntroPage(QWidget *parent = 0);
private:
QLabel *label;
};
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Introduction"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));
label = new QLabel(tr("This wizard will generate a skeleton C++ class "
"definition, including a few functions. You simply "
"need to specify the class name and set a few "
"options to produce a header file and an "
"implementation file for your new C++ class."));
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
setLayout(layout);
}
Страница унаследована от QWizardPage. Мы установили title и watermark pixmap. Не устанавливая любой subTitle мы обеспечиваем, что для этой страницы не будет показан заголовок. (В Windows это обычно для мастеров - показывать растровое изображение водяного знака на первой и последней страницах, а на остальных страницах иметь заголовок.)
Затем мы создаём QLabel и добавляем её в компоновку.
Класс ClassInfoPage
Вторая страница определена и реализована как изложено ниже:
class ClassInfoPage : public QWizardPage
{
Q_OBJECT
public:
ClassInfoPage(QWidget *parent = 0);
private:
QLabel *classNameLabel;
QLabel *baseClassLabel;
QLineEdit *classNameLineEdit;
QLineEdit *baseClassLineEdit;
QCheckBox *qobjectMacroCheckBox;
QGroupBox *groupBox;
QRadioButton *qobjectCtorRadioButton;
QRadioButton *qwidgetCtorRadioButton;
QRadioButton *defaultCtorRadioButton;
QCheckBox *copyCtorCheckBox;
};
ClassInfoPage::ClassInfoPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Class Information"));
setSubTitle(tr("Specify basic information about the class for which you "
"want to generate skeleton source code files."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));
classNameLabel = new QLabel(tr("&Class name:"));
classNameLineEdit = new QLineEdit;
classNameLabel->setBuddy(classNameLineEdit);
baseClassLabel = new QLabel(tr("B&ase class:"));
baseClassLineEdit = new QLineEdit;
baseClassLabel->setBuddy(baseClassLineEdit);
qobjectMacroCheckBox = new QCheckBox(tr("Generate Q_OBJECT ¯o"));
groupBox = new QGroupBox(tr("C&onstructor"));
...
registerField("className*", classNameLineEdit);
registerField("baseClass", baseClassLineEdit);
registerField("qobjectMacro", qobjectMacroCheckBox);
registerField("qobjectCtor", qobjectCtorRadioButton);
registerField("qwidgetCtor", qwidgetCtorRadioButton);
registerField("defaultCtor", defaultCtorRadioButton);
registerField("copyCtor", copyCtorCheckBox);
QVBoxLayout *groupBoxLayout = new QVBoxLayout;
...
}
Сначала мы установили title, subTitle и logo pixmap страницы. Растровое изображение логотипа выводится на экран в заголовке страницы в ClassicStyle и ModernStyle.
Затем мы создаём дочерние виджеты, создаём поля мастера, связанные с ними, и помещаем их в компоновки. Поле className создано с символом звёздочки(*) после его имени. Это делает его обязательным полем, т.е., поле должно быть заполнено перед тем, как пользователь сможет нажать кнопку Next (Continue в Mac OS X). Значения полей доступны из любой другой страницы с использованием QWizardPage::field(), или из кода мастера используя QWizard::field().
Класс CodeStylePage
Третья страница определена и реализована так:
class CodeStylePage : public QWizardPage
{
Q_OBJECT
public:
CodeStylePage(QWidget *parent = 0);
protected:
void initializePage();
private:
QCheckBox *commentCheckBox;
QCheckBox *protectCheckBox;
QCheckBox *includeBaseCheckBox;
QLabel *macroNameLabel;
QLabel *baseIncludeLabel;
QLineEdit *macroNameLineEdit;
QLineEdit *baseIncludeLineEdit;
};
CodeStylePage::CodeStylePage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Code Style Options"));
setSubTitle(tr("Choose the formatting of the generated code."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo2.png"));
commentCheckBox = new QCheckBox(tr("&Start generated files with a "
...
setLayout(layout);
}
void CodeStylePage::initializePage()
{
QString className = field("className").toString();
macroNameLineEdit->setText(className.toUpper() + "_H");
QString baseClass = field("baseClass").toString();
includeBaseCheckBox->setChecked(!baseClass.isEmpty());
includeBaseCheckBox->setEnabled(!baseClass.isEmpty());
baseIncludeLabel->setEnabled(!baseClass.isEmpty());
baseIncludeLineEdit->setEnabled(!baseClass.isEmpty());
if (baseClass.isEmpty()) {
baseIncludeLineEdit->clear();
} else if (QRegExp("Q[A-Z].*").exactMatch(baseClass)) {
baseIncludeLineEdit->setText("<" + baseClass + ">");
} else {
baseIncludeLineEdit->setText("\"" + baseClass.toLower() + ".h\"");
}
}
Код в конструкторе очень похож на такой же, что мы сделали для ClassInfoPage, поэтому мы пропустили большую его часть.
Функция initializePage() - это то, что делает этот класс интересным. Она переопределена из QWizardPage и используется для инициализации некоторых полей страницы с значениями из предыдущей страницы (а именно, className и baseClass). Например, если имя класса на странице 2 - SuperDuperWidget, по умолчанию имя макроса на странице 3 SUPERDUPERWIDGET_H.
Классы OutputFilesPage и ConclusionPage очень похожи на CodeStylePage, поэтому мы не будем рассматривать их здесь.
Смотрите также QWizard, Пример "License Wizard" и Пример "Trivial Wizard".
|