将水平滑块添加到QTableWidget

时间:2018-07-09 14:36:38

标签: c++ qt qt5 qtablewidget qgraphicsrectitem

我正在尝试为视频播放器设计类似时间轴视图的内容。我决定使用QTableWidget作为时间表,因为它适合我的目的。我的小部件看起来像这样:

enter image description here

当我单击播放时,我希望绿线贯穿小部件。这是我的MVCE示例:

//View.cpp

View::View(QWidget* parent) :  QGraphicsView(parent)
{
    QGraphicsScene* scene = new QGraphicsScene(this);

    TableWidget* wgt = new TableWidget;

    scene->addWidget(wgt);

    QGraphicsLineItem* item = new QGraphicsLineItem(30, 12, 30, wgt->height() - 9);
    item->setPen(QPen(QBrush(Qt::green), 3));
    item->setFlags(QGraphicsItem::ItemIsMovable);
    scene->addItem(item);

    setScene(scene);
}

这里是TableWidget

TableWidget::TableWidget(QWidget* parent) : QTableWidget(parent)
{
    setColumnCount(10);
    setRowCount(10);

    //Hides the numbers on the left side of the table
    verticalHeader()->hide();

    //Prevents top header from highlighting on selection
    horizontalHeader()->setHighlightSections(false);

    //Makes the cells un-editable
    setEditTriggers(QAbstractItemView::NoEditTriggers);

    setSelectionMode(QAbstractItemView::MultiSelection);
}

问题:

移动订单项会反映对已添加到场景中的更改,即当我使用鼠标拖动该行时,该行会在场景中移动,但不会在TableWidget内部移动。

我想要什么

我希望绿色条像水平滑块一样工作。它应该水平通过TableWidget,使小部件随其一起滚动,并显示由标题上显示的数字指示的框架的当前位置。

如下所示(注意红线):

The Red line

我知道这可能不是实现时间表的最佳方法,但是我将不胜感激任何其他想法。

1 个答案:

答案 0 :(得分:0)

可能的解决方案是覆盖itemChange方法以限制移动,如下所示:

#include <QApplication>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QTableWidget>
#include <QHeaderView>
#include <QGraphicsProxyWidget>

class SeekBarItem: public QGraphicsRectItem{
public:
    SeekBarItem(QRectF rect, QGraphicsItem *parent=nullptr)
        : QGraphicsRectItem(rect, parent)
    {
        setFlag(QGraphicsItem::ItemIsMovable, true);
        setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
        setBrush(Qt::red);
    }
protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value){
        if(change == QGraphicsItem::ItemPositionChange){
            QPointF p = value.toPointF();

            qreal max = parentItem()->boundingRect().bottom()- boundingRect().bottom();
            qreal min = parentItem()->boundingRect().top()-boundingRect().top();

            if(p.y() > max) p.setY(max);
            else if (p.y() < min) p.setY(min);
            p.setX(pos().x());
            return p;
        }
        return QGraphicsRectItem::itemChange(change, value);
    }
};

class TableWidget: public QTableWidget
{
public:
    TableWidget(QWidget* parent=nullptr) : QTableWidget(10, 10, parent)
    {
        verticalHeader()->hide();
        horizontalHeader()->setHighlightSections(false);
        setEditTriggers(QAbstractItemView::NoEditTriggers);
        setSelectionMode(QAbstractItemView::MultiSelection);
    }
};

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

    QGraphicsScene *scene = new QGraphicsScene;
    view.setScene(scene);

    QGraphicsProxyWidget *proxy = scene->addWidget(new TableWidget);

    QGraphicsRectItem *it = new QGraphicsRectItem(QRectF(0, 0, 10, proxy->boundingRect().height()), proxy);
    it->setBrush(Qt::green);

    SeekBarItem *seekBarItem = new SeekBarItem(QRectF(-5, 0, 20, 50));
    seekBarItem->setParentItem(it);

    view.resize(640, 480);
    view.show();

    return a.exec();
}

enter image description here

enter image description here

enter image description here


更新

#include <QApplication>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QTableWidget>
#include <QHeaderView>
#include <QGraphicsProxyWidget>
#include <QScrollBar>

class TableWidget: public QTableWidget
{
public:
    TableWidget(QWidget* parent=nullptr) : QTableWidget(10, 10, parent)
    {
        verticalHeader()->hide();
        horizontalHeader()->setHighlightSections(false);
        setEditTriggers(QAbstractItemView::NoEditTriggers);
        setSelectionMode(QAbstractItemView::MultiSelection);
        setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
    }
};

class SeekBarItem: public QGraphicsRectItem{
public:
    SeekBarItem(int width, QAbstractItemView *view, QGraphicsScene *scene)
        : QGraphicsRectItem(nullptr),
          proxy(new QGraphicsProxyWidget()),
          m_view(view)
    {
        proxy->setWidget(m_view);
        scene->addItem(proxy);
        setParentItem(proxy);
        setFlag(QGraphicsItem::ItemIsMovable, true);
        setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
        setBrush(Qt::red);
        setRect(0, 0, width, m_view->height());
        scrollbar = m_view->horizontalScrollBar();
    }
protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value){
        if(change == QGraphicsItem::ItemPositionChange){
            QPointF p = value.toPointF();

            qreal max = parentItem()->boundingRect().right()- boundingRect().right();
            qreal min = parentItem()->boundingRect().left()-boundingRect().left();

            if(p.x() > max) p.setX(max);
            else if (p.x() < min) p.setX(min);
            p.setY(pos().y());

            float percentage = (p.x()-min)*1.0/(max-min);
            int value = scrollbar->minimum() + percentage*(scrollbar->maximum() - scrollbar->minimum());
            scrollbar->setValue(value);
            return p;
        }
        return QGraphicsRectItem::itemChange(change, value);
    }
private:
    QGraphicsProxyWidget *proxy;
    QAbstractItemView *m_view;
    QScrollBar *scrollbar;
};



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

    QGraphicsScene *scene = new QGraphicsScene;
    view.setScene(scene);

   TableWidget *table =  new TableWidget;

    SeekBarItem *seekBarItem = new SeekBarItem(15, table, scene);
    view.resize(640, 480);
    view.show();

    return a.exec();
}

enter image description here

enter image description here

enter image description here