[Предыдущий: Урок 9] [Учебное пособие] [Следующий: Урок 11]
Урок 10 - Гладкий как шелк
Файлы:
В этом примере мы добавим контроль силы выстрела.
Разберем программу строка за строкой
В дополнение к углу возвышения 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.
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 * )
{
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).
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]
|