Самарев Р.С. - Программирование с использованием библиотеки Qt (1075627), страница 5
Текст из файла (страница 5)
Ниже приведен текст программы, снабженный комментариями.#include <QtGui>#include <QVector>#include <QGridLayout>#include <QHBoxLayout>#include <QVBoxLayout>#include ”calcDialog.h”// Идентификаторы кнопок// Для цифровых кнопок идентификатор является соответствующая цифра#define DIV10#define MUL11#define MINUS12#define PLUS13#define INVERSE 15#define DOT16#define EQ20#define BKSP30#define CLR31#define CLR_ALL 32// количество кнопок в группе, отображаемой в виде сетки#define GRID_KEYS 16Оглавление27/// Описатель кнопкиstruct BtnDescr{QString text; ///< Отображаемый на кнопке текстintid;///< Идентификатор кнопкиBtnDescr() { id=0;}; ///< Конструктор по умолчанию///< Конструктор для инициализацииBtnDescr( const QString & str, int i){text = str; id = i; };};/// Динамический массив-вектор элементов описателей кнопокQVector<BtnDescr> _btnDescr;/// Инициализация массива _btnDescr всеми отображаемыми кнопкамиvoid InitBtnDescrArray(){_btnDescr.push_back( BtnDescr("7", 7) );_btnDescr.push_back( BtnDescr("8", 8) );_btnDescr.push_back( BtnDescr("9", 9) );_btnDescr.push_back( BtnDescr("/", DIV) );_btnDescr.push_back( BtnDescr("4", 4) );_btnDescr.push_back( BtnDescr("5", 5) );_btnDescr.push_back( BtnDescr("6", 6) );_btnDescr.push_back( BtnDescr("*", MUL) );_btnDescr.push_back( BtnDescr("1", 1) );_btnDescr.push_back( BtnDescr("2", 2) );_btnDescr.push_back( BtnDescr("3", 3) );_btnDescr.push_back( BtnDescr("-", MINUS) );_btnDescr.push_back( BtnDescr("0", 0) );_btnDescr.push_back( BtnDescr("-/+", INVERSE) );_btnDescr.push_back( BtnDescr(".", DOT) );_btnDescr.push_back( BtnDescr("+", PLUS) );_btnDescr.push_back( BtnDescr("<-",BKSP) );_btnDescr.push_back( BtnDescr("CE",CLR) );_btnDescr.push_back( BtnDescr("C", CLR_ALL) );_btnDescr.push_back( BtnDescr("=", EQ) );}/// Конструктор класса калькулятораCalcDialog::CalcDialog( QWidget * parent){initNum(); // инициализируем счетные переменныеInitBtnDescrArray(); // инициализируем массив с описанием кнопокОглавление28// Создаем формуm_pLineEdit = new QLineEdit(this);// устанавливаем режим только чтения - разрешаем ввод только// с нарисованных кнопокm_pLineEdit->setReadOnly ( true );m_pSignalMapper = new QSignalMapper(this);// создаем схемы выравниванияQGridLayout *gridLayout = new QGridLayout();QHBoxLayout *bccKeysLayout = new QHBoxLayout();QHBoxLayout *mainKeysLayout = new QHBoxLayout();QVBoxLayout *dlgLayout = new QVBoxLayout();// Заполняем форму кнопками из _btnDescrfor (int i = 0; i < _btnDescr.size(); i++) {// Создаем кнопку с текстом из очередного описателяQPushButton *button = new QPushButton(_btnDescr[i].text);// если кнопка в основном блоке цифровых или "=" // разрешаем изменение всех размеровif( i >= GRID_KEYS + 3 || i < GRID_KEYS)button->setSizePolicy ( QSizePolicy::Expanding,QSizePolicy::Expanding);// если кнопка не цифровая - увеличиваем шрифт надписи на 4 пунктаif( _btnDescr[i].id >= 10 ){QFont fnt = button->font();fnt.setPointSize( fnt.pointSize () + 4 );button->setFont( fnt );}// связываем сигнал нажатия кнопки с объектом m_pSignalMapperconnect(button, SIGNAL(clicked()), m_pSignalMapper, SLOT(map()));// обеспечиваем соответствие кнопки её идентификаторуm_pSignalMapper->setMapping(button, _btnDescr[i].id);if(i<GRID_KEYS) // Если кнопка из центрального блока - помещаем в сеткуgridLayout->addWidget(button, i / 4, i % 4);else if( i < GRID_KEYS + 3) // кнопка из верхнего блока - в bccKeysLayoutbccKeysLayout->addWidget(button);Оглавление29else{ // кнопка "=" - помещаем в блок mainKeysLayout после gridLayoutmainKeysLayout->addLayout(gridLayout);mainKeysLayout->addWidget(button);}}// связываем сигнал из m_pSignalMapper о нажатии со слотом clicked// нашего классаconnect(m_pSignalMapper, SIGNAL(mapped(int)),this, SLOT(clicked(int)));// добавляем блоки кнопок в схему выравнивания всей формыdlgLayout->addWidget(m_pLineEdit);dlgLayout->addLayout(bccKeysLayout);dlgLayout->addLayout(mainKeysLayout);// связываем схему выравнивания dlgLayout с формойsetLayout(dlgLayout);// отображаем "0" в поле ввода чисел m_pLineEditsetNumEdit( 0 );};// Обработка нажатия клавишvoid CalcDialog::clicked(int id){ // по идентификатору кнопки ищем действие для выполненияswitch(id){case INVERSE: // унарная операция +/{setNumEdit( getNumEdit() * -1.0 );break;};case DOT:// добавление десятичной точки{// если на экране резульатат предыдущей операции - сброситьcheckOpPerf();QString str =m_pLineEdit->text ();str.append( "." ); // добавляем точку к строкеbool ok = false;// проверяем, является ли результат числом (исключаем 0.1.
)str.toDouble(&ok);// если строка является числом - помещаем резульат в m_pLineEditif( ok ) m_pLineEdit->setText ( str );break;};Оглавление30case DIV: // бинарные арифметические операцииcase MUL:case PLUS:case MINUS:case EQ:{calcPrevOp( id );break;}case CLR_ALL: initNum();// удалить всёcase CLR:{setNumEdit( 0 );// записать в m_pLineEdit число 0break;}case BKSP:{// удалить последний символ// если на экране резульатат предыдущей операции - сброситьcheckOpPerf();QString str =m_pLineEdit->text ();if( str.length() ){// если строка в m_pLineEdit не нулевая - удалить символstr.remove( str.length()-1, 1 );m_pLineEdit->setText ( str );}break;}default:{// обработка цифровых клавиш// если на экране результат предыдущей операции - сброситьcheckOpPerf();QString sId;// сформировать строку по идентификатору нажатой клавишиsId.setNum( id );QString str =m_pLineEdit->text ();if( str == "0" )str = sId; // затираем незначащий нульelsestr.append( sId ); // добавить в m_pLineEdit нажатую цифруm_pLineEdit->setText ( str );}};};Оглавление31// Получить число из m_pLineEditdouble CalcDialog::getNumEdit(){double result;QString str =m_pLineEdit->text ();result = str.toDouble(); // преобразовать строку в числоreturn result;};// записать число в m_pLineEditvoid CalcDialog::setNumEdit( double num ){QString str;str.setNum ( num,'g', 25 ); // преобразовать вещественное число в строкуm_pLineEdit->setText ( str);};// Выполнить предыдущую бинарную операциюvoid CalcDialog::calcPrevOp( int curOp ){// получить число на экране// m_Val хранит число, введенное до нажатия кнопки операцииdouble num = getNumEdit();switch( m_Op ){case DIV:{if ( num != 0) m_Val /= num;else m_Val = 0;break;}case MUL:{m_Val *= num;break;}case PLUS:{m_Val += num;break;}case MINUS:{m_Val -= num;break;}Оглавление32case EQ: { // если была нажата кнопка "=" - не делать ничегоm_Val = num;break; }}m_Op = curOp;// запомнить результат текущей операцииsetNumEdit( m_Val ); // отобразить результатm_bPerf = true;// поставить флаг выполнения операции};void CalcDialog::checkOpPerf(){if( m_bPerf ){// если что-то выполнялось - очистить m_pLineEditm_pLineEdit->clear();m_bPerf = false;};};void CalcDialog::initNum(){m_bPerf = false; m_Val = 0; m_Op = EQ;};В отдельном файле calc.cpp реализуем запуск приложения и создание формыCalcDialog.#include <QApplication>#include "calcDialog.h"int main(int argc, char *argv[]){QApplication app(argc, argv);CalcDialog * dialog = new CalcDialog();dialog->show();// отображаем окноreturn app.exec();// запускаем цикл обработки сообщений}Оглавление33Последний этап – создание проекта для сборки приложения – файл calc.pro.TEMPLATE = appTARGET = calcCONFIG += release# InputHEADERS += calcDialog.hSOURCES += calc.cpp calcDialog.cppСборка проекта производится командами qmake calc.pro и nmake.4.2ЗаданиеДобавьте кнопки, выполняющие:бинарные операции x y , log y x (по аналогии с операциями +,-,/,*), а также унарные sin(x) и cos(x) (по аналогии с операцией -/+) и разместите этот ряд кнопок вертикально, слева от цифровых кнопок с использованием нового объекта выравнивания(Layout).Оглавление3455.1Простейшие элементы ввода-выводаНекоторые средства для ввода и вывода текстаКласс QStringДля работы со строками в Qt используется класс Qstring.
Основной особенностьюэтого класса является то, что внутреннее хранение и все операции над строками проводятся в кодировке UNICODE. Класс позволяет преобразовывать текст из различных кодировок строки в формат C и обратно. Реализуется операции склейки, добавления, сравнения,вырезания подстроки и пр.При работе со строками в Qt следует помнить, что любой текст, в котором присутствуют символы, отличные от основного латинского алфавита (с кодами более 128), следует явно преобразовывать в UNICODE одним из ниже представленных способов.Если программа набирается в кодировке Windows-1251, возможно получениеобъекта кодировщика и его использование:QTextCodec *codec=QtextCodec::codecForName("Windows-1251");QString str = codec->toUnicode( "Некоторый текст" );Второй вариант основан на том, что Qt изначально ориентирована на написаниемногоязычных приложений, следовательно весь текст, написание которого зависит отрегиона использования, должен быть вынесен за пределы кода программы.
Это позволяетв коде программы использовать только латинские символы и специальную функцию tr(...),которая поставит в соответствие тексту, переданному tr некоторую строку на национальном языке. Порядок написания многоязычных приложений следует смотреть в руководстве к QtLingust.QString str = tr("Some text");Класс QLineEditПредставляет собой одиночную строку ввода или вывода данных. Возможно использование в режиме пароля, в котором вводимые символы будут заменяться однимединственным знаком. Предусмотрена возможность отключение режима ввода, позволяятолько отображать данные. На рисунке 20 показаны некоторые элементы ввода-вывода.Оглавление35QLabelQLineEditQLabelQPushButtonQPushButtonQLabelQSpinBoxQTextEditРисунок 20 – Окно приложения Simple Widget Mapper из состава Qt Examples and DemosРассмотрим наиболее часто используемые методы класса. Среди них выделеныслоты, т.е.