355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Нейл Мэтью » Основы программирования в Linux » Текст книги (страница 63)
Основы программирования в Linux
  • Текст добавлен: 21 сентября 2016, 17:59

Текст книги "Основы программирования в Linux"


Автор книги: Нейл Мэтью


Соавторы: Ричард Стоунс
сообщить о нарушении

Текущая страница: 63 (всего у книги 67 страниц)

 LayoutWindow *window = new LayoutWindow();

 app.setMainWidget(window);

 window->show();

 return app.exec();

}

Как и прежде, перед компиляцией нужно выполнить moc для заголовочного файла:

$ moc LayoutWindow.h -о LayoutWindow.moc

$ g++ -о layout LayoutWindow.cpp -I$QTDIR/include -L$QTDIR/lib -lqui

Выполнив эту программу, вы получите схему размещения ваших меток QLabel (рис. 17.4). Попробуйте изменить величину окна и посмотрите, как расширяются и сжимаются метки, заполняя все доступное пространство.

Рис. 17.4

Как это работает

Программа LayoutWindow.cpp создает два виджета упаковочных контейнеров, горизонтальный и вертикальный контейнер для размещения виджетов. Вертикальный контейнер получает две метки, описанные, соответственно, как Top и Bottom. Горизонтальный контейнер также содержит два виджета, метку, обозначенную Right, и вертикальный контейнер. Вы можете помещать компоновочные виджеты внутрь других компоновочных виджетов, как показано в данном примере.

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

Мы рассмотрели основы применения Qt – сигналы и слоты, команду moc и средства компоновки. Теперь пора более внимательно изучить виджеты.

Виджеты Qt

Для каждого случая в Qt есть виджеты, и их подробное рассмотрение займет всю оставшуюся часть книги. В этом разделе мы познакомимся с виджетами Qt общего применения, включая виджеты для ввода данных, кнопки, обычные и раскрывающиеся списки.

QLineEdit

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

Далее перечислены конструкторы и наиболее полезные методы.

#include

QLineEdit::QLineEdit(QWidget *parent, const char* name = 0);

QLineEdit::QLineEdit(const QString& contents, QWidget *parent,

 const char *name = 0);

QLineEdit::QLineEdit(const QString& contents, const QString& inputMask,

 QWidget *parent, const char* name = 0);

void setInputMask(const QString& inputMask);

void insert(const QString& newText);

bool isModified(void);

void setMaxLength(int length);

void setReadOnly(bool read);

void setText(const QString &text);

QString text(void);

void setEchoMode(EchoMode mode);

В конструкторах вы задаете как обычно родительский виджет и имя виджета с помощью параметров parent и name.

Интересно свойство EchoMode, определяющее способ отображения текста в виджете. Оно может принимать одно из трех значений:

QLineEdit::Normal – отображать вводимые символы (по умолчанию);

□ QLineEdit::Password – отображать звездочки на месте символов;

□ QLineEdit::NoEcho – ничего не отображать. Задается режим отображения с помощью метода setEchoMode:

lineEdit->setEchoMode(QLineEdit::Password);

Усовершенствование, внесенное в версию Qt 3.2, – свойство inputMask, ограничивающее ввод в соответствии с правилом маски.

inputMask – это строка, сформированная из символов, каждый из которых соответствует правилу, принимающему диапазон определенных символов. Если вы знакомы с регулярными выражениями, inputMask использует во многом тот же самый принцип.

Есть два сорта символов, формирующих inputMask: первые указывают на необходимость присутствия определенного символа, вторые при наличии символа добиваются его соответствия заданному правилу. В табл. 17.1 приведены примеры таких символов и их значения.

Таблица 17.1


AaСимволы ASCII А–Z, а–z
NnСимволы ASCII A–Z, a–z, 0–9
XxЛюбой символ
90Цифры 0–9
DdЦифры 1–9

Наша inputMask – это строка, сформированная комбинацией этих символов и необязательно завершающаяся точкой с запятой. Существуют дополнительные специальные символы, у которых также есть значения (табл. 17.2).

Таблица 17.2


# Разрешен, но не обязателен знак +/-
> Преобразует все последующие введенные символы в символы верхнего регистра.
< Преобразует все последующие введенные символы в символы нижнего регистра
! Останавливает преобразование регистра
Символ управляющей последовательности для применения специальных символов в качестве разделителей

Все остальные символы в inputMask действуют как разделители в поле ввода QLineEdit.

В табл. 17.3 приведены примеры масок ввода и соответствующий им текст для ввода.

