前言
最近一直使用QGraphicsView架構在我的一個實際項目中,官方文檔好多都沒說清楚啊,有木有?!文檔都翻光了,卻還是有好多沒明白。
一個令我惱火的bug就是,明明log打出來的每個Item的坐标都是預期的,但為什麼最後結果不對呢?
我在視圖中添加了一個直線項(QPoint(0,0),QPoint(100,100));
結果卻是:
有的同行看到可能會一下指出,我沒有設定QGraphicsScene的SceneRect,是以所有的元素預設顯示。
是的,上面這個例子的确如此,但是即使我們設定了呢,結果卻是這樣:
直線項确實不居中了,但是端點也沒有在左上角啊!下面,我們就來深入結合例子弄清楚這一些問題。
解決之道
先上demo代碼,很簡單,
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsView>
#include<QGraphicsScene>
#include<QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = );
~MainWindow();
void showView();//顯示graphicsView的函數
private:
QGraphicsScene *graphicsScene;//scene聲明
QGraphicsView *graphicsView;//view聲明
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
graphicsScene = new QGraphicsScene(this);
graphicsView = new QGraphicsView(graphicsScene,this);
QSize window =this->size();
graphicsView->setFixedSize(this->width(),this->height());
graphicsScene->addLine(,,,);
}
void MainWindow::showView()
{
graphicsView->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug() <<"line location:"<<"\n";
qDebug()<<"startPoint:" <<QPoint(,);
qDebug()<<"endPoint:" <<QPoint(,);
MainWindow w;
w.show();
w.showView();
return a.exec();
}
這份代碼确實是QGraphicsScene和QGraphicsView的基本代碼,并沒有設定QGraphicsScene的sceneRect,是以結果也是大家可以預測的那樣居中顯示:
但是!很多時候架構中自認為很令人友善的設計一點都不利于我們開發,我們開發人員習慣的坐标系統是左上角為(0,0)的坐标系統!
于是,官方給出了解決方案:使用void setSceneRect(const QRectF & rect)控制sceneRect區域,這很人迷惑,就在我們這個例子中,我們想讓scene左上角坐标是(0,0),是不是說隻需要scene->setSceneRect(QRectF(0,0,W,H)就可以了呢?很遺憾的是,實驗結果告訴我們不是:
我們在上面的mainwindow.cpp裡面設定scenRect為(0,0,150,150)試試看!:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
graphicsScene = new QGraphicsScene(this);
graphicsView = new QGraphicsView(graphicsScene,this);
QSize window =this->size();
graphicsView->setFixedSize(this->width(),this->height());
graphicsScene->setSceneRect(,,,);
graphicsScene->addLine(,,,);
}
void MainWindow::showView()
{
graphicsView->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
結果是:
結果不是預期!
其實,正确的解決方案是setSceneRect(0,0,W,H);而且需要
- W>=static_cast< QWidget *>(graphicsScene->parent())->size().width()
- H>=static_cast< QWidget *>(graphicsScene->parent())->size().height()
看再次修改後的代碼:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QWidget>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
graphicsScene = new QGraphicsScene(this);
graphicsView = new QGraphicsView(graphicsScene,this);
QSize windowsize =this->size();
graphicsView->setFixedSize(this->width(),this->height());
graphicsScene->setSceneRect(,
,static_cast<QWidget *>(graphicsScene->parent())->size().width()
,static_cast<QWidget *>(graphicsScene->parent())->size().height());
graphicsScene->addLine(,,,);
}
void MainWindow::showView()
{
graphicsView->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
運作結果:
下面有相應的工程下載下傳:
戳我下載下傳