天天看點

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

前言

最近一直使用QGraphicsView架構在我的一個實際項目中,官方文檔好多都沒說清楚啊,有木有?!文檔都翻光了,卻還是有好多沒明白。

一個令我惱火的bug就是,明明log打出來的每個Item的坐标都是預期的,但為什麼最後結果不對呢?

我在視圖中添加了一個直線項(QPoint(0,0),QPoint(100,100));

結果卻是:

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

有的同行看到可能會一下指出,我沒有設定QGraphicsScene的SceneRect,是以所有的元素預設顯示。

是的,上面這個例子的确如此,但是即使我們設定了呢,結果卻是這樣:

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

直線項确實不居中了,但是端點也沒有在左上角啊!下面,我們就來深入結合例子弄清楚這一些問題。

解決之道

先上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,是以結果也是大家可以預測的那樣居中顯示:

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

但是!很多時候架構中自認為很令人友善的設計一點都不利于我們開發,我們開發人員習慣的坐标系統是左上角為(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;
}
           

結果是:

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

結果不是預期!

其實,正确的解決方案是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;
}
           

運作結果:

QGraphicsView架構容易忽視的坐标問題-“畫布”QgraphicsScene到底放在了哪兒?前言 解決之道

下面有相應的工程下載下傳:

戳我下載下傳