Шаг 85.
Библиотека Qt.
Класс QComboBox

    На этом шаге рассмотрим класс QComboBox.

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

    В качестве элемента можно добавить текст и/или картинку. Для этого служит метод addItem(). Можно добавить сразу несколько текстовых элементов, передав указатель на объект класса QStringList в метод addItems().

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

    Чтобы узнать, какой из элементов является текущим, нужно вызывать метод currentIndex(), который возвратит его порядковый номер.

    Можно сделать так, чтобы пользователь мог сам добавлять элементы в список. Типичным примером этого является адресная строка Проводника ОС Windows, содержащая в себе список просмотренных адресов (ссылок). Для установки виджета в этот режим вызывается метод setEditable() с параметром true. После того как пользователь изменил текст выбранного элемента, отправляется сигнал editTextChanged(const QString&), и новый элемент добавляется в список.

    После выбора элемента отправляются сразу два сигнала activated() — один с параметром типа int (индексом выбранного элемента), а другой с параметром типа const QString& (его значением). Эти сигналы отправляются, даже если пользователь выбрал ранее выбранный элемент; для информирования о реальном изменении служат два сигнала currentIndexChanged(), также отправляемые с параметрами int и const QString& каждый.

    Пример, приведенный на рис. 1, демонстрирует виджет выпадающего списка. При изменении элемента список дополнится новым элементом.


Рис.1. Пример выпадающего списка

    Рассмотрим текст приложения:

//создается виджет выпадающего списка cb
QComboBox cb;
QStringList lst;
//в список lst добавляются строки
lst << "Январь" << "Февраль" << "Март" << "Апрель";
//строки устанавливаются вызовом метода addItems()
//в виджете выпадающего списка
cb.addItems(lst);
//вызов метода setEditable() с параметром true
//переводит список в режим редактирования
cb.setEditable(true);
cb.show();

    Файлы приложения можно взять здесь.

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


Рис.2. Пример выпадающего списка с картинками

    Рассмотрим текст приложения:

QComboBox cb;
QStringList lst;
lst << "Android" << "Linux" << "Windows" << "MacOSX" << "MSDOS";
//для каждой строки из списка
foreach(QString str, lst)
{   //добавляем новый элемент в список, который состоит из
    //иконки и текста
    cb.addItem(QIcon(str+".jpg"),str, Qt::UserRole);
}
//устанавливаем размер иконки
cb.setIconSize(QSize(60,60));
cb.show();

    Файлы приложения можно взять здесь.

    Пример, приведенный на рис. 3, демонстрирует применение сигнала activated(int) выпадающего списка. В примере требуется ввести два числа и выбрать из списка действие над ними.


Рис.3. Пример использования выпадающего списка

    Для реализации этого приложения описали следующий класс:

class cb:public QWidget
{
    Q_OBJECT
private:
    QStringList lst;
    QLabel *l,*l1,*l2;
    QLineEdit *a,*b;
    QComboBox *cbox;
    FileNameValidator *pnameValidator1,*pnameValidator2;
public:
    cb(QWidget *parent=0);
private slots:
    void schet();
};

    Конструктор реализован следующим образом:

//создали виджет выпадающего списка
cbox=new QComboBox();
//создали виджеты надписей
l=new QLabel("Результат: ");
l1=new QLabel("Введите первое число: ");
l2=new QLabel("Введите второе число: ");
//создали виджеты полей ввода и
//инициализировали их значениями
a=new QLineEdit("10");
//защита от ввода букв и специальных символов
pnameValidator1 = new FileNameValidator(a);
a->setValidator(pnameValidator1);
l1->setBuddy(a);
b=new QLineEdit("2");
pnameValidator2 = new FileNameValidator(b);
b->setValidator(pnameValidator2);
l2->setBuddy(b);
//создаем список строк
lst << "Сумма" << "Разность"
    << "Произведение" << "Частное";
//строки устанавливаются вызовом метода addItems()
//в виджете выпадающего списка
cbox->addItems(lst);
//установили в качестве текущего элемент с индексом 0
cbox->setCurrentIndex(0);
//объявили переменные вещественного типа
float ax,bx,res;
//содержит первое введенное число
ax=a->text().toFloat();
//содержит второе введенное число
bx=b->text().toFloat();
//содержит сумму двух введенных чисел
res=ax+bx;
//выводим полученный результат в виджет надписи
l->setText(l->text()+QString::number(res));
//при выборе элемента выпадающего списка срабатывает сигнал
//activated(int) с параметром целого типа (индекс выбранного элемента)
//при возникновении сигнала activated(int) будем выполнять
//слот schet(), который реализует соответствующее действие
connect(cbox,SIGNAL(activated(int)),this,SLOT(schet()));
//аналогично, будем выполнфть слот schet() при изменении
//в полях ввода
connect(a,SIGNAL(textChanged(QString)),this,SLOT(schet()));
connect(b,SIGNAL(textChanged(QString)),this,SLOT(schet()));
//выполняем размещение элементов в окне
QVBoxLayout *phbl1=new QVBoxLayout;
phbl1->setMargin(5);
phbl1->setSpacing(15);
phbl1->addWidget(l1);
phbl1->addWidget(a);
phbl1->addWidget(l2);
phbl1->addWidget(b);
phbl1->addWidget(l);
QHBoxLayout *pvbl=new QHBoxLayout;
pvbl->setMargin(5);
pvbl->setSpacing(15);
pvbl->addWidget(cbox);
pvbl->addLayout(phbl1);
setLayout(pvbl);

    Слот schet() выполняет с введенными числами выбранное в списке действие:

l->setText("Результат: ");
//если поля ввода не пусты 
if((a->text()!="")&&(b->text()!=""))
{
    float ax,bx,res;
    ax=a->text().toFloat();
    bx=b->text().toFloat();
    //если выбран элемент Сумма
    if(cbox->currentIndex()==0)
    {
       res=ax+bx;
       l->setText(l->text()+QString::number(res));
    }
    else
        //если выбран элемент Разность
        if(cbox->currentIndex()==1)
        {
           res=ax-bx;
           l->setText(l->text()+QString::number(res));
        }
    else
        //если выбран элемент Произведение
        if(cbox->currentIndex()==2)
        {
           res=ax*bx;
           l->setText(l->text()+QString::number(res));
        }
    else
    {   //если выбран элемент Частное
        if(bx!=0)
        {
            res=ax/bx;
            l->setText(l->text()+QString::number(res));
        }
        else
           l->setText(l->text()+" Делить на 0 нельзя");
    }
}

    Защита от неверного ввода реализована следующим классом:

class FileNameValidator : public QValidator {
public:
    FileNameValidator(QObject* parent) : QValidator(parent)
    {
    }
    virtual State validate(QString& str, int& pos) const
    {   //все символы, кроме цифр и точки
        QRegExp rxp = QRegExp("[^0-9.]");
        if (str.contains(rxp)) {
            return Invalid;
        }
        else
         return Acceptable;
    }
};

    Файлы приложения можно взять здесь.

    На следующем шаге рассмотрим класс QTabWidget.




Предыдущий шаг Содержание Следующий шаг