Перенос слов на новую строку в подписи - Виджеты в Qt. Часть 7
Сегодня мы реализуем для нашего виджета довольно востребованный функционал – перенос слов на новую строку.
Мы будем использовать проект из предыдущей статьи.
Очистка проекта
Сперва очистим проект от лишнего кода и внесем некоторые изменения:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout *vlay = new QVBoxLayout();
QHBoxLayout *hlay1 = new QHBoxLayout();
QLampWidget *lamp1 = new QLampWidget("#557d00","#F00",QLampWidget::on, 32, "2");
lamp1->setCaption("Left Right Top Bottom");
lamp1->setCaptionAlign(Qt::TextWordWrap);
hlay1->addWidget(lamp1);
QLampWidget *lamp2 = new QLampWidget("#557d00","#F00",QLampWidget::on, 64, "2");
lamp2->setCaption("Left Right Top Bottom");
lamp2->setCaptionAlign(Qt::TextWordWrap);
hlay1->addWidget(lamp2);
hlay1->addStretch(1);
vlay->addItem(hlay1);
QHBoxLayout *hlay3 = new QHBoxLayout();
QLampWidget *lamp3 = new QLampWidget("#557d00","#F00",QLampWidget::on, 96, "2");
lamp3->setCaption("Left Right Top Bottom");
lamp3->setCaptionAlign(Qt::TextWordWrap);
hlay3->addWidget(lamp3);
hlay3->addStretch(1);
vlay->addItem(hlay3);
QHBoxLayout *hlay4 = new QHBoxLayout();
QLampWidget *lamp4 = new QLampWidget("#557d00","#F00",QLampWidget::on, 128, "2");
lamp4->setCaption("Left Right Top Bottom");
lamp4->setCaptionAlign(Qt::TextWordWrap);
hlay4->addWidget(lamp4);
hlay4->addStretch(1);
vlay->addItem(hlay4);
vlay->addStretch(1);
ui->centralwidget->setLayout(vlay);
}
В методе paintEvent() уберем все умножения на *2
void QLampWidget::paintEvent(QPaintEvent *event)
{
installEventFilter(this);
QString onColor = this->color;
QColor mainColorOn = QColor(onColor);
QColor subColorOn = QColor(onColor);
subColorOn.setHsl(0,100,95,0);
QString aoffColor = this->offColor;
QColor mainColorOff = QColor(aoffColor);
QColor subColorOff = QColor(aoffColor);
subColorOff.setHsl(0,100,95,0);
QPainter painter(this);
painter.setFont(this->captionFont);
QFontMetrics metrics(painter.font());
int heightOfText = metrics.height();
this->setFixedHeight(this->getLampSize()+heightOfText);
int widthOfText = metrics.horizontalAdvance(this->getCaption());
float xPos = 0;
if (widthOfText > this->getLampSize())
{
this->setFixedWidth(widthOfText);
xPos = widthOfText / 2 - (this->getLampSize()-8) / 2;
}
else
{
xPos = 4;
this->setFixedWidth(this->getLampSize());
}
QLinearGradient linearGrad(
QPointF(xPos,
4),
QPointF(xPos + this->getLampSize()-8,
this->getLampSize()-8));
if (this->getStatus()==QLampWidget::on)
{
linearGrad.setColorAt(0, subColorOn);
linearGrad.setColorAt(1, mainColorOn);
} else {
linearGrad.setColorAt(0, subColorOff);
linearGrad.setColorAt(1, mainColorOff);
}
QRect r;
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(QColor("#f00"), 0.1));
painter.setBrush(linearGrad);
painter.drawEllipse(
QRectF(xPos, 4,
this->getLampSize()-8, this->getLampSize()-8));
painter.setBrush(QBrush(QColor(157,255,252,127)));
QPen pen;
pen.setStyle(Qt::DashLine);
painter.setPen(pen);
QRect border = QRect(0,this->getLampSize(),
this->getLampSize(), heightOfText);
painter.drawRect(border);
painter.setPen(QPen(QColor(this->captionColor), 1));
painter.drawText(0,this->getLampSize(),
this->getLampSize(), heightOfText,
this->getCaptionAlign(),
this->getCaption(),
new QRect(0,this->getLampSize(),this->getLampSize(), heightOfText));
}
Запустим:
Как видите у нас есть надпись, но она обрезается по ширине, к тому же всплыл неприятный баг с шириной виджета, так как она у нас зависит от ширины текста. Давайте это исправим.
Перенос по словам
У класса QFontMetrics есть метод
QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &text, int tabStops = 0, int *tabArray = nullptr) const
Который возвращает размеры прямоугольника - QRect, в котором поместиться текст - text, нарисованный в прямоугольнике rect, с флагами flag. Параметр tabStops в данном случае, всегда будет равен 0, а tabArray равен nullptr, поэтому мы их не указываем.
Особенность метода состоит в том, что если мы используем флаг Qt::TextWordWrap, то возвращаемый прямоугольник будет автоматически расширен по высоте на нужное количество строк, а это нам и нужно!
Внесем изменения в метод
После
QFontMetrics metrics(painter.font());
Добавим
QRect bRect = metrics.boundingRect(QRect(0,0,this->getLampSize(),32),this->getCaptionAlign(),this->getCaption());;
Изменим строки
int heightOfText = bRect.height();
и
int widthOfText = bRect.width();
Заменим код
if (widthOfText > this->getLampSize())
{
this->setFixedWidth(widthOfText);
xPos = widthOfText / 2 - (this->getLampSize()-8) / 2;
}
else
{
xPos = 4;
this->setFixedWidth(this->getLampSize());
}
на
if (widthOfText > this->getLampSize())
{
this->setFixedWidth(bRect.width());
}
else
{
this->setFixedWidth(this->getLampSize());
}
Запустим:
На этот раз всё работает как надо.
Использование Qt::TextWordWrap
Вы можете использовать Qt::TextWordWrap совместно с флагами выравнивания, например у вас может получиться следующее:
QLampWidget *lamp1 = new QLampWidget("#557d00","#F00",QLampWidget::on, 32, "2");
lamp1->setCaption("Left Right Top Bottom");
lamp1->setCaptionAlign(Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter);
hlay1->addWidget(lamp1);
QLampWidget *lamp2 = new QLampWidget("#557d00","#F00",QLampWidget::on, 64, "2");
lamp2->setCaption("Left Right Top Bottom");
lamp2->setCaptionAlign(Qt::TextWordWrap | Qt::AlignRight);
hlay1->addWidget(lamp2);
hlay1->addStretch(1);
vlay->addItem(hlay1);
QHBoxLayout *hlay3 = new QHBoxLayout();
QLampWidget *lamp3 = new QLampWidget("#557d00","#F00",QLampWidget::on, 96, "2");
lamp3->setCaption("Left Right Top Bottom");
lamp3->setCaptionAlign(Qt::TextWordWrap | Qt::AlignRight);
hlay3->addWidget(lamp3);
hlay3->addStretch(1);
vlay->addItem(hlay3);
QHBoxLayout *hlay4 = new QHBoxLayout();
QLampWidget *lamp4 = new QLampWidget("#557d00","#F00",QLampWidget::on, 128, "2");
lamp4->setCaption("Left Right Top Bottom");
lamp4->setCaptionAlign(Qt::TextWordWrap | Qt::AlignCenter);
hlay4->addWidget(lamp4);
Запустим:
Заключение
Сегодня мы реализовали функционал для переноса слова на новую строку в случае, если оно не умещается по ширине и исправили еще один баг в нашем виджете.
Исходный код проекта вы можете найти на GitFlic.
Добавить комментарий