好的,我可以帮你整理一份 Qt 实战教程:第16章 构建甘特图 的思路与实现方法。这里我会把步骤、关键类、绘图思路和示例代码都整理出来,方便你快速上手。


Qt 实战 16:构建甘特图

一、甘特图概述

甘特图(Gantt Chart)是一种常用的项目管理工具,用于展示任务的时间进度和依赖关系。
特点:

  • 横轴:时间轴
  • 纵轴:任务列表
  • 图形表示:任务条、完成比例、里程碑、依赖关系箭头

在 Qt 中,常用 QGraphicsView / QGraphicsSceneQTableView + 自定义绘制 来实现甘特图。


二、关键技术点

  1. 任务数据模型
    • 定义任务类 Task:
    class Task { public: QString name; QDate startDate; QDate endDate; double progress; // 0.0~1.0 QList<Task*> dependencies; };
    • 可以用 QListQStandardItemModel 保存任务列表。
  2. 时间轴映射
    • 将日期映射到横坐标:
    int dayWidth = 20; // 每天的像素宽度 int x = (task.startDate.toJulianDay() - projectStartDate.toJulianDay()) * dayWidth; int width = (task.endDate.toJulianDay() - task.startDate.toJulianDay()) * dayWidth;
  3. 绘制任务条
    • 使用 QGraphicsRectItemQPainter 绘制任务条:
    QGraphicsRectItem *rect = scene->addRect(x, y, width, taskHeight, pen, brush);
    • 可使用 不同颜色表示任务状态
      • 绿色:已完成
      • 蓝色:进行中
      • 灰色:未开始
  4. 绘制依赖箭头
    • 使用 QGraphicsLineItemQPainterPath 画箭头:
    QGraphicsLineItem *line = scene->addLine(x1, y1, x2, y2, pen);
    • 可以添加三角形箭头表示依赖方向。
  5. 绘制时间刻度
    • 横轴显示日期:
    for (QDate date = projectStartDate; date <= projectEndDate; date = date.addDays(1)) { int x = (date.toJulianDay() - projectStartDate.toJulianDay()) * dayWidth; scene->addLine(x, 0, x, 20, pen); // 刻度线 scene->addText(date.toString("MM-dd"))->setPos(x, 0); }
  6. 任务滚动和缩放
    • 使用 QGraphicsViewsetHorizontalScrollBarPolicy / setVerticalScrollBarPolicy
    • 支持鼠标滚轮缩放时间轴(可用 QTransform 缩放)

三、示例代码(核心部分)

// main.cpp
#include &lt;QApplication>
#include &lt;QGraphicsView>
#include &lt;QGraphicsScene>
#include &lt;QDate>
#include &lt;QBrush>

struct Task {
    QString name;
    QDate startDate;
    QDate endDate;
    double progress; // 0~1
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&amp;scene);

    int dayWidth = 20;
    int taskHeight = 20;
    QDate projectStart = QDate::currentDate();

    QList&lt;Task> tasks = {
        {"Task 1", projectStart, projectStart.addDays(5), 0.5},
        {"Task 2", projectStart.addDays(3), projectStart.addDays(10), 0.2},
        {"Task 3", projectStart.addDays(6), projectStart.addDays(12), 0.0}
    };

    int y = 30;
    for (const Task &amp;task : tasks) {
        int x = (task.startDate.toJulianDay() - projectStart.toJulianDay()) * dayWidth;
        int width = (task.endDate.toJulianDay() - task.startDate.toJulianDay()) * dayWidth;

        QGraphicsRectItem *rect = scene.addRect(x, y, width, taskHeight, QPen(Qt::black), QBrush(Qt::blue));
        // 绘制完成进度
        scene.addRect(x, y, width*task.progress, taskHeight, Qt::NoPen, QBrush(Qt::green));

        y += taskHeight + 10;
    }

    view.setScene(&amp;scene);
    view.setWindowTitle("Qt 甘特图示例");
    view.show();

    return a.exec();
}

✅ 特点:

  • 支持基本任务条显示
  • 绘制任务完成进度
  • 横向时间映射到像素

四、扩展功能建议

  1. 里程碑标记
    • 使用三角形或小圆点表示关键时间点。
  2. 任务拖动修改
    • 为 QGraphicsRectItem 添加 鼠标事件,拖动修改开始/结束时间。
  3. 多行任务显示
    • 支持任务嵌套或子任务,用缩进或颜色区分。
  4. 数据导入导出
    • 从 JSON / XML / CSV 导入任务
    • 支持导出甘特图为 PNG / PDF
  5. UI 美化
    • 使用渐变填充任务条
    • 支持主题切换(暗色模式/浅色模式)