如何从 Qt 中为 QProgressBar 中的文本获得以下效果?:
我的想法是我必须在进度条的左侧有一个更亮的颜色。
我会按如下方式进行自定义绘图:
从 QLabel 派生您自己的进度条类。
覆盖paintEvent() 函数。
在 paintEvent() 中,使用 QPainter 开始绘制:
你最终应该得到你想要达到的目标。由于 Qt 的默认双缓冲,您应该不会观察到闪烁。
借助这个,
QModernProgressBar.h
#include <QWidget>
#include <QProgressBar>
#include <QPaintEvent>
#include <QStylePainter>
#include <QStyleOption>
#include <QDebug>
class QModernProgressBar : public QProgressBar
{
Q_OBJECT
public:
explicit QModernProgressBar(QWidget *parent = nullptr);
~QModernProgressBar() Q_DECL_OVERRIDE;
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
public:
virtual QString text() const Q_DECL_OVERRIDE;
};
QModernProgressBar.cpp
#include "QModernProgressBar.h"
QModernProgressBar::QModernProgressBar(QWidget *parent) : QProgressBar(parent) {}
QModernProgressBar::~QModernProgressBar() {}
/* https://www.qtcentre.org/threads/70885-QProgressBar-with-in-decimal */
QString QModernProgressBar::text() const
{
QString result = format();
if(minimum() ==0 && maximum()==0)
{
if(result=="%p%")
{
return QString("");
}
else
{
return result;
}
}
else if ( minimum() == maximum() )
{
return QString("");
}
if(result.isEmpty())
{
return QString("%p%");
}
else
{
return result;
}
}
void QModernProgressBar::paintEvent(QPaintEvent *ev)
{
Q_UNUSED(ev)
QStylePainter paint(this);
QStyleOptionProgressBar opt;
initStyleOption(&opt);
paint.drawControl(QStyle::CE_ProgressBarGroove, opt);
paint.drawControl(QStyle::CE_ProgressBarContents, opt);
const QStyleOptionProgressBar *option = &opt;
QStylePainter *painter = &paint;
// Stolen from QFusionStyle::drawControl
if (const QStyleOptionProgressBar *pbar = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
{
QRect leftRect;
QRect rect = pbar->rect;
QColor textColor = option->palette.text().color();
QColor alternateTextColor = option->palette.window().color();
painter->save();
bool vertical = false, inverted = false;
vertical = (pbar->orientation == Qt::Vertical);
inverted = pbar->invertedAppearance;
if (vertical)
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width());
const auto totalSteps = qMax(Q_INT64_C(1), qint64(pbar->maximum) - pbar->minimum);
const auto progressSteps = qint64(pbar->progress) - pbar->minimum;
const int progressIndicatorPos = static_cast<int>(progressSteps * rect.width() / totalSteps);
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
if (vertical)
leftRect.translate(rect.width() - progressIndicatorPos, 0);
bool flip = (!vertical && (((pbar->direction == Qt::RightToLeft) && !inverted) ||
((pbar->direction == Qt::LeftToRight) && inverted)));
QString formattedText = pbar->text;
formattedText.replace(QLatin1String("%m"), QString("%1").arg(totalSteps));
const auto progress = static_cast<int>((qint64(value()) - pbar->minimum) * 100.0 / totalSteps);
formattedText.replace(QLatin1String("%p"), QString("%1").arg(progress));
QRegion rightRect = rect;
rightRect = rightRect.subtracted(leftRect);
painter->setClipRegion(rightRect);
painter->setPen(flip ? alternateTextColor : textColor);
painter->drawText(rect, formattedText, QTextOption(Qt::AlignAbsolute |
Qt::AlignHCenter |
Qt::AlignVCenter));
if (!leftRect.isNull())
{
painter->setPen(flip ? textColor : alternateTextColor);
painter->setClipRect(leftRect);
painter->drawText(rect, formattedText, QTextOption(Qt::AlignAbsolute |
Qt::AlignHCenter |
Qt::AlignVCenter));
}
painter->restore();
}
}
main.cpp
#include <QApplication>
#include <QTimer>
#include <QTextStream>
#include <QTimer>
#include <QDebug>
#include <QVBoxLayout>
#include "QModernProgressBar.h"
int main(int argc, char* argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setApplicationName("QModernProgressbar Demo");
QApplication app(argc, argv);
app.setStyleSheet(QLatin1String(" \
QProgressBar { \
font-family : Fira Code; \
font-size : 12pt; \
font-style : normal; \
font-weight : bold; \
color : rgba(8, 218, 157, 100%); \
border : 1px solid rgba(8, 218, 157, 100%); \
border-radius : 0px; \
text-align : center; \
} \
\
QProgressBar::chunk { \
background-color : rgba(8, 218, 157, 100%); \
width : 1px; \
text-align : center; \
}")); \
QTimer timer;
QWidget mainWindow;
InvertProgressBar w1, w2, w3;
w1.setTextVisible(true);
w2.setTextVisible(true);
w3.setTextVisible(true);
int i=25;
int j=0;
w1.setRange(0,25);
w2.setRange(0,100);
w3.setRange(0,0);
w1.setFormat(QString("Searching... Timing out in %1 seconds.").arg(i));
w2.setFormat(QString("Flashing the controller ..."));
w3.setFormat(QString("Rebooting the controller ..."));
QVBoxLayout *finalLayout = new QVBoxLayout;
QObject::connect(&timer, &QTimer::timeout, [&]() {
w1.setFormat(QString("Searching... Timing out in %1 seconds...").arg(i));
w1.setValue(i);
if(--i==-1)
{
i=25;
}
w2.setFormat(QString("Flashing the controller ...%p%"));
w2.setValue(j);
if(j++==101)
{
j=0;
}
}
);
timer.start(500);
finalLayout->addWidget(&w1);
finalLayout->addWidget(&w2);
finalLayout->addWidget(&w3);
mainWindow.setFixedSize(500,150);
mainWindow.setLayout(finalLayout);
mainWindow.show();
return app.exec();
}
请注意,当忙指示灯亮时,双音文本无效。