Arlen
Arlen

Reputation: 6835

QGraphicsView possible bug?

The example code is from my project. I've tried to make it as short as possible and to the point.

The overlay is used to draw over all the other widgets in the app. This works for most widgets, but today I've started to notice that QAbstractScrollArea subclasses are giving me a hard time. The problem is that the overlay appears not on top, and whatever drawing that happens is blocked.

#include <QtGui/QApplication>
#include <QtGui/QVBoxLayout>
#include <QtGui/QGraphicsView>
#include <QtGui/QPushButton>

class View : public QGraphicsView{
public:
  View(){ 
    //delete viewport(); setViewport(new QWidget);
  }
};

class Widget : public QWidget{

  QWidget* overlay_;

public:
  Widget(){
    resize(512,  512);
    QVBoxLayout* layout = new QVBoxLayout;
    QPushButton* button = new QPushButton(" Click Me! ");
    layout->addWidget(button);
    layout->addWidget(new View);
    overlay_ = new QWidget(this);
    overlay_->installEventFilter(this);
    connect(button, SIGNAL(clicked()),
        overlay_, SLOT(show()));
    overlay_->hide();
    setLayout(layout);
  }

  bool eventFilter(QObject* target, QEvent* event){

    if(target == overlay_){
      if(event->type() == QEvent::Paint && overlay_->isVisible()){
    overlay_->resize(size());
    QPainter painter(overlay_);
    painter.setPen(QPen(QColor(1, 102, 192, 255), 1, Qt::SolidLine,
                Qt::FlatCap, Qt::MiterJoin));
    painter.drawRect(rect().adjusted(60, 0, -60, 0));
    return true;
      }
    }
  }
};


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

  QApplication a(argc, argv);
  Widget w;
  w.show();
  return a.exec();
}

To fix this in this example and have overlay go on top of View, you'll need to uncomment the commented line at the top. So my question is this: why do I need to delete and assign a new viewport widget in the constructor in order for overlay not get overdrawn?

Upvotes: 0

Views: 742

Answers (1)

Adam
Adam

Reputation: 246

This isn't a bug with QGraphicsView, it will happen if you use a standard QScrollArea as well.

The issue, I think, is the order in which Qt draws child widgets. Sibling widgets are drawn in the order they are added to the parent (although you can't rely on this).

The reason that resetting the viewport "solved" the problem is because when you do that you create a new QWidget that has no background to be the viewport. The QGraphicsView is still being drawn over the overlay_, it just has a transparent viewport. Notice how it's still drawn behind the pushbutton, however.

If you want to draw an overlay only over the QGraphicsView, you can override QGraphicsView::paintEvent() and do it there. If you want to draw the overlay over your entire widget, I would embed your layout inside a second QWidget and then try using QWidget::raise() to force the overlay visually to the top.

Upvotes: 3

Related Questions