Qt 使用 kdChart 自定义甘特图

  Qt绘制甘特图,网上找了很久,只找到kdChart,编译很简单,我是Qt 5.5.0 + VS2013,直接编译就行,kdChart有甘特图例子:

但是和项目设计有点出入,所以自定义部分显示:

 

1.左边的是QTreeView,并为其添加委托,控件变化主要是通过QStandardItem->setData()来区别,这没什么说的,主要记录修改颜色和获取甘特图item拖动事件

(1).修改颜色(可实现每个item的颜色都不一样):

 这是设置每个item的颜色:

topitem->setData(249, KDGantt::ItemColor_R);
topitem->setData(171, KDGantt::ItemColor_G);
topitem->setData(82, KDGantt::ItemColor_B);

kdChart中,颜色的修改是:

void ItemDelegate::paintGanttItem( QPainter* painter,
                                   const StyleOptionGanttItem& opt,
                                   const QModelIndex& idx )

函数修改:

void ItemDelegate::paintGanttItem( QPainter* painter,
                                   const StyleOptionGanttItem& opt,
                                   const QModelIndex& idx )
{
    if ( !idx.isValid() ) return;

    const ItemType typ = static_cast<ItemType>( idx.model()->data( idx, ItemTypeRole ).toInt() );
    const QString& txt = opt.text;
    QRectF itemRect = opt.itemRect;
    QRectF boundingRect = opt.boundingRect;
    boundingRect.setY( itemRect.y() );
    boundingRect.setHeight( itemRect.height() );
    painter->save();

    int color_r = idx.model()->data( idx, ItemColor_R ).toInt();
    int color_g = idx.model()->data( idx, ItemColor_G ).toInt();
    int color_b = idx.model()->data( idx, ItemColor_B ).toInt();

    QColor itemColor(color_r, color_g, color_b);

    QPen pen(itemColor);
    if ( opt.state & QStyle::State_Selected ) pen.setWidth( 2*pen.width() );
    painter->setPen( pen );
    painter->setBrush( QBrush(Qt::white, Qt::Dense1Pattern) );

    bool drawText = true;
    qreal pw = painter->pen().width()/2.;
    switch ( typ ) {
    case TypeTask:
        if ( itemRect.isValid() ) {
            // TODO
            qreal pw = painter->pen().width()/2.;
            pw-=1;
            QRectF r = itemRect;
            r.translate( 0., r.height()/6. );
            r.setHeight( 2.*r.height()/3. );
            painter->setBrushOrigin( itemRect.topLeft() );
            painter->save();
            painter->translate( 0.5, 0.5 );
            painter->drawRect( r );
            bool ok;
            qreal completion = idx.model()->data( idx, KDGantt::TaskCompletionRole ).toReal( &ok );
            if ( ok ) {
                qreal h = r.height();
                QRectF cr( r.x(), r.y()+h/4.,
                           r.width()*completion/100., h/2.+1 /*??*/ );
                QColor compcolor( painter->pen().color() );
                compcolor.setAlpha( 150 );
                painter->fillRect( cr, compcolor );
            }
            painter->restore();
        }
        break;
    case TypeSummary:
        if ( opt.itemRect.isValid() ) {
            // TODO
            pw-=1;
            const QRectF r = QRectF( opt.itemRect ).adjusted( -pw, -pw, pw, pw );
            QPainterPath path;
            const qreal deltaY = r.height()/2.;
            const qreal deltaXBezierControl = .25*qMin( r.width(), r.height() );
            const qreal deltaX = qMin( r.width()/2., r.height() );
            path.moveTo( r.topLeft() );
            path.lineTo( r.topRight() );
            path.lineTo( QPointF( r.right(), r.top() + 2.*deltaY ) );
            //path.lineTo( QPointF( r.right()-3./2.*delta, r.top() + delta ) );
            path.quadTo( QPointF( r.right()-deltaXBezierControl, r.top() + deltaY ), QPointF( r.right()-deltaX, r.top() + deltaY ) );
            //path.lineTo( QPointF( r.left()+3./2.*delta, r.top() + delta ) );
            path.lineTo( QPointF( r.left() + deltaX, r.top() + deltaY ) );
            path.quadTo( QPointF( r.left()+deltaXBezierControl, r.top() + deltaY ), QPointF( r.left(), r.top() + 2.*deltaY ) );
            path.closeSubpath();
            painter->setBrushOrigin( itemRect.topLeft() );
            painter->save();
            painter->translate( 0.5, 0.5 );
            painter->drawPath( path );
            painter->restore();
        }
        break;
    case TypeEvent: /* TODO */
        //qDebug() << opt.boundingRect << opt.itemRect;
        if ( opt.boundingRect.isValid() ) {
            const qreal pw = painter->pen().width() / 2. - 1;
            const QRectF r = QRectF( opt.itemRect ).adjusted( -pw, -pw, pw, pw ).translated( -opt.itemRect.height()/2, 0 );
            QPainterPath path;
            const qreal delta = static_cast< int >( r.height() / 2 );
            path.moveTo( delta, 0. );
            path.lineTo( 2.*delta, delta );
            path.lineTo( delta, 2.*delta );
            path.lineTo( 0., delta );
            path.closeSubpath();
            painter->save();
            painter->translate( r.topLeft() );
            painter->translate( 0, 0.5 );
            painter->drawPath( path );
            painter->restore();
#if 0
            painter->setBrush( Qt::NoBrush );
            painter->setPen( Qt::black );
            painter->drawRect( opt.boundingRect );
            painter->setPen( Qt::red );
            painter->drawRect( r );
#endif
        }
        break;
    default:
        drawText = false;
        break;
    }

    Qt::Alignment ta;
    switch ( opt.displayPosition ) {
        case StyleOptionGanttItem::Left: ta = Qt::AlignLeft; break;
        case StyleOptionGanttItem::Right: ta = Qt::AlignRight; break;
        case StyleOptionGanttItem::Center: ta = Qt::AlignCenter; break;
        case StyleOptionGanttItem::Hidden: drawText = false; break;
    }
    if ( drawText ) {
        painter->drawText( boundingRect, ta | Qt::AlignVCenter, txt );
    }

    painter->restore();
}

