OK, so I know it's a bit late, but here is my implementation.
ScrollingMapCanvas.hpp
class ScrollingMapCanvas : public QAbstractScrollArea
{
public:
ScrollingMapCanvas(MapCanvas* mapCanvas, QWidget *parent = Q_NULLPTR);
MapCanvas* mapCanvas() const;
protected:
void resizeEvent(QResizeEvent* event);
void scrollContentsBy(int dx, int dy);
private:
MapCanvas* m_mapCanvas;
};
ScrollingMapCanvas.cpp
ScrollingMapCanvas::ScrollingMapCanvas(MapCanvas* mapCanvas, QWidget* parent) :
QAbstractScrollArea(parent)
{
m_mapCanvas = mapCanvas;
m_mapCanvas->setParent(viewport());
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
void ScrollingMapCanvas::resizeEvent(QResizeEvent* /*event*/)
{
QSize areaSize = viewport()->size();
m_mapCanvas->resize(areaSize);
//add 1.f to width and height to see the end of the grid
int width = (m_mapCanvas->map()->size().x * m_mapCanvas->map()->tileSize().x + 1) / m_mapCanvas->scale();
int height = (m_mapCanvas->map()->size().y * m_mapCanvas->map()->tileSize().y + 1) / m_mapCanvas->scale();
QSize mapSize = QSize(width, height);
horizontalScrollBar()->setPageStep(areaSize.width());
verticalScrollBar()->setPageStep(areaSize.height());
horizontalScrollBar()->setRange(0, mapSize.width() - areaSize.width());
verticalScrollBar()->setRange(0, mapSize.height() - areaSize.height());
}
void ScrollingMapCanvas::scrollContentsBy(int dx, int dy)
{
m_mapCanvas->translate(sf::Vector2f(-dx * m_mapCanvas->scale(), -dy * m_mapCanvas->scale()));
}
MapCanvas* ScrollingMapCanvas::mapCanvas() const
{
return m_mapCanvas;
}
MapCanvas is the class which inherits from QSFMLCanvas, it has a Map object (which owns in particular the size of the map and the tile size for the map), a translation (sf::Vector2f) and a scaling factor (for zoom). These 2 last attributes are used by an internal sf::View to update the camera at each frame.
Here you go, if you have any suggestion to improve it, I will gladly receive them !