3

I have a game that happens on top of a static map. I thought of painting the map in QGraphicsView::drawBackground().

All seems swell. Except that nothing is drawn unless I do a window resize... I think it has to do with QGraphicsScene::fitInView() or something related...

My mapscene.cpp

#include "mapscene.h"
#include <qpainter.h>
#include <iostream>

static const float WIDTH = 800.f;
static const float HEIGHT = 480.f;

static const float _map[][2] = {
    { 0, 0 },
    { 1, 1 },
//    { 1, 0 },  // TEMP: coordinates of map
//    { 0, 1 },
//    { 0, 0 },
};

MapScene::MapScene() : QGraphicsScene(0, 0, WIDTH, HEIGHT)
{
    mapPath.moveTo(_map[0][0], _map[0][0]);
    int len = sizeof(_map)/sizeof(float)/2;
    std::cout << len << std::endl;
    for(int i = 1; i < len; i++)
        mapPath.lineTo(QPointF(_map[i][0]*WIDTH, _map[i][1]*HEIGHT));
}

void MapScene::drawBackground(QPainter *painter, const QRectF &)
{
    std::cout << "draw background" << std::endl;
    painter->drawPath(mapPath);
}

My mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#include "mapscene.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    MapScene *scene = new MapScene();
    ui->graphicsView->setScene(scene);
    resizeEvent(0);
}

void MainWindow::resizeEvent(QResizeEvent *)
{
    QRectF bounds = ui->graphicsView->scene()->sceneRect();
    ui->graphicsView->fitInView(bounds, Qt::KeepAspectRatio);
    ui->graphicsView->centerOn(bounds.center());
    std::cout << "resize - scene rect: " << ui->graphicsView->sceneRect().width() << " x " << ui->graphicsView->sceneRect().height() << std::endl;
}

MainWindow::~MainWindow()
{
    delete ui;
}

I am using Qt 5.5.1 (Ubuntu).

EDIT: I have changed \n to std::endl as @LogicStuff suggested and now the message gets printed, so drawBackground() is getting called. The problem seems to be with QGraphicsView::fitInView() and QGraphicsView::centerOn(). I have changed the post accordingly.

Ricardo Magalhães Cruz
  • 3,504
  • 6
  • 33
  • 57

3 Answers3

2

The problem was that ui->graphicsView->fitInView(bounds, Qt::KeepAspectRatio); should not be called until the widget is actually shown:

https://stackoverflow.com/a/17085612/2680707

Community
  • 1
  • 1
Ricardo Magalhães Cruz
  • 3,504
  • 6
  • 33
  • 57
1

One problem would be that std::cout << "draw background\n"; in MainWindow::drawBackground does not flush std::cout. On the other hand, std::cout gets flushed in MainWindow::resizeEvent because of std::endl.

Use std::endl or \n and std::flush.

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • Oh thanks. I did not know there was a difference between `std::endl` and `\n`. Now the message gets printed, so at least I know the problem is not because the `paintBackground()` does not get called... – Ricardo Magalhães Cruz Feb 09 '16 at 13:17
0

Since most of the time the background doesn't change, it's cached by default using : QGraphicsView::CacheBackground. You have two options:

  1. use view.setCacheMode(QGraphicsView::CacheNone); but it may reduce performance
  2. use invalidate(const QRectF & rect = QRectF(), SceneLayers layers = AllLayers) on your background layer each time you need.

Even if the second one is a bit trickier to implement, I would recommend it for sake of performance and CPU laziness.

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142