Таблица 17.3


«AAAAAA-999D» Допустимо Athens-2004, но не Sydney-2000 или Atlanta-1996
«ААААnn-99-99;» Допустимо March-03-12, но не Мау-03-12 или September-03-12
«000.000.000.000» Допустим IP-адрес, например, 192.168.0.1

Выполните упражнение 17.4.

Упражнение 17.4. Виджет QLineEdit

Посмотрим, как действует виджет QLineEdit.

1. Сначала – заголовочный файл LineEdit.h:

#include

#include

#include

class LineEdit : public QMainWindow {

 Q_OBJECT

public:

 LineEdit(QWidget *parent = 0, const char *name = 0);

 QLineEdit *password_entry;

private slots:

 void Clicked();

};

2. LineEdit.cpp – уже знакомый файл реализации класса:

#include «LineEdit.moc»

#include

#include

#include

#include

#include

LineEdit::LineEdit(QWidget *parent, const char *name) :

 QMainWindow(parent, name) {

 QWidget *widget = new QWidget(this);

 setCentralWidget(widget);

3. Для компоновки виджетов примените QGridLayout. Задайте число строк и столбцов, величины отступов и расстояния между виджетами:

 QGridLayout *grid = new QGridLayout(widget, 3, 2, 10, 10, «grid»);

 QLineEdit *username_entry = new QLineEdit(widget, «username_entry»);

 password_entry = new QLineEdit(widget, «password_entry»);

 password_entry->setEchoMode(QLineEdit::Password);

 grid->addWidget(new QLabel(«Username», widget, «userlabel»), 0, 0, 0);

 grid->addwidget(new QLabel(«Password», widget, «passwordlabel»), 1, 0, 0);

 grid->addWidget(username_entry, 0, 1, 0);

 grid->addWidget(password_entry, 1, 1, 0);

 QPushButton *button = new QPushButton(«Ok», widget, «button»);

 grid->addWidget(button, 2, 1, Qt::AlignRight);

 resize(350, 200);

 connect(button, SIGNAL(clicked()), this, SLOT(Clicked()));

}

void LineEdit::Clicked(void) {

 std::cout << password_entry->text() << «n»;

}

int main(int argc, char **argv) {

 QApplication app(argc, argv);

 LineEdit *window = new LineEdit();

 app.setMainWidget(window);

 window->show();

 return app.exec();

}

Выполнив эту программу, вы должны получить результат, показанный на рис. 17.5.

Рис. 17.5

Как это работает

Вы создали два виджета QLineEdit, один подготовили для ввода пароля, задав EchoMode, и заставили его выводить содержимое при щелчке мышью кнопки PushButton. Обратите внимание на виджет QGridLayout, который очень полезен для размещения виджетов в табличной сетке. Когда виджет вставляется в сетку таблицы, вы передаете номер строки и столбца, нумерация начинается с 0, нулевые номера строки и столбца у верхней левой ячейки.

Кнопки Qt

Кнопки виджетов вездесущи и мало отличаются внешним видом, способом применения и API в разных комплектах инструментов. Неудивительно, что Qt предлагает стандартные кнопки PushButton, флажки CheckBox и радиокнопки (или зависимые переключатели) RadioButton.

QButton: базовый класс кнопок

Все виджеты кнопок в комплекте Qt – потомки абстрактного класса QButton. У этого класса есть методы для опроса и переключения включенного/выключенного состояния кнопки и задания текста кнопки или ее графического представления.

Вам никогда не придется обрабатывать виджет типа QButton (не путайте с виджетом QPushButton!), поэтому нет смысла приводить конструкторы. Далее перечислено несколько полезных функций-методов этого класса:

#include

virtual void QButton::setText(const QString&);

virtual void QButton::setPixmap(const QPixmap&);

bool QButton::isToggleButton() const;

virtual void QButton::setDown(bool);

bool QButton::isDown() const;

bool QButton::isOn() const;

enum QButton::ToggleState { Off, NoChange, On }

ToggleState QButton::state() const;

У функций isDown и isOn одно назначение. Обе они возвращают TRUE, если кнопка была нажата или активизирована.

Часто вам нужно отключить или сделать серым вариант, если он недоступен в данный момент. Сделать недоступным любой виджет, включая QButton, можно с помощью вызова метода QWidget::setEnable(FALSE).

У QButton есть три подкласса, заслуживающие внимания:

□ QPushButton – виджет простой кнопки, выполняющий некоторое действие при щелчке кнопкой мыши;

