Главная · Все классы · Основные классы · Классы по группам · Модули · Функции

[Предыдущий: Урок 9] [Учебное пособие] [Следующий: Урок 11]

Урок 10 - Гладкий как шелк

Файлы:

Снимок экрана к Уроку 10

В этом примере мы добавим контроль силы выстрела.

Разберем программу строка за строкой

t10/cannonfield.h

В дополнение к углу возвышения CannonField содержит теперь и значение силы выстрела.

     int angle() const { return currentAngle; }
     int force() const { return currentForce; }

 public slots:
     void setAngle(int angle);
     void setForce(int force);

 signals:
     void angleChanged(int newAngle);
     void forceChanged(int newForce);

Интерфейс к силе выстрела следует той же практике, что и для угла возвышения.

 private:
     QRect cannonRect() const;

Мы поместили определение ограждающего прямоугольника пушки в отдельную функцию.

     int currentAngle;
     int currentForce;
 };

Сила выстрела запоминается в переменной currentForce.

t10/cannonfield.cpp

 CannonField::CannonField(QWidget *parent)
     : QWidget(parent)
 {
     currentAngle = 45;
     currentForce = 0;
     setPalette(QPalette(QColor(250, 250, 200)));
     setAutoFillBackground(true);
 }

Сила выстрела инициализируется нулем.

 void CannonField::setAngle(int angle)
 {
     if (angle < 5)
         angle = 5;
     if (angle > 70)
         angle = 70;
     if (currentAngle == angle)
         return;
     currentAngle = angle;
     update(cannonRect());
     emit angleChanged(currentAngle);
 }

Мы внесли незначительные изменения в функцию setAngle(). Она перерисовывает только ту часть виджета, в которой находится пушка.

 void CannonField::setForce(int force)
 {
     if (force < 0)
         force = 0;
     if (currentForce == force)
         return;
     currentForce = force;
     emit forceChanged(currentForce);
 }

Реализация функции setForce() довольно похожа на таковую для setAngle(). Единственная разница заключается в том, что поскольку значение силы выстрела мы не показываем, то перерисовывать виджет нам не нужно.

 void CannonField::paintEvent(QPaintEvent * /* event */)
 {
     QPainter painter(this);

     painter.setPen(Qt::NoPen);
     painter.setBrush(Qt::blue);

     painter.translate(0, height());
     painter.drawPie(QRect(-35, -35, 70, 70), 0, 90 * 16);
     painter.rotate(-currentAngle);
     painter.drawRect(QRect(30, -5, 20, 10));
 }

Рисуем как в Уроке 9.

 QRect CannonField::cannonRect() const
 {
     QRect result(0, 0, 50, 50);
     result.moveBottomLeft(rect().bottomLeft());
     return result;
 }

Функция cannonRect() возвращает ограждающий прямоугольник пушки в координатах виджета. Сначала мы создаем прямоугольник с размерами 50 x 50, а затем передвигаем его так, чтобы его нижний левый угол совпадал с нижним левым углом виджета.

Функция QWidget::rect() возвращает ограничивающий прямоугольник виджета в координатах виджета. Верхний левый угол прямоугольника всегда имеет координаты (0, 0).

t10/main.cpp

 MyWidget::MyWidget(QWidget *parent)
     : QWidget(parent)
 {

Конструктор по большей части тот же, но были добавлены несколько кусочков.

     LCDRange *force = new LCDRange;
     force->setRange(10, 50);

Мы добавили второй ЖК-индикатор LCDRange, который будет использоваться для установки силы выстрела.

     connect(force, SIGNAL(valueChanged(int)),
             cannonField, SLOT(setForce(int)));
     connect(cannonField, SIGNAL(forceChanged(int)),
             force, SLOT(setValue(int)));

Мы соединили виджет force и виджет cannonField так же, как сделали для виджета angle.

     QVBoxLayout *leftLayout = new QVBoxLayout;
     leftLayout->addWidget(angle);
     leftLayout->addWidget(force);

     QGridLayout *gridLayout = new QGridLayout;
     gridLayout->addWidget(quit, 0, 0);
     gridLayout->addLayout(leftLayout, 1, 0);
     gridLayout->addWidget(cannonField, 1, 1, 2, 1);
     gridLayout->setColumnStretch(1, 10);

В Уроке 9 мы поместили виджет angle в нижнюю левую ячейку компоновки. Теперь мы хотим иметь два виджета в ячейке, поэтому мы сделали вертикальный прямоугольник, поместили его в ячейку сетки и поместили angle и range в этот прямоугольник.

     force->setValue(25);

Инициализируем силу выстрела значением 25.

Запуск приложения

Теперь мы имеет контроль силы выстрела.

Домашнее задание

Сделайте размер ствола пушки зависящим от силы выстрела.

Поместите пушку в нижний правый угол.

Попытайтесь добавить улучшенный клавиатурный интерфейс. Например, сделайте увеличение и уменьшение силы выстрела с помощью клавиш + и -, а с помощью клавиши enter - выстрел. Если вас не устраивает способ работы клавиш Left и Right, то измените также и его. [Подсказка: Реализуйте заново QWidget::keyPressEvent().]

[Предыдущий: Урок 9] [Учебное пособие] [Следующий: Урок 11]


Copyright © 2008 Trolltech Торговые марки
Qt 4.3.5