自定义QProgressBar

3
我有一个日记程序,用户可以在其中创建任务,并添加休息时间。每个“任务”对象都有一个“QTime start_time”,一个“QTime end_time”和一个“Breaks”向量。“Break”具有“QTime start_time”和“QTime end_time”成员,就像“Task”一样。我希望通过使用自定义的“QProgressBar”来展示当前任务的进度“时间轴”。它应该是一个绿色的线段,由红色块分隔,表示休息,并且在其上方有一个三角形表示当前进度。这是我的高质量绘图:
enter image description here

要求:三角形应平滑地每分钟或更长时间向末尾移动,而不是跳跃。它还必须根据它是否在红色块或绿色区域中而改变颜色。该线条必须可调整大小,但不应影响任务或休息的时间变量。用户不能添加连续时间的多个休息。
现在我的问题是,这是否可能?如果是,则如何实现?
我尝试制作没有红块的任务,仅绘制绿色线和三角形,但我立即遇到了调整大小的问题。如果线的宽度增加,则三角形的“步骤”每分钟应该也会增加。我尝试实现了这一点,但没有取得很大的成功。
下面是代码:

//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个回答

2

我修改了你的绘画事件,并增加了一些简单的格式来显示换行和运行情况,请查看。

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)));
    }
}

由于整数算术运算,会出现上述提到的跳跃。将其转换为浮点数再转回来可以解决这种情况。


另外,不要试图将开始和结束时间与图表上的起始点和终止点过于紧密地联系在一起。在提供的示例中,我有一个中间步骤,可以计算百分比值。


尽管这个方法可行,但仍然不符合所有要求。我一定会尝试使用“时间轴”和三角形着色的部分,但目前我无法接受这个答案。如果我能想出一个使用你的代码的可行实现,我将在编辑中发布它并接受你的答案。 - Chechen Itza
@7Y3RPXK3ETDCNRDD 这一行可以调整大小,颜色也能正常显示,没有任何问题。哪些要求没有被满足?我不会给你一个完整的解决方案,而是提供答案来解决你的问题,让你进一步进展。我不明白你的观点。 - maxik
你的代码解决了一些问题,但并非全部。三角形表示从task.start_timetask.end_time的进度,即它应该移动固定次数,但其“步长”(每次进展通过的像素数量)应随线宽缩放。我还写道Break具有start_timeend_time以及Break向量。所以红色块的大小和数量可能会有所变化。也许我的帖子表述不够清楚,如果是这样,我对造成的困扰很抱歉。但我仍然无法接受你的答案,因为问题尚未完全解决。 - Chechen Itza
请仔细查看breaks方法,它返回一个包含断点和进度的QList。每个元素都有可能有不同的起始和结束。所以这个已经完成了。paint方法使用一些模2运算进行着色,因此每隔一个条目就是一个断点。这只是为了同时拥有两种状态的一些简单约定。您还可以轻松地在队列中添加另一个断点,请注意所选的值与进度条的最大值匹配。而且,三角形移动的不是直接一个像素,而是QProgressBar的一个确切的。完成。 - maxik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接