自定义 QProgressBar
Posted
技术标签:
【中文标题】自定义 QProgressBar【英文标题】:Customizing QProgressBar 【发布时间】:2016-07-29 14:23:53 【问题描述】:我有一个日记程序,用户可以在其中创建任务,然后为它们添加休息时间。每个Task
对象都有一个QTime start_time
、QTime end_time
和vector
的Break
s。每个Break
都有一个QTime start_time
和QTime end_time
成员,就像Task
一样。我想通过使用自定义QProgressBar
来显示当前任务的进度以显示“时间线”。它应该是一条绿线,由代表中断的红色块分隔,其上方的三角形表示当前进度。这是我的***画作:
要求:三角形应该每分钟左右平稳地向终点移动,而不是跳跃。它还必须根据它是在红色块上还是绿色上来改变它的颜色。该行必须可调整大小,但这不应影响task
s 或break
s 时间变量。用户不能添加多个中断时间。
现在我的问题是,这甚至可能吗?如果是,那怎么办?
我试图做一个没有中断的任务,只画一条绿线和一个没有红色块的三角形,但我立即遇到了调整大小的问题。如果线宽增加,那么三角形的“步长”也应该增加。我试图实现这一点,但没有取得太大的成功。
代码如下:
//class CustomProgressBar: public QProgressBar
void CustomProgressBar::paintEvent(QPaintEvent* event)
setMaximum(this->width());
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPoint start_point;
start_point.setX(0);
start_point.setY(13);
QPoint end_point;
end_point.setY(13);
end_point.setX(this->width()); //has to be resizable
//"TimeLine"
painter.setPen(QPen(Qt::green, 2, Qt::SolidLine, Qt::RoundCap));
painter.drawLine(start_point, end_point);
//Triangle
int progress = this->value();
QPoint triangle_start_point;
triangle_start_point.setX(this->value() + this->width() / 15 + 1);
triangle_start_point.setY(0);
QPoint triangle_bot_point;
triangle_bot_point.setX(this->value() + this->width() / 15 + 6);
triangle_bot_point.setY(10);
QPoint triangle_top_point;
triangle_top_point.setX(this->value() + this->width() / 15 + 11);
triangle_top_point.setY(0);
QPainterPath path;
path.moveTo(triangle_start_point);
path.lineTo(triangle_bot_point);
path.lineTo(triangle_top_point);
path.lineTo(triangle_start_point);
painter.setPen (Qt :: NoPen);
painter.fillPath(path, QBrush(QColor (Qt::green)));
【问题讨论】:
【参考方案1】:我调整了你的绘画事件并扩展了一些简单的格式来显示休息和跑步,看看吧。
QList<QPoint> CustomProgessBar::breaks()
QList<QPoint> times;
times.append(QPoint(0, 20));
times.append(QPoint(20, 50));
times.append(QPoint(50, 80));
times.append(QPoint(80, 100));
return times;
void CustomProgessBar::paintEvent(QPaintEvent *e)
Q_UNUSED(e)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPoint start_point;
start_point.setX(0);
start_point.setY(13);
QPoint end_point;
end_point.setY(13);
end_point.setX(this->width());
//"TimeLine"
for (int i = 0; i < breaks().length(); ++i)
start_point.setX((int)((float)this->width() / 100 * breaks().at(i).x()));
end_point.setX((int)((float)this->width() / 100 * breaks().at(i).y()));
if (i % 2 == 0)
painter.setPen(QPen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap));
else
painter.setPen(QPen(Qt::green, 2, Qt::SolidLine, Qt::RoundCap));
painter.drawLine(start_point, end_point);
//Triangle
QPoint triangle_start_point;
triangle_start_point.setX((int)((float)this->width() / this->maximum() * this->value()) - 5);
triangle_start_point.setY(0);
QPoint triangle_bot_point;
triangle_bot_point.setX((int)((float)this->width() / this->maximum() * this->value()) + 0);
triangle_bot_point.setY(10);
QPoint triangle_top_point;
triangle_top_point.setX((int)((float)this->width() / this->maximum() * this->value()) + 5);
triangle_top_point.setY(0);
QPainterPath path;
path.moveTo(triangle_start_point);
path.lineTo(triangle_bot_point);
path.lineTo(triangle_top_point);
path.lineTo(triangle_start_point);
painter.setPen (Qt :: NoPen);
for (int i = 0; i < breaks().length(); ++i)
int x = (int)((float)triangle_bot_point.x() * 100 / this->width());
if (x >= breaks().at(i).x() && x <= breaks().at(i).y() && i % 2 == 0)
painter.fillPath(path, QBrush(QColor (Qt::red)));
if (x >= breaks().at(i).x() && x <= breaks().at(i).y() && i % 2 == 1)
painter.fillPath(path, QBrush(QColor (Qt::green)));
提到的跳跃是由于整数运算而发生的。转换为浮动和返回可修复此行为。
也不要试图将开始和停止时间紧紧地链接到图表上的开始和停止点。在提供的示例中,我有一个生成百分比值的中间步骤。
【讨论】:
尽管这可行,但它并不能满足所有要求。我肯定会尝试使用“时间轴”和三角形着色部分,但现在我不能接受这个答案。如果我想出一个使用你的代码的工作实现,我会在编辑中发布它并接受你的回答。 @7Y3RPXK3ETDCNRDD 线可调整大小,着色工作,没有啤酒花。哪些要求没有满足?而是为您提供所有课程的完整解决方案,很好地解决了您的问题,让您进一步进步。我不明白你的意思。 您的代码解决了一些问题,但不是全部。三角形表示从task.start_time
到task.end_time
的进度,也就是说,它应该移动恒定的次数,但它的“步长”(它通过每个进度的像素数量)应该随线宽缩放。我还写了Break
s 有start_time
、end_time
并且有一个Break
s 的向量。所以红色块的大小和数量可能会有所不同。也许我的帖子不够明确。如果是这样的话,我很抱歉混淆。但是我还是不能接受你的回答,因为问题还没有完全解决。
@7Y3RPXK3ETDCNRDD 仔细查看方法breaks
,它返回一个QList
,其中包含both、breaks 和progress。每个元素都有可能单独变化的开始和结束。所以这个就完成了。 paint
方法使用一些模 2 操作进行着色,因此每隔一个条目就会中断一次。这只是拥有两种状态的一些简单约定。您也可以轻松地在队列中纠缠另一个中断,请注意所选值与进度条的最大数量相匹配。同样,三角形不是直接移动一个像素,而是恰好移动QProgressBar
的一个值。完成以上是关于自定义 QProgressBar的主要内容,如果未能解决你的问题,请参考以下文章