0

I have a QGraphicsView with a scene containing QGraphicsProxyWidget (QTableView) and a QGraphicsRectItem on top of QTableView. Unfortunately, i am not able to upload any images (Imgur error) but here is a post to visualize how it looks. My QGraphicsRectItem a vertical line, acts like a seek bar which runs horizontally on the QTableView. Basically, it looks like a time line with a seek bar commonly found in Audio and Video editing tools.

Issues:

  • Moving the horizontal scroll bar makes the seek bar disappear on hitting the boundaries of QTableView and it doesn't reappear anymore.
  • While moving the scrollbar if the seekbar hits the boundaries, scrollbar cannot be moved further.

What did i do:

I have managed to create a MVCE (Not really Minimal)

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

What do i want:

  • I want to smoothly scroll the table view whenever i drag the seek bar using mouse but it should stay inside the view's boundaries.
  • I want to keep the seek at a fixed position(column) while scrolling using the horizontal bar. But it should NOT have any boundaries i.e. while using scrollbar, the seek should be able to pass through the view or hide but should appear at the fixed position when scrolled back.

Seek at column 5

Starts at column 5

Horizontal bar scrolled a little bit to the right

Seek fix at col 5

Scrolled till the end of the view

End of the view

Scrolled back to column 5

Back to original

EDIT1: For instance, if the seek is at column 5, while scrolling using horizontal scroll bar it should stick to column 5 and should pass through the boundaries(or hide it when it hits the boundaries?). Seek should be visible whenever the column 5 is in the view while scrolling.

I would appreciate some ideas.

MarKS
  • 494
  • 6
  • 22
  • you could explain yourself better, and provide a [mcve] – eyllanesc Aug 07 '18 at 18:20
  • @eyllanesc check the updated example. – MarKS Aug 08 '18 at 08:56
  • You could explain to me what the error is. – eyllanesc Aug 08 '18 at 09:34
  • @eyllanesc updated the Issues section and added an edit. – MarKS Aug 08 '18 at 11:26
  • I do not understand you, it seems that you have several problems, so I would ask you to describe error by error, maybe with images you can illustrate your problem. – eyllanesc Aug 08 '18 at 11:39
  • You're right! It is too hard to explain it with words. Anyways, i have added sequence of images. The error stays the same as explained above...the seek disappears forever when i use scroll bar. – MarKS Aug 08 '18 at 11:58
  • I understand that you want that if you move the horizontal scrollbar you also want the SeekBar to move, so I ask you when should the seekbar be hidden? – eyllanesc Aug 08 '18 at 12:10
  • Hiding the seek was just my concept may be there is a better way to do it...i meant when you scroll too far and column 5 is no longer in the view something should happen like hide the seek or something like that. Like in the third image, there is no seek because the column 5 is not in the view. – MarKS Aug 08 '18 at 12:16
  • Now if you confused me, the requirements are not discussed, if your requirement is to hide I could not tell you if it's good or bad, that's your criterion, my question is what behavior do you want? – eyllanesc Aug 08 '18 at 12:19
  • My bad, yes the seek should not be visible anymore when the column is out of the view. – MarKS Aug 08 '18 at 12:22
  • Let's see I will summarize what I understand, say that with the SeekBar move the QTableView to column 3, if I move the horizontal scrollbar the SeekBar must be hidden, am I correct? If I am correct, when should I turn to show the SeekBar? – eyllanesc Aug 08 '18 at 12:25
  • Yes! Almost right. When you move horizontal scrollbar and can no longer see column 3 it should be hidden. When you scroll back and column 3 is back in the view the seekbar should show up exactly at the same position where you left it (column 3). – MarKS Aug 08 '18 at 12:31
  • okay, I understood you better, you say the same position in which it is hidden, but when the position depends on where you look, you mean the same position of SeekBar with respect to the column or the QTableView – eyllanesc Aug 08 '18 at 12:34
  • With respect to the column i.e. if it was left at column 3 then it should reappear at column 3. Exact position inside the column 3 doesn't matter. I have tried to do this in the function scrollBarMoved(). Check it out. – MarKS Aug 08 '18 at 12:42
  • Ok, I understand, you say that the SeekBar should be hidden as soon as the horizontal scrollbar moves, let's say it moves a little bit that does not allow the particular column to be hidden, then in that case before what event should the SeekBar be showed? – eyllanesc Aug 08 '18 at 12:46
  • No! As per the `scrollBarMoved()` i am hiding the SeekBar when it hits the `min` and `max` boundaries of `QTableView` in other cases it should be visible. So when you use horizontal scrollbar and the SeekBar moves along with column 3 it should stay visible until column 3 is out of the view or SeekBar hits the min or max position. – MarKS Aug 08 '18 at 12:57
  • Okay, in conclusion if the SeekBar is in the top of the 3rd column and I move the scrollbar it should be hidden with when the whole third column is hidden (the column has a width), and again when the third column is shown and also the seekbar can be drawn (for example if the seekbar is left in half then it will only be shown when the middle of the column is displayed) – eyllanesc Aug 08 '18 at 13:00
  • Exactly! Man it is lot more difficult to explain than i thought. – MarKS Aug 08 '18 at 13:01
  • Analyzing what you point out to me I find an inconvenient, let's say that the QTableView has 5 columns, and let's say that the SeekBar is placed exactly in the middle of the third column, then we move the scroollbar until the third column is hidden and then we move it little until we do Visible again the Seekbar, ie the SeekBar for example would be on the right edge, and the user wants to use the SeekBar to show the 4 column, but if it is already right on the right side you can not move anything, do not you think that Would it cause problems? – eyllanesc Aug 08 '18 at 13:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177648/discussion-between-marks-and-eyllanesc). – MarKS Aug 08 '18 at 13:34

0 Answers0