(2).拖动事件:

 在文件kdganttgraphicsview.h中添加信号

void signal_dataChanged( const QModelIndex & index );
void GraphicsView::Private::slotDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight )
{
    const QModelIndex parent = topLeft.parent();
    for ( int row = topLeft.row(); row <= bottomRight.row(); ++row ) {
        scene.updateRow( scene.summaryHandlingModel()->index( row, 0, parent ) );
    }

    emit q->signal_dataChanged(topLeft);
}

外部使用:

connect(ui->ganttView->graphicsView(), SIGNAL(signal_dataChanged(const QModelIndex&)), this, SLOT(onCheckTask(const QModelIndex&)));

 

修改显示的日期格式,效果:

上面显示年月,下面显示多少号,显示号很简单:

grid.setUserDefinedLowerScale(new KDGantt::DateTimeScaleFormatter(KDGantt::DateTimeScaleFormatter::Day,QString::fromLatin1("dd"),QString::fromLatin1("%1"),Qt::AlignHCenter));

其中有个格式:QString::fromLatin1("dd"),dd:号, ddd:星期几

使用这个函数,只能显示年或者月或者天,不能组合显示,所有重写DateTimeScaleFormatter;

class MyDateTimeScaleFormatter : public KDGantt::DateTimeScaleFormatter 
{
public:
    MyDateTimeScaleFormatter() : DateTimeScaleFormatter(Month, "MM"){}

    /*reimp*/QDateTime nextRangeBegin(const QDateTime& datetime) const
    {
        return currentRangeBegin(datetime).addMonths(1);
    }
    /*reimp*/QDateTime currentRangeBegin(const QDateTime& datetime) const
    {
        return datetime;
    }

    /*reimp*/QString text(const QDateTime& dt) const
    {
        return QObject::tr("%1年%2月").arg(dt.date().year()).arg(dt.date().month());
    }
};
grid.setUserDefinedUpperScale(new MyDateTimeScaleFormatter()); // 显示在上面

 

 

转载请保留出处!

 

posted @ 2017-10-18 10:41  积跬步,到千里  阅读(6079)  评论(1编辑  收藏  举报