□ QCheckBox – виджет кнопки, способный изменять состояние с включенного на выключенное для обозначения некоторого выбора;

□ QRadioButton – виджет кнопки, обычно применяемый в группе таких же кнопок, только одна из которых может быть активна в любой момент времени.

QPushButton

QPushButton – стандартная кнопка общего вида, содержащая текст, такой как «OK» или «Cancel» и/или пиксельную пиктограмму. Как все кнопки класса QButton, она порождает при активизации сигнал clicked и обычно используется для связи со слотом и выполнения некоторого действия.

Вы уже применяли кнопку QPushButton в примерах, и есть лишь еще одна интересная деталь, касающаяся этого простейшего из виджетов Qt. Кнопку QPushButton можно превратить из кнопки, не помнящей своего состояния, в кнопку-выключатель (т.е. способную быть включенной и выключенной), вызвав метод setToggleButton. (Если помните, у комплекта GTK+ из предыдущей главы есть для этих целей разные виджеты.)

Далее для полноты описания приведены конструкторы и полезные методы.

#include

QPushButton(QWidget *parent, const char *name = 0);

QPushButton(const QString& text, QWidget *parent, const char *name = 0);

QPushButton(const QIconSet& icon, const QString& text,

 QWidget *parent, const char * name = 0);

void QPushButton::setToggleButton(bool);

QCheckBox

QCheckBox – это кнопка, у которой есть состояние, ее можно включить и выключить (или установить и сбросить). Внешний вид QCheckBox зависит от стиля отображения окон текущей системы (Motif, Windows и т.д.), но обычно она отображается как флажок с сопроводительным текстом справа.

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

#include

QCheckBox(QWidget *parent, const char *name = 0);

QCheckBox(const QString& text, QWidget *parent, const char *name = 0);

bool QCheckBox::isChecked();

void QCheckBox::setTristate(bool y = TRUE);

bool QCheckBox::isTristate();

QRadioButton

Радиокнопки – кнопки-переключатели, применяемые для отображения исключающего выбора, когда можно выбрать только один вариант из группы представленных (вспомните снова старые автомобильные радиоприемники, в которых можно было нажать только одну кнопку блока). Сами по себе кнопки QRadioButton не многим отличаются от кнопок QCheckBox, поскольку группировка и исключительный выбор обрабатываются классом QButtonGroup, главное же их отличие заключается в том, что они отображаются как круглые кнопки, а не как флажки.

QButtonGroup – виджет, облегчающий обработку групп кнопок за счет предоставления удобных методов.

#include

QButtonGroup(QWidget *parent = 0, const char* name = 0);

QButtonGroup(const QString& title, QWidget* parent = 0,

 const char * name = 0);

int insert (QButton *button, int id = -1);

void remove(QButton *button);

int id(QButton *button) const;

int count() const;

int selectedId() const;

Применять виджет QButtonGroup проще простого: он даже предлагает необязательную рамку вокруг кнопок, если используется конструктор title.

Добавить кнопку в QButtonGroup можно с помощью метода insert или заданием QButtonGroup в качестве родительского виджета кнопки. Для уникального обозначения каждой кнопки в группе можно задать id в методе insert. Это особенно полезно при определении выбранной кнопки, т.к. функция selectedId возвращает id выбранной кнопки.

Все кнопки QRadioButton, добавляемые в группу, автоматически становятся кнопками с исключающим выбором.

Далее приведены прототипы конструкторов QRadioButton и одного уникального метода, который не вызовет большого удивления:

#include

QRadioButton(QWidget* parent, const char* name = 0);

QRadioButton(const QString& text, QWidget *parent, const char *name = 0);

bool QRadioButton::isChecked();

Выполните упражнение 17.5.

Упражнение 17.5. Виджет QButton

Теперь применим полученные знания в примере с кнопками Qt. Приведенная далее программа создает кнопки разных типов (радиокнопки, флажки и простые кнопки), чтобы показать, как использовать эти виджеты в ваших приложениях.

1. Введите файл Buttons.h:

#include

#include

#include

#include

class Buttons : public CMainWindow {

 Q_OBJECT

public:

 Buttons(QWidget *parent = 0, const char *name = 0);

2. Вы запросите состояние ваших кнопок позже, в функции слота, поэтому объявите указатели кнопок и вспомогательную функцию PrintActive с атрибутом private в объявлении класса:

private:

 void PrintActive(QButton *button);

 QCheckBox *checkbox;

