Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

В данном разделе мы рассмотрим программный код клиента и сервера, которые используют пользовательский протокол блочной передачи. Клиент называется Trip Planner (планировщик путешествий) и позволяет пользователям составлять план путешествия на поезде. Сервер называется Trip Server (сервер путешествий) и обеспечивает клиента информацией о путешествии. Мы начнем с написания клиентского приложения Trip Planner.

Приложение Trip Planner содержит поле From (из пункта), поле To (до пункта), поле Date (дата), поле Approximate Time (приблизительное время) и два переключателя, определяющие приблизительное время отправления или прибытия. Когда пользователь нажимает клавишу Search, приложение посылает запрос на сервер, который возвращает список железнодорожных рейсов, которые удовлетворяют критериям пользователя.

Этот список отображается в виджете QTableWidget в окне Trip Planner. В нижней части окна расположены текстовая метка QLabel, показывающая состояние последней операции, и индикатор состояния процесса QProgressBar.

Рис. 14.1. ПриложениеТпр Planner.

Пользовательский интерфейс приложения Trip Planner был создан при помощи QtDesigner в файле tripplanner.ui. Ниже мы основное внимание уделим исходному коду подкласса QDialog, который реализует функциональность приложения:

#include "ui_tripplanner.h"

01 class TripPlanner : public QDialog, public Ui::TripPlanner

02 {

03 Q_OBJECT

04 public:

05 TripPlanner(QWidget *parent = 0);

06 private slots:

07 void connectToServer;

08 void sendRequest;

09 void updateTableWidget;

10 void stopSearch;

11 void connectionClosedByServer;

12 void error;

13 private:

14 void closeConnection;

15 QTcpSocket tcpSocket;

16 quint16 nextBlockSize;

17 };

Класс TripPlanner наследует не только QDialog, но и Ui::TripPlanner (который генерируется компилятором uic, используя файл tripplanner.ui). Переменная—член tcpSocket инкапсулирует соединение TCP. Переменная nextBlockSize используется при синтаксическом анализе блоков, поступивших с сервера.

01 TripPlanner::TripPlanner(QWidget *parent)

02 : QDialog(parent)

03 {

04 setupUi(this);

05 QDateTime dateTime = QDateTime::currentDateTime;

06 dateEdit->setDate(dateTime.date);

07 timeEdit->setTime(QTime(dateTime.time.hour, 0));

08 progressBar->hide;

09 progressBar->setSizePolicy(QSizePolicy::Preferred,

10 QSizePolicy::Ignored);

11 tableWidget->verticalHeader->hide;

12 tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

13 connect(searchButton, SIGNAL(clicked),

14 this, SLOT(connectToServer));

15 connect(stopButton, SIGNAL(clicked), this, SLOT(stopSearch));

16 connect(&tcpSocket, SIGNAL(connected),

17 this, SLOT(sendRequest));

18 connect(&tcpSocket, SIGNAL(disconnected),

19 this, SLOT(connectionClosedByServer));

20 connect(&tcpSocket, SIGNAL(readyRead),

21 this, SLOT(updateTableWidget));

22 connect(&tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),

23 this, SLOT(error));

24 }

В

конструкторе мы инициализируем поля редактирования даты и времени текущей датой и временем. Мы также не показываем индикатор состояния программы, потому что он необходим только при активном соединении. В Qt Designer свойства minimum и maximum индикатора состояния устанавливались в 0. Это определяет поведение QProgressBar как индикатора занятости вместо стандартного индикатора, показывающего процент выполнения работы.

В конструкторе мы также связываем сигналы connected, disconnected, readyRead и error(QAbstractSocket::SocketError) класса QTcpSocket с закрытыми слотами.

01 void TripPlanner::connectToServer

02 {

03 tcpSocket.connectToHost("tripserver.zugbahn.de", 6178);

04 tableWidget->setRowCount(0);

05 searchButton->setEnabled(false);

06 stopButton->setEnabled(true);

07 statusLabel->setText(tr("Connecting to server..."));

08 progressBar->show;

09 nextBlockSize = 0;

10 }

Слот connectToServer выполняется, когда пользователь нажимает клавишу Search для запуска процедуры поиска. Мы вызываем функцию connectToHost объекта типа QTcpSocket для подсоединения к серверу, который, как мы предполагаем, доступен через порт 6178 по вымышленному адресу хоста tripserver.zugbahn.de. (Если вы собираетесь проверить работу этого примера на вашей машине, замените имя хоста на QHostAddress::LocalHost.) Вызов connectToHost выполняется асинхронно; эта функция всегда немедленно возвращает управление. Соединение обычно устанавливается позже. Объект QTcpSocket генерирует сигнал connected, если соединение успешно осуществлено и действует, или error(QAbstractSocket::SocketError), если соединение завершилось неудачей.

Затем мы обновляем интерфейс пользователя, в частности делаем видимым индикатор состояния приложения.

Наконец, мы устанавливаем переменную nextBlockSize на 0. Эта переменная содержит длину следующего блока, полученного от сервера. Мы задали значение 0, поскольку еще не знаем размер следующего блока.

01 void TripPlanner::sendRequest

02 {

03 QByteArray block;

04 QDataStream out(&block, QIODevice::WriteOnly);

05 out.setVersion(QDataStream::Qt_4_1);

06 out << quint16(0) << quint8('S') << fromComboBox->currentText

07 << toComboBox->currentText << dateEdit->date

08 << timeEdit->time;

09 if (departureRadioButton->isChecked) {

10 out << quint8('D');

11 } else {

12 out << quint8('A');

Поделиться с друзьями: