How can I use one horizontal scrollbar to scroll several QGraphicsViews?

In order to use one scrollbar to scroll several views, you can put your views and a QScrollBar [doc.qt.nokia.com] inside a widget and connect the scrollbar’s value changed signal to the setValue() [doc.qt.nokia.com] slots of the hidden horizontal scrollbars. In addition the ranges need to be kept in sync, although you can easily change this if you want to make it a bit smarter. See the following example for a demonstration:

  1. #include <QtGui>
  2.  
  3. class Widget : public QWidget
  4. {
  5.     Q_OBJECT
  6. public:
  7.     Widget(QWidget *parent = 0) : QWidget(parent)
  8.     {
  9.         QGraphicsScene *scene = new QGraphicsScene();
  10.         scene->addEllipse(QRectF(-100, -100, 300, 200), QPen(Qt::blue), QBrush(Qt::cyan));
  11.  
  12.         QGraphicsView *view1 = new QGraphicsView(scene);
  13.         view1->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  14.  
  15.         QGraphicsView *view2 = new QGraphicsView(scene);
  16.         view2->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  17.  
  18.         scrollbar = new QScrollBar(Qt::Horizontal, this);
  19.         QVBoxLayout *vertical = new QVBoxLayout(this);
  20.         QWidget *subWidget = new QWidget(this);
  21.         QHBoxLayout *layout = new QHBoxLayout(subWidget);
  22.         layout->addWidget(view1);
  23.         layout->addWidget(view2);
  24.  
  25.         vertical->addWidget(subWidget);
  26.         vertical->addWidget(scrollbar);
  27.         scrollbar->setRange(view1->horizontalScrollBar()->minimum(), view1->horizontalScrollBar()->maximum());
  28.  
  29.         connect(scrollbar, SIGNAL(valueChanged(int)), view1->horizontalScrollBar(), SLOT(setValue(int)));
  30.         connect(scrollbar, SIGNAL(valueChanged(int)), view2->horizontalScrollBar(), SLOT(setValue(int)));
  31.         connect(view1->horizontalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(updateRange(int, int)));
  32.     }
  33. public slots:
  34.     void updateRange(int min, int max)
  35.     {
  36.         scrollbar->setRange(min, max);
  37.     }
  38. private:
  39.     QScrollBar *scrollbar;
  40. };
  41.  
  42. #include "main.moc"
  43.  
  44. int main(int argc, char** argv)
  45. {
  46.     QApplication app(argc, argv);
  47.     Widget widget;
  48.     widget.show();
  49.     return app.exec();
  50. }
  51.  

4 comments

November 22, 2010

Picture of JesseHobbs JesseHobbs

Lab Rat

That works if the views are scrolled only using the scroll bar. Using the cursor keys
up/down/pgup/pgdown or <ALT>+mousewheel causes the views to become out of sync.
The QGraphicsViews need their scroll bars cross connected with valueChange/setValue functions in addition to connecting to the master scroll bar. The connect code shown above should be:

connect(scrollbar, SIGNAL), view1->horizontalScrollBar(), SLOT));
//connect(scrollbar, SIGNAL), view2->horizontalScrollBar(), SLOT));
connect(view1->horizontalScrollBar(), SIGNAL), this, SLOT));

connect(view1->horizontalScrollBar(),SIGNAL), view2->horizontalScrollBar(),SLOT));
connect(view2->horizontalScrollBar(),SIGNAL), view1->horizontalScrollBar(),SLOT));
connect(view1->horizontalScrollBar(), SIGNAL), scrollbar, SLOT));

The views are smart enough to prevent infinite signal recursion on setValue

November 22, 2010

Picture of JesseHobbs JesseHobbs

Lab Rat

Let’s try again. The formatter made the code unreadable.
The code should read:

connect ( scrollbar, SIGNAL ( valueChanged ( int ) ) , view1->horizontalScrollBar ( ), SLOT ( setValue ( int ) ) ) ;
connect ( view1->horizontalScrollBar ( ) , SIGNAL ( rangeChanged ( int, int ) ) , this, SLOT ( updateRange ( int, int ) ) ) ;

connect ( view1->horizontalScrollBar ( ) , SIGNAL ( valueChanged ( int ) ) , view2->horizontalScrollBar ( ) , SLOT ( setValue ( int ) ) ) ;
connect ( view2->horizontalScrollBar ( ) , SIGNAL ( valueChanged ( int ) ) , view1->horizontalScrollBar ( ) , SLOT ( setValue ( int ) ) ) ;
connect ( view1->horizontalScrollBar ( ) , SIGNAL ( valueChanged ( int ) ) , scrollbar, SLOT ( setValue ( int ) ) ) ;

December 4, 2010

Picture of xsacha xsacha

Lab Rat

Formatting won’t work in here Jesse. We get what you’re saying though :)

I don’t know if it’s good to rely on infinite recursion detection. Doesn’t it cause a slow down?

December 13, 2010

Picture of JesseHobbs JesseHobbs

Lab Rat

I have not seen any slowdown. Scrolling response is instantaneous and there is no duplicate drawing occurring in either GraphicsView.

Write a comment

Sorry, you must be logged in to post a comment.