将水平滑块添加到 QTableWidget [英] Adding horizontal slider to QTableWidget

查看:62
本文介绍了将水平滑块添加到 QTableWidget的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的视频播放器设计类似于时间线视图的内容.我决定使用 QTableWidget 作为时间线,因为它适合我的目的.我的小部件如下所示:

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:

当我点击播放时,我希望绿线穿过小部件.这是我的 MVCE 示例:

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

这是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 内.

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.

我想要什么

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

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.

推荐答案

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

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

更新:

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

这篇关于将水平滑块添加到 QTableWidget的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