d_stranz
12th February 2013, 21:15
OK, in follow-up to my previous post, I have refactored my data plotting widget so that it uses a QGraphicsView instance only for the part of the plot that displays the data itself. The axes, titles, footers, etc. are displayed using QwtScaleWidget, QLabel, etc.
One of the characteristics of this plot is that labels for the data points are drawn so that they don't collide or overlap, and that the size of the label does not scale (remains a fixed size) when the plot is zoomed in or out. This is accomplished with the ItemIgnoresTransformations flag.
I have also implemented view-based collision detection: I create the candidate set of labels based on the zoom region in the view, then map the label positions and sizes from scene to view. I then go through this list and check for collisions; for any colliding pair of labels, the one with the lower z-value is made invisible. All of this works fine.
The way I am trying to realize this on screen is to overlay two QGraphicsView windows. One window contains the data and its plot, the other contains only the labels. There are two QGraphicsScene instances, one for the data and plot, the other for the labels. The data scene can be shared among multiple plots, which allows me to display one in 1:1 format, the other zoomed in or out, etc. without having to duplicate the underlying data or scene objects. The label scene is dedicated to the QGraphicsView that displays the labels. In this way, two views of the same scene could have a different set of non-colliding labels, as a sort of "level of detail" effect.
The problem I am having is that I cannot seem to make both graphics views simultaneously visible. I have tried various versions of this code in my plot widget constructor:
mpCanvas = new QGraphicsView( this );
mpCanvas->setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
mpCanvas->setEnabled( true );
mpCanvas->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpCanvas->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpCanvas->setWindowOpacity( 0.0 );
mpCanvas->setBackgroundBrush( Qt::NoBrush );
mpLabelCanvas = new QGraphicsView( &mLabelScene, this );
mpLabelCanvas->setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
mpLabelCanvas->setEnabled( false );
mpLabelCanvas->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpLabelCanvas->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpLabelCanvas->stackUnder( mpCanvas );
where "mpCanvas" is the QGraphicsView that uses the shared QGraphicsScene containing the data, and "mpLabelCanvas" is the QGraphicsView with the dedicated scene holding the labels. (Scenes are assigned later in the constructor, and labels are calculated on-the-fly during resize and zoom operations).
In the version posted above, the "mpCanvas" is visible, the "mpLabelCanvas" is not. (I see the data but no labels). If I stack them the other way, the opposite occurs, so I know that I am positioning, sizing, and setting transforms for the two views correctly.
What I want to happen is that the upper (data) view is transparent so that the lower (label) view shows through it. This is my last hurdle in getting this widget to a state where I can actually write the app that uses it.
Is there some combination of window flags, opacity, background brush, etc. that will create this effect?
One of the characteristics of this plot is that labels for the data points are drawn so that they don't collide or overlap, and that the size of the label does not scale (remains a fixed size) when the plot is zoomed in or out. This is accomplished with the ItemIgnoresTransformations flag.
I have also implemented view-based collision detection: I create the candidate set of labels based on the zoom region in the view, then map the label positions and sizes from scene to view. I then go through this list and check for collisions; for any colliding pair of labels, the one with the lower z-value is made invisible. All of this works fine.
The way I am trying to realize this on screen is to overlay two QGraphicsView windows. One window contains the data and its plot, the other contains only the labels. There are two QGraphicsScene instances, one for the data and plot, the other for the labels. The data scene can be shared among multiple plots, which allows me to display one in 1:1 format, the other zoomed in or out, etc. without having to duplicate the underlying data or scene objects. The label scene is dedicated to the QGraphicsView that displays the labels. In this way, two views of the same scene could have a different set of non-colliding labels, as a sort of "level of detail" effect.
The problem I am having is that I cannot seem to make both graphics views simultaneously visible. I have tried various versions of this code in my plot widget constructor:
mpCanvas = new QGraphicsView( this );
mpCanvas->setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
mpCanvas->setEnabled( true );
mpCanvas->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpCanvas->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpCanvas->setWindowOpacity( 0.0 );
mpCanvas->setBackgroundBrush( Qt::NoBrush );
mpLabelCanvas = new QGraphicsView( &mLabelScene, this );
mpLabelCanvas->setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
mpLabelCanvas->setEnabled( false );
mpLabelCanvas->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpLabelCanvas->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mpLabelCanvas->stackUnder( mpCanvas );
where "mpCanvas" is the QGraphicsView that uses the shared QGraphicsScene containing the data, and "mpLabelCanvas" is the QGraphicsView with the dedicated scene holding the labels. (Scenes are assigned later in the constructor, and labels are calculated on-the-fly during resize and zoom operations).
In the version posted above, the "mpCanvas" is visible, the "mpLabelCanvas" is not. (I see the data but no labels). If I stack them the other way, the opposite occurs, so I know that I am positioning, sizing, and setting transforms for the two views correctly.
What I want to happen is that the upper (data) view is transparent so that the lower (label) view shows through it. This is my last hurdle in getting this widget to a state where I can actually write the app that uses it.
Is there some combination of window flags, opacity, background brush, etc. that will create this effect?