 QRadioButton *radiobutton1, *radiobutton2;

private slots:

 void Clicked();

}

3. Далее следует файл Buttons.срр:

#include «Buttons.moc»

#include

#include

#include

#include

#include

#include

Buttons::Buttons(QWidget *parent, const char *name) :

 QMainWindow(parent, name) {

 QWidget* widget = new QWidget(this);

 setCentralWidget(widget);

 QVBoxLayout *vbox = new QVBoxLayout(widget, 5, 10, «vbox»);

 checkbox = new QCheckBox(«CheckButton», widget, «check»);

 vbox->addWidget(checkbox);

4. Затем вы создаете QButtonGroup для двух ваших радиокнопок (переключателей).

 QButtonGroup *buttongroup = new QButtonGroup(0);

 radiobutton1 = new QRadioButton(«RadioButton1», widget, «radio1»);

 buttongroup->insert(radiobutton1);

 vbox->addWidget(radiobutton1);

 radiobutton2 = new QRadioButton(«RadioButton2», widget, «radio2»);

 buttongroup->insert(radiobutton2);

 vbox->addWidget(radiobutton2);

 QPushButton* button = new QPushButton(«Ok», widget, «button»);

 vbox->addWidget(button);

 resize(350, 200);

 connect(button, SIGNAL(clicked()), this, SLOT(Clicked()));

}

5. Затем приведен удобный метод для вывода состояния заданной кнопки QButton:

void Buttons::PrintActive(QButton *button) {

 if (button->isOn())

  std::cout << button->name() << « is checkedn»;

 else

  std::cout" << button->name() << « is not checkedn»;

}

void Buttons::Clicked(void) {

 PrintActive(checkbox);

 PrintActive(radiobutton1);

 PrintActive(radiobutton2);

 std::cout << «n»;

}

int main(int argc, char **argv) {

 QApplication app(argc, argv);

 Buttons *window = new Buttons();

 app.setMainWidget(window);

 window->show();

 return app.exec();

}

Как это работает

Этот простой пример показывает, как опрашивать виджеты кнопок Qt разных типов. После создания все они по большей части действуют одинаково. Например, функция PrintActive демонстрирует, как получить состояние кнопки (включена или выключена). Обратите внимание на то, как она действует в случае запоминающих состояние кнопок разных типов, таких как флажки и переключатели (радиокнопки). В основном отличаются только вызовы для создания виджета кнопки. Радиокнопки, наиболее сложные (т.к. только одна в группе может быть включена), при создании требуют больше всего работы. В случае радиокнопок вы должны создать QButtonGroup для того, чтобы гарантировать активность только одной радиокнопки в группе в любой момент времени.

QComboBox

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

В виджете QComboBox сочетаются функциональные возможности виджетов QLineEdit и QPushButton и раскрывающихся меню, позволяя выбрать один вариант из неограниченного набора вариантов.

QComboBox может быть открытым, как для чтения и записи, так и только для чтения. Если он позволяет читать и записывать, пользователь может ввести новый вариант в дополнение к предлагаемым; в противном случае пользователь ограничен выбором варианта из раскрывающегося списка.

При создании виджета QComboBox можно указать, открыт ли он для чтения и записи или только для чтения, задавая логическое значение в конструкторе:

QComboBox *combo = new QComboBox(TRUE, parent, «widgetname»);

Передача значения TRUE переводит QComboBox в режим «чтение/запись». Остальные параметры – обычный указатель на родительский виджет и имя создаваемого виджета.

Как все виджеты Qt, QComboBox обладает гибкостью и предлагает широкий набор функциональных возможностей.

Вы можете добавлять варианты по одному или набором, как тип QString или в стандартном формате char*.

Для вставки одного варианта вызовите функцию insertItem:

combo->insertItem(QString(«An Item»), 1);

Приведенная функция принимает объект типа QString и номер позиции в списке. В данном случае 1 вставляет вариант в список первым.

Для добавления в конец списка задайте любое отрицательное целое число.

Гораздо чаще вы будете вставлять несколько элементов списка одновременно, для этого можно применить класс QStrList или, как показано далее, массив char*:

char* weather[] = {"Thunder", «Lightning», «Rain», 0};

combo->insertStrList(weather, 3);

И снова вы можете задать номер позиции вставляемых в список элементов.

Если в виджете QComboBox задан режим «чтение/запись», вводимые пользователем варианты могут автоматически вставляться в список. Это очень полезное, экономящее время свойство, избавляющее пользователя от повторного набора варианта, если он хочет уже введенный вариант использовать несколько раз.

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

Таблица 17.4


QComboBox::AtTop Вставляет вводимый в список элемент первым
QComboBox::AtBottom Вставляет вводимый в список элемент последним
QComboBox::AtCurrent Заменяет предварительно выбранный вариант в списке
QComboBox::BeforeCurrent Вставляет вводимый элемент перед предварительно выбранным вариантом из списка
QComboBox::AfterCurrent Вставляет вводимый элемент после предварительно выбранного варианта из списка
QComboBox::NoInsertion Новый элемент не вставляется в список вариантов

Для задания политики вызовите метод InsertionPolicy виджета QComboBox:

combo->setInsertionPolicy(QComboBox::AtTop);

Давайте бросим взгляд на конструкторы и методы выбора варианта виджета QComboBox:

#include

QComboBox(QWidget *parent = 0, const char *name = 0);

QComboBox(bool readwrite, QWidget *parent = 0, const char *name = 0);

int count();

void insertStringList(const QStringList& list, int index = -1);

void insertStrList(const QStrList& list, int index = -1);

void insertStrList(const QStrList *list, int index = -1);

void insertStrList (const char **strings, int numStrings = -1, int index = -1);

void insertItem(const QString &t, int index = -1);

void removeItem(int index);

virtual void setCurrentItem(int index);

QString currentText();

virtual void setCurrentText(const QString &);

void setEditable(bool);

Функция count возвращает количество вариантов в списке. QStringList и QStrList – классы коллекций, которые можно применять для вставки вариантов. Удалить варианты можно с помощью метода removeItem, извлечь и задать текущий вариант можно, с помощью методов currentText и setCurrentText, а перейти в редактируемый режим – с помощью метода setEditable.

QComboBox порождает сигнал textChanged(QString&) при каждом новом выборе варианта, передавая вновь выбранный элемент как аргумент.

Выполните упражнение 17.6.

Упражнение 17.6. Виджет QComboBox

В этом примере вы сделаете попытку применить виджет QComboBox и посмотрите, как ведут себя сигналы и слоты с параметрами. Вы создадите класс ComboBox, потомка QMainWindow. В нем будут два виджета QComboBox: один для чтения/записи, другой только для чтения. Вы установите связь с сигналом textChanged для того, чтобы получать текущее значение при каждом его изменении.

1. Введите следующий программный код и назовите файл ComboBox.h:

#include

#include

class ComboBox : public QMainWindow {

 Q_OBJECT

public:

 ComboBox(QWidget* parent = 0, const char *name = 0);

private slots:

 void Changed(const QString& s);

};

2. Интерфейс состоит из двух виджетов QComboBox: один редактируемый, а другой предназначен только для чтения. Вы заполните оба списка одними и теми же вариантами:

#include «ComboBox.moс»

#include

#include

ComboBox::ComboBox(QWidget *parent, const char *name) :

 QMainWindow(parent, name) {

 QWidget *widget = new QWidget(this);

 setCentralWidget(widget);

 QVBoxLayout *vbox = new QVBoxLayout(widget, 5, 10, «vbox»);

 QComboBox *editablecombo = new QComboBox(TRUE, widget, «editable»);

 vbox->addWidget(editablecombo);

 QComboBox *readonlycombo = new QComboBox(FALSE, widget, «readonly»);

 vbox->addWidget(readonlycombo);

 static const char* items[] = {"Macbeth", «Twelfth Night», «Othello», 0};

 editablecombo->insertStrList(items);

 readonlycombo->insertStrList(items);

 connect(editablecombo, SIGNAL(textchanged(const QString&),

  this, SLOT(Changed(const QString&)));

 resize(350, 200);

}

3. Далее приведена функция слота. Обратите внимание на параметр s типа QString, передаваемый сигналом:

void ComboBox::Changed(const QString& s) {

 std::cout << s << «n»;

}

int main(int argc, char **argv) {

 QApplication app(argc, argv);

 ComboBox* window = new ComboBox();

 app.setMainWidget(window);

 window->show();

 return app.exec();

}

Вы сможете видеть вновь выбранные из редактируемого QComboBox варианты в командной строке на рис. 17.6.

Рис. 17.6

Как это работает

Создаются виджеты раскрывающегося списка во многом так же, как и другие виджеты. Главная новая деталь – вызов функции insertStrList для сохранения списка вариантов в виджете.

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


    Ваша оценка произведения:

Популярные книги за неделю