如何使用复选框更改 QGraphicsView 背景
How can I change QGraphicsView background using check box
在这段代码中,改变了 QGraphicsView
background.Now 我需要在检查 true checkBox
时更改背景。当我设置为 checkBox
以检查 true
我需要这样设置背景 code.When 我设置 checkBox
来检查 false
。我需要设置 QGraphicsView
为正常的默认方式。我该怎么做。
这是我的代码:
mainwindow.cpp
#include "mainwindow.h"
#include <QGraphicsTextItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
scene = new Scene(this);
scene->setSceneRect(10,10,260,200);
view = new QGraphicsView(scene);
setCentralWidget(view);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsView>
#include "scene.h"
#include "customrectitem.h"
class MainWindow : public QMainWindow
{
public:
explicit MainWindow(QWidget *parent = 0);
private:
QGraphicsView* view;
QGraphicsScene* scene;
};
#endif // MAINWINDOW_H
Scene.h
#ifndef SCENE_H
#define SCENE_H
#include <QGraphicsScene>
#include <QPainter>
#include <QApplication>
class Scene : public QGraphicsScene
{
Q_OBJECT
public:
explicit Scene(QObject *parent = 0);
int getGridSize() const {return this->gridSize;}
protected:
void drawBackground (QPainter* painter, const QRectF &rect);
private:
int gridSize;
};
#endif // SCENE_H
Scene.cpp
#include "scene.h"
Scene::Scene(QObject *parent) : QGraphicsScene(parent), gridSize(20)
{
Q_ASSERT(gridSize > 0);
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
QColor c (10,140,255,155);
painter->setPen(c);
qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
QVarLengthArray<QLineF,100> lines;
for (qreal x = left; x < rect.right(); x += gridSize)
lines.append(QLineF(x,rect.top(),x,rect.bottom()));
for (qreal y = top; y < rect.bottom(); y += gridSize)
lines.append(QLineF(rect.left(),y,rect.right(),y));
painter->drawLines(lines.data(),lines.size());
}
我有两个机会画一个网格:
从 QGraphicsView
导出 class 并重载 paintEvent()
并绘制网格,然后返回到 QGraphicsView::paintEvent()
将网格线添加为 QGraphicsItemGroup
下的场景项,这样可以控制可见性。
第一种方法的优点是可以无缝适应视口的任何大小调整。
这是我的示例代码testQGraphicsView-BgGrid.cc
:
#include <QtWidgets>
class Canvas: public QGraphicsView {
private:
int _gridSize;
QColor _gridColor;
bool _gridVisible;
public:
explicit Canvas(QWidget *pQParent = nullptr):
QGraphicsView(pQParent),
_gridSize(20), _gridColor(0x0a8affu), _gridVisible(true)
{ }
bool gridVisible() const { return _gridVisible; }
void setGridVisible(bool gridVisible)
{
_gridVisible = gridVisible;
viewport()->update();
}
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override
{
QPainter qPainter(viewport());
if (_gridVisible) {
const int wView = viewport()->width(), hView = viewport()->height();
qPainter.setPen(_gridColor);
for (int x = _gridSize / 2; x < wView; x += _gridSize) {
qPainter.drawLine(x, 0, x, hView - 1);
}
for (int y = _gridSize / 2; y < hView; y += _gridSize) {
qPainter.drawLine(0, y, wView - 1, y);
}
}
QGraphicsView::paintEvent(pQEvent);
}
};
void makeGrid(
QGraphicsItemGroup &qItemGrp, const QSize &size,
int gridSize = 20, const QColor &gridColor = 0x0a8affu)
{
const int wView = size.width(), hView = size.height();
for (int x = gridSize / 2; x < wView; x += gridSize) {
QGraphicsLineItem *pQItem = new QGraphicsLineItem(x, 0, x, hView - 1);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
for (int y = gridSize / 2; y < hView; y += gridSize) {
QGraphicsLineItem *pQItem = new QGraphicsLineItem(0, y, wView - 1, y);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWnd;
QGridLayout qGrid;
QLabel qLblL(QString::fromUtf8("Grid as part of scene"));
qGrid.addWidget(&qLblL, 0, 0);
QCheckBox qTglGridL(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridL, 0, 1);
QGraphicsView qGraphView;
qGrid.addWidget(&qGraphView, 1, 0, 1, 2);
QLabel qLblR(QString::fromUtf8("Grid painted as background"));
qGrid.addWidget(&qLblR, 0, 2);
QCheckBox qTglGridR(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridR, 0, 3);
Canvas canvas;
qGrid.addWidget(&canvas, 1, 2, 1, 2);
qWnd.setLayout(&qGrid);
qWnd.show();
// init GUI
QGraphicsScene qGraphSceneL;
QGraphicsItemGroup qItemGrid;
makeGrid(qItemGrid, qGraphView.viewport()->size());
qGraphSceneL.addItem(&qItemGrid);
qGraphView.setScene(&qGraphSceneL);
qTglGridL.setCheckState(
qItemGrid.isVisible() ? Qt::Checked : Qt::Unchecked);
qTglGridR.setCheckState(
canvas.gridVisible() ? Qt::Checked : Qt::Unchecked);
// install signal handlers
QObject::connect(&qTglGridL, &QCheckBox::stateChanged,
[&qItemGrid](int state)
{
qItemGrid.setVisible(state != Qt::Unchecked);
});
QObject::connect(&qTglGridR, &QCheckBox::stateChanged,
[&canvas](int state)
{
canvas.setGridVisible(state != Qt::Unchecked);
});
// runtime loop
return app.exec();
}
使用 VS2013 和 Qt 5.9.2 编译,在 Window 10(64 位)上测试:
更新:
QMake 脚本testQGraphicsView-BgGrid.pro
:
SOURCES = testQGraphicsView-BgGrid.cc
QT += widgets
在 cygwin 上 bash
构建和测试:
$ qmake-qt5 testQGraphicsView-BgGrid.pro
$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQGraphicsView-BgGrid.o testQGraphicsView-BgGrid.cc
g++ -o testQGraphicsView-BgGrid.exe testQGraphicsView-BgGrid.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
$ ./testQGraphicsView-BgGrid
与 X11 应用程序相同的程序:
又一个更新:
我不得不承认,在我的第一个版本中,我专注于如何使用复选框更改 QGraphicsView 背景,重点是复选框 忽略 QGraphicsScene::drawBackground()
(which I didn't know) and ignoring issues in the grid rendering itself (which I used instead). As pointed out in ,两个显示的解决方案都提供了一些我应该(至少)记录下来的弱点。
左视图(涉及到场景中的网格)不一定填满viewport()
。恕我直言,如果网格填充场景使用的相关范围,这是可以接受的。 (这可能是为了形象化场景只覆盖了viewport()
的一部分。)然而,makeGrid()
的参数const QSize &size
是这个意图的一个不幸的选择。我通过将其替换为 const QRect &rect
.
来解决此设计问题
右视图(重载paintEvent()
)没有考虑可能的场景滚动。我通过将左上角映射到场景坐标 (const QPointF offs = mapToScene(0, 0);
) 并将偏移量视为循环中的起始值来修复此问题。
更新示例代码testQGrapicsView-BgGrid.cc
:
#include <QtWidgets>
class Canvas: public QGraphicsView {
private:
int _gridSize;
QColor _gridColor;
bool _gridVisible;
public:
explicit Canvas(QWidget *pQParent = nullptr):
QGraphicsView(pQParent),
_gridSize(20), _gridColor(0x0a8affu), _gridVisible(true)
{ }
bool gridVisible() const { return _gridVisible; }
void setGridVisible(bool gridVisible)
{
_gridVisible = gridVisible;
viewport()->update();
}
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override
{
QPainter qPainter(viewport());
if (_gridVisible) {
const int wView = viewport()->width(), hView = viewport()->height();
const QPointF offs = mapToScene(0, 0);
qPainter.setPen(_gridColor);
for (int x = (int)offs.x() % _gridSize; x < wView; x += _gridSize) {
qPainter.drawLine(x, 0, x, hView - 1);
}
for (int y = (int)offs.y() % _gridSize; y < hView; y += _gridSize) {
qPainter.drawLine(0, y, wView - 1, y);
}
}
QGraphicsView::paintEvent(pQEvent);
}
};
void makeGrid(
QGraphicsItemGroup &qItemGrp, const QRect &rect,
int gridSize = 20, const QColor &gridColor = 0x0a8affu)
{
for (int x = rect.x(), xE = x + rect.width(); x < xE; x += gridSize) {
QGraphicsLineItem *pQItem
= new QGraphicsLineItem(x, rect.y(), x, rect.height() - 1);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
for (int y = rect.y(), yE = y + rect.height(); y < yE; y += gridSize) {
QGraphicsLineItem *pQItem
= new QGraphicsLineItem(rect.x(), y, rect.width() - 1, y);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWnd;
QGridLayout qGrid;
QLabel qLblL(QString::fromUtf8("Grid as part of scene"));
qGrid.addWidget(&qLblL, 0, 0);
QCheckBox qTglGridL(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridL, 0, 1);
QGraphicsView qGraphView;
qGrid.addWidget(&qGraphView, 1, 0, 1, 2);
QLabel qLblR(QString::fromUtf8("Grid painted as background"));
qGrid.addWidget(&qLblR, 0, 2);
QCheckBox qTglGridR(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridR, 0, 3);
Canvas canvas;
qGrid.addWidget(&canvas, 1, 2, 1, 2);
qWnd.setLayout(&qGrid);
qWnd.show();
// init GUI
QGraphicsScene qGraphSceneL;
QGraphicsItemGroup qItemGrid;
makeGrid(qItemGrid, QRect(0, 0, 320, 240));
qGraphSceneL.addItem(&qItemGrid);
qGraphView.setScene(&qGraphSceneL);
qTglGridL.setCheckState(
qItemGrid.isVisible() ? Qt::Checked : Qt::Unchecked);
qTglGridR.setCheckState(
canvas.gridVisible() ? Qt::Checked : Qt::Unchecked);
// install signal handlers
QObject::connect(&qTglGridL, &QCheckBox::stateChanged,
[&qItemGrid](int state)
{
qItemGrid.setVisible(state != Qt::Unchecked);
});
QObject::connect(&qTglGridR, &QCheckBox::stateChanged,
[&canvas](int state)
{
canvas.setGridVisible(state != Qt::Unchecked);
});
// runtime loop
return app.exec();
}
以下快照显示了启动后和调整大小后的应用程序:
虽然@Scheff的方案很好,但是存在以下问题:
第一个解决方案让它只覆盖一小部分space,如果你改变QGraphicsView的大小它不会覆盖所有space.
第二个解决方案有问题,你使用的是viewport()
坐标,而不是场景,如果你添加一个项目然后在不移动项目的情况下放大QGraphicsView,那么你看到一个卷轴。
初始:
更改大小后:
纠正这两个错误的解决方案是覆盖 QGraphicsScene 的 drawBackground 方法:
#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H
#include <QGraphicsScene>
#include <QPainter>
class GraphicsScene: public QGraphicsScene{
int mGridSize;
QColor mGridColor;
bool mGridVisible;
Q_OBJECT
public:
GraphicsScene(QObject *parent = Q_NULLPTR):QGraphicsScene(parent),
mGridSize(20), mGridColor(0x0a8affu), mGridVisible(true)
{
}
bool gridVisible() const {
return mGridVisible;
}
void setGridVisible(bool gridVisible){
if(mGridVisible != gridVisible){
mGridVisible = gridVisible;
update();
}
}
protected:
void drawBackground(QPainter *painter, const QRectF &rect){
if(mGridVisible) {
QRect r = rect.toRect();
int xmin =r.left() - r.left()%mGridSize - mGridSize;
int ymin = r.top() - r.top()%mGridSize - mGridSize;
int xmax = r.right() - r.right()%mGridSize + mGridSize;
int ymax = r.bottom() - r.bottom()%mGridSize + mGridSize;
for(int x=xmin ; x <= xmax; x += mGridSize ){
painter->drawLine(x, r.top(), x, r.bottom());
}
for(int y=ymin ; y <= ymax; y+= mGridSize ){
painter->drawLine(r.left(), y, r.right(), y);
}
}
}
};
#endif // GRAPHICSSCENE_H
这个方案的优点是不加载任何新的对象,而且图形在场景的坐标中,所以没有第二种方案的位移。
初始:
更改大小后:
完整的例子可以在下面找到link
在这段代码中,改变了 QGraphicsView
background.Now 我需要在检查 true checkBox
时更改背景。当我设置为 checkBox
以检查 true
我需要这样设置背景 code.When 我设置 checkBox
来检查 false
。我需要设置 QGraphicsView
为正常的默认方式。我该怎么做。
这是我的代码:
mainwindow.cpp
#include "mainwindow.h"
#include <QGraphicsTextItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
scene = new Scene(this);
scene->setSceneRect(10,10,260,200);
view = new QGraphicsView(scene);
setCentralWidget(view);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsView>
#include "scene.h"
#include "customrectitem.h"
class MainWindow : public QMainWindow
{
public:
explicit MainWindow(QWidget *parent = 0);
private:
QGraphicsView* view;
QGraphicsScene* scene;
};
#endif // MAINWINDOW_H
Scene.h
#ifndef SCENE_H
#define SCENE_H
#include <QGraphicsScene>
#include <QPainter>
#include <QApplication>
class Scene : public QGraphicsScene
{
Q_OBJECT
public:
explicit Scene(QObject *parent = 0);
int getGridSize() const {return this->gridSize;}
protected:
void drawBackground (QPainter* painter, const QRectF &rect);
private:
int gridSize;
};
#endif // SCENE_H
Scene.cpp
#include "scene.h"
Scene::Scene(QObject *parent) : QGraphicsScene(parent), gridSize(20)
{
Q_ASSERT(gridSize > 0);
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
QColor c (10,140,255,155);
painter->setPen(c);
qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
QVarLengthArray<QLineF,100> lines;
for (qreal x = left; x < rect.right(); x += gridSize)
lines.append(QLineF(x,rect.top(),x,rect.bottom()));
for (qreal y = top; y < rect.bottom(); y += gridSize)
lines.append(QLineF(rect.left(),y,rect.right(),y));
painter->drawLines(lines.data(),lines.size());
}
我有两个机会画一个网格:
从
QGraphicsView
导出 class 并重载paintEvent()
并绘制网格,然后返回到QGraphicsView::paintEvent()
将网格线添加为
QGraphicsItemGroup
下的场景项,这样可以控制可见性。
第一种方法的优点是可以无缝适应视口的任何大小调整。
这是我的示例代码testQGraphicsView-BgGrid.cc
:
#include <QtWidgets>
class Canvas: public QGraphicsView {
private:
int _gridSize;
QColor _gridColor;
bool _gridVisible;
public:
explicit Canvas(QWidget *pQParent = nullptr):
QGraphicsView(pQParent),
_gridSize(20), _gridColor(0x0a8affu), _gridVisible(true)
{ }
bool gridVisible() const { return _gridVisible; }
void setGridVisible(bool gridVisible)
{
_gridVisible = gridVisible;
viewport()->update();
}
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override
{
QPainter qPainter(viewport());
if (_gridVisible) {
const int wView = viewport()->width(), hView = viewport()->height();
qPainter.setPen(_gridColor);
for (int x = _gridSize / 2; x < wView; x += _gridSize) {
qPainter.drawLine(x, 0, x, hView - 1);
}
for (int y = _gridSize / 2; y < hView; y += _gridSize) {
qPainter.drawLine(0, y, wView - 1, y);
}
}
QGraphicsView::paintEvent(pQEvent);
}
};
void makeGrid(
QGraphicsItemGroup &qItemGrp, const QSize &size,
int gridSize = 20, const QColor &gridColor = 0x0a8affu)
{
const int wView = size.width(), hView = size.height();
for (int x = gridSize / 2; x < wView; x += gridSize) {
QGraphicsLineItem *pQItem = new QGraphicsLineItem(x, 0, x, hView - 1);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
for (int y = gridSize / 2; y < hView; y += gridSize) {
QGraphicsLineItem *pQItem = new QGraphicsLineItem(0, y, wView - 1, y);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWnd;
QGridLayout qGrid;
QLabel qLblL(QString::fromUtf8("Grid as part of scene"));
qGrid.addWidget(&qLblL, 0, 0);
QCheckBox qTglGridL(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridL, 0, 1);
QGraphicsView qGraphView;
qGrid.addWidget(&qGraphView, 1, 0, 1, 2);
QLabel qLblR(QString::fromUtf8("Grid painted as background"));
qGrid.addWidget(&qLblR, 0, 2);
QCheckBox qTglGridR(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridR, 0, 3);
Canvas canvas;
qGrid.addWidget(&canvas, 1, 2, 1, 2);
qWnd.setLayout(&qGrid);
qWnd.show();
// init GUI
QGraphicsScene qGraphSceneL;
QGraphicsItemGroup qItemGrid;
makeGrid(qItemGrid, qGraphView.viewport()->size());
qGraphSceneL.addItem(&qItemGrid);
qGraphView.setScene(&qGraphSceneL);
qTglGridL.setCheckState(
qItemGrid.isVisible() ? Qt::Checked : Qt::Unchecked);
qTglGridR.setCheckState(
canvas.gridVisible() ? Qt::Checked : Qt::Unchecked);
// install signal handlers
QObject::connect(&qTglGridL, &QCheckBox::stateChanged,
[&qItemGrid](int state)
{
qItemGrid.setVisible(state != Qt::Unchecked);
});
QObject::connect(&qTglGridR, &QCheckBox::stateChanged,
[&canvas](int state)
{
canvas.setGridVisible(state != Qt::Unchecked);
});
// runtime loop
return app.exec();
}
使用 VS2013 和 Qt 5.9.2 编译,在 Window 10(64 位)上测试:
更新:
QMake 脚本testQGraphicsView-BgGrid.pro
:
SOURCES = testQGraphicsView-BgGrid.cc
QT += widgets
在 cygwin 上 bash
构建和测试:
$ qmake-qt5 testQGraphicsView-BgGrid.pro
$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQGraphicsView-BgGrid.o testQGraphicsView-BgGrid.cc
g++ -o testQGraphicsView-BgGrid.exe testQGraphicsView-BgGrid.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
$ ./testQGraphicsView-BgGrid
与 X11 应用程序相同的程序:
又一个更新:
我不得不承认,在我的第一个版本中,我专注于如何使用复选框更改 QGraphicsView 背景,重点是复选框 忽略 QGraphicsScene::drawBackground()
(which I didn't know) and ignoring issues in the grid rendering itself (which I used instead). As pointed out in
左视图(涉及到场景中的网格)不一定填满
viewport()
。恕我直言,如果网格填充场景使用的相关范围,这是可以接受的。 (这可能是为了形象化场景只覆盖了viewport()
的一部分。)然而,makeGrid()
的参数const QSize &size
是这个意图的一个不幸的选择。我通过将其替换为const QRect &rect
. 来解决此设计问题
右视图(重载
paintEvent()
)没有考虑可能的场景滚动。我通过将左上角映射到场景坐标 (const QPointF offs = mapToScene(0, 0);
) 并将偏移量视为循环中的起始值来修复此问题。
更新示例代码testQGrapicsView-BgGrid.cc
:
#include <QtWidgets>
class Canvas: public QGraphicsView {
private:
int _gridSize;
QColor _gridColor;
bool _gridVisible;
public:
explicit Canvas(QWidget *pQParent = nullptr):
QGraphicsView(pQParent),
_gridSize(20), _gridColor(0x0a8affu), _gridVisible(true)
{ }
bool gridVisible() const { return _gridVisible; }
void setGridVisible(bool gridVisible)
{
_gridVisible = gridVisible;
viewport()->update();
}
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override
{
QPainter qPainter(viewport());
if (_gridVisible) {
const int wView = viewport()->width(), hView = viewport()->height();
const QPointF offs = mapToScene(0, 0);
qPainter.setPen(_gridColor);
for (int x = (int)offs.x() % _gridSize; x < wView; x += _gridSize) {
qPainter.drawLine(x, 0, x, hView - 1);
}
for (int y = (int)offs.y() % _gridSize; y < hView; y += _gridSize) {
qPainter.drawLine(0, y, wView - 1, y);
}
}
QGraphicsView::paintEvent(pQEvent);
}
};
void makeGrid(
QGraphicsItemGroup &qItemGrp, const QRect &rect,
int gridSize = 20, const QColor &gridColor = 0x0a8affu)
{
for (int x = rect.x(), xE = x + rect.width(); x < xE; x += gridSize) {
QGraphicsLineItem *pQItem
= new QGraphicsLineItem(x, rect.y(), x, rect.height() - 1);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
for (int y = rect.y(), yE = y + rect.height(); y < yE; y += gridSize) {
QGraphicsLineItem *pQItem
= new QGraphicsLineItem(rect.x(), y, rect.width() - 1, y);
pQItem->setPen(gridColor);
qItemGrp.addToGroup(pQItem);
}
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWnd;
QGridLayout qGrid;
QLabel qLblL(QString::fromUtf8("Grid as part of scene"));
qGrid.addWidget(&qLblL, 0, 0);
QCheckBox qTglGridL(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridL, 0, 1);
QGraphicsView qGraphView;
qGrid.addWidget(&qGraphView, 1, 0, 1, 2);
QLabel qLblR(QString::fromUtf8("Grid painted as background"));
qGrid.addWidget(&qLblR, 0, 2);
QCheckBox qTglGridR(QString::fromUtf8("Show Grid"));
qGrid.addWidget(&qTglGridR, 0, 3);
Canvas canvas;
qGrid.addWidget(&canvas, 1, 2, 1, 2);
qWnd.setLayout(&qGrid);
qWnd.show();
// init GUI
QGraphicsScene qGraphSceneL;
QGraphicsItemGroup qItemGrid;
makeGrid(qItemGrid, QRect(0, 0, 320, 240));
qGraphSceneL.addItem(&qItemGrid);
qGraphView.setScene(&qGraphSceneL);
qTglGridL.setCheckState(
qItemGrid.isVisible() ? Qt::Checked : Qt::Unchecked);
qTglGridR.setCheckState(
canvas.gridVisible() ? Qt::Checked : Qt::Unchecked);
// install signal handlers
QObject::connect(&qTglGridL, &QCheckBox::stateChanged,
[&qItemGrid](int state)
{
qItemGrid.setVisible(state != Qt::Unchecked);
});
QObject::connect(&qTglGridR, &QCheckBox::stateChanged,
[&canvas](int state)
{
canvas.setGridVisible(state != Qt::Unchecked);
});
// runtime loop
return app.exec();
}
以下快照显示了启动后和调整大小后的应用程序:
虽然@Scheff的方案很好,但是存在以下问题:
第一个解决方案让它只覆盖一小部分space,如果你改变QGraphicsView的大小它不会覆盖所有space.
第二个解决方案有问题,你使用的是
viewport()
坐标,而不是场景,如果你添加一个项目然后在不移动项目的情况下放大QGraphicsView,那么你看到一个卷轴。
初始:
更改大小后:
纠正这两个错误的解决方案是覆盖 QGraphicsScene 的 drawBackground 方法:
#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H
#include <QGraphicsScene>
#include <QPainter>
class GraphicsScene: public QGraphicsScene{
int mGridSize;
QColor mGridColor;
bool mGridVisible;
Q_OBJECT
public:
GraphicsScene(QObject *parent = Q_NULLPTR):QGraphicsScene(parent),
mGridSize(20), mGridColor(0x0a8affu), mGridVisible(true)
{
}
bool gridVisible() const {
return mGridVisible;
}
void setGridVisible(bool gridVisible){
if(mGridVisible != gridVisible){
mGridVisible = gridVisible;
update();
}
}
protected:
void drawBackground(QPainter *painter, const QRectF &rect){
if(mGridVisible) {
QRect r = rect.toRect();
int xmin =r.left() - r.left()%mGridSize - mGridSize;
int ymin = r.top() - r.top()%mGridSize - mGridSize;
int xmax = r.right() - r.right()%mGridSize + mGridSize;
int ymax = r.bottom() - r.bottom()%mGridSize + mGridSize;
for(int x=xmin ; x <= xmax; x += mGridSize ){
painter->drawLine(x, r.top(), x, r.bottom());
}
for(int y=ymin ; y <= ymax; y+= mGridSize ){
painter->drawLine(r.left(), y, r.right(), y);
}
}
}
};
#endif // GRAPHICSSCENE_H
这个方案的优点是不加载任何新的对象,而且图形在场景的坐标中,所以没有第二种方案的位移。
初始:
更改大小后:
完整的例子可以在下面找到link