Adding horizontal slider to QTableWidget

[亡魂溺海] 提交于 2019-12-08 06:06:58

问题


I am trying to design something like a timeline view for my video player. I decided to use QTableWidget as the timeline since it suits my purpose. My widget looks like this:

I want the green line to run through the widget when i click on play. Here is my MVCE example:

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

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

Problem:

Moving the line item reflects changes to the scene it has been added to i.e. when i drag the line using mouse, the line moves in the scene but not inside the TableWidget.

What do i want

I want the green bar to act like a horizontal slider. It should go through the TableWidget horizontally making the widget scroll along with it showing the current position of the frame indicated by the numbers shown on the header.

Something like as shown below (notice the Red line):

I know this might not be the best way to implement a timeline but i would appreciate any other ideas to implement.


回答1:


A possible solution is to overwrite the itemChange method to restrict movement as shown below:

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


Update:

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



来源:https://stackoverflow.com/questions/51248086/adding-horizontal-slider-to-qtablewidget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!