带有子QGraphicsRectItem

时间:2018-08-07 15:45:04

标签: c++ qt qtableview

我有一个QGraphicsView,场景中包含QGraphicsProxyWidget(QTableView),在QGraphicsRectItem的顶部有一个QTableView。不幸的是,我无法上传任何图像(Imgur错误),但是here是一则帖子,用于形象化外观。 我的QGraphicsRectItem是一条垂直线,就像在QTableView上水平延伸的搜索栏一样。基本上,它看起来像带有搜索栏的时间线,通常在音频和视频编辑工具中找到。

问题:

  • 移动水平滚动条会使搜索条在到达QTableView的边界时消失,并且不再出现。
  • 如果搜寻栏触及边界,则在移动滚动条时,滚动条不能进一步移动。

我做了什么:

我已经设法创建了MVCE(不是真的很小)

//SeekBar.h
#include <QGraphicsRectItem>
#include <QAbstractItemView>
#include <QObject>
#include <QScrollBar>
#include <QGraphicsProxyWidget>
#include "tableview.h"

class SeekBar : public QObject, public QGraphicsRectItem
{
        Q_OBJECT

    public:
        SeekBar(int width, QTableView* view, QGraphicsScene* scene);

    protected:
        QVariant itemChange(GraphicsItemChange change, const QVariant& value);

    public slots:
        void scrollBarMoved();

    private:
        QGraphicsProxyWidget* proxy;
        QTableView* m_view;
        QScrollBar* scrollbar;
        bool m_isScrollMoving;
};

//SeekBar.cpp
#include <QBrush>
#include <QGraphicsScene>

#include "seekbar.h"

SeekBar::SeekBar(int width, QTableView* view, QGraphicsScene* scene) :
    QGraphicsRectItem(nullptr),
    proxy(new QGraphicsProxyWidget()),
    m_view(view),
    m_isScrollMoving(false)
{
    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();

    connect(m_view->horizontalScrollBar(), &QScrollBar::sliderMoved, this, &SeekBar::scrollBarMoved);
}



QVariant SeekBar::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
    if (change == QGraphicsItem::ItemPositionChange && !m_isScrollMoving)
    {
        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;
    }

    else if (change == QGraphicsItem::ItemPositionChange && m_isScrollMoving)
    {
        QPointF p = value.toPointF();

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

        setVisible(true);

        if (p.x() > max)
        {
            hide();
        }
        else if (p.x() < min)
        {
            hide();
        }
        p.setY(pos().y());

        return p;
    }
    return QGraphicsRectItem::itemChange(change, value);
}



void SeekBar::scrollBarMoved()
{
    m_isScrollMoving = true;

    int col = m_view->columnAt(pos().x());

    setPos(m_view->columnViewportPosition(col), 0);
    m_isScrollMoving = false;
}

//TableView.h
#include <QTableView>

class TableView : public QTableView
{
    public:
        TableView(QWidget* parent = nullptr);
};
//TableView.cpp
#include "tableview.h"

#include <QHeaderView>
#include <QStandardItemModel>
#include <QScrollBar>

TableView::TableView(QWidget* parent) : QTableView(parent)
{
    QStandardItemModel* model = new QStandardItemModel(10, 10);

    setModel(model);
    verticalHeader()->hide();
    horizontalHeader()->setHighlightSections(false);
    setEditTriggers(QAbstractItemView::NoEditTriggers);
    setSelectionMode(QAbstractItemView::MultiSelection);
    setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}
//main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsProxyWidget>

#include "tableview.h"
#include "seekbar.h"

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

    QGraphicsView view;

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

    TableView* table =  new TableView;

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

    return a.exec();
}

我想要什么:

  • 我希望每当我使用鼠标拖动搜索栏时就可以平滑地滚动表格视图,但是它应该保持在视图的边界之内。
  • 我想在使用水平条滚动时将搜索保持在固定位置(列)。但是它不应该有任何边界,即在使用滚动条时,搜索应该能够通过视图或隐藏,但是在向后滚动时应该显示在固定位置。

查看第5列

Starts at column 5

水平栏向右滚动

Seek fix at col 5

滚动到视图结尾

End of the view

滚动回到第5列

Back to original

EDIT1: 例如,如果搜寻位于第5列,则在使用水平滚动条滚动时,它应停留在第5列并应穿过边界(或在到达边界时隐藏边界?)。滚动时,只要第5列在视图中,搜索就应该可见。

我希望您能提出一些想法。

0 个答案:

没有答案