論Qt4的視口(ViewPort)與窗口(Window)


最近在研究Qt的2D繪圖部分,對窗口和視口比較感興趣,故寫幾個測試程序來加深理解。

PaintDemo.h

#ifndef PAINTDEMO_H
#define PAINTDEMO_H
#include <QWidget>
class QPaintEvent;

class PaintDemo : public QWidget
{
    public:
        PaintDemo();
    protected:
        void paintEvent(QPaintEvent *event);
};
#endif

PaintDemo.cpp

#include <QPainter>
#include "PaintDemo.h"

PaintDemo::PaintDemo()
{
    resize(800, 600);
    setWindowTitle(tr("Paint Demo"));
}

void PaintDemo::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::black, 2));
    painter.drawLine(0,0,800,600);
}

在構造函數中將窗口大小設置為800x600,在paintEvent中從(0,0)到(800,600)繪制了一條Line,斜貫整個窗口:

此時,我們拉動改變窗口的大小,顯然,窗口右下角的坐標不再是(800,600),而且其它更大的一個數值,譬如(900,700),而我們的線只畫到(800,600),所以剩下的一段是空白。如下圖所示:

OK,我們來修改一下代碼,在繪制Line前加上一行

painter.setWindow(0,0,800,600);

修改后的PaintDemo.cpp代碼如下(紅色為增加的代碼):

#include <QPainter>
#include "PaintDemo.h"

PaintedDemo::PaintedDemo()
{
    resize(800, 600);
    setWindowTitle(tr("Paint Demo"));
}

void PaintDemo::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setWindow(0,0,800,600);
    painter.setPen(QPen(Qt::black, 2));
    painter.drawLine(0,0,800,600);
}

編譯運行:

這個時候我們發現不管怎樣拉動窗口,Line永遠貫穿整個窗口:

這說明painter.setWindow(0,0,800,600)將整個窗口設置為一個區域,左上角為原點,X坐標的終點為800,即窗口的寬度,Y坐標的終點為600,即窗口高度,這樣,不管窗口怎么變化,右下角的坐標始終為(800,600),因此我們的Line始終貫穿整個窗口。

OK,我們再接再厲,將ViewPort也設置一下,PaintDemo.cpp代碼如下(紅色為增加的代碼):

#include <QPainter>
#include "PaintDemo.h"

PaintDemo::PaintDemo()
{
    resize(800, 600);
    setWindowTitle(tr("Paint Demo"));
}

void PaintDemo::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setViewport(0,0,800,600);
    painter.setWindow(0,0,800,600);
    painter.setPen(QPen(Qt::black, 2));
    painter.drawLine(0,0,800,600);
}

 編譯運行,這時我們會驚奇的發現,Line又不能貫穿整個窗口了

再來,我們將Viewport改小一點,寬度由800改為300,高度由600改為400,結果如何?看圖:

現在可以得到結論了,Qt通過QPainter::setWindow將窗口坐標映射到視口坐標,而QPainter::setViewport則用來指定在窗體上所能繪制的區域。

關於Qt的坐標系統其實在Qt的doc里已經講得很詳細了,具體請參看:

http://qt-project.org/doc/qt-4.8/coordsys.html#window-viewport-conversion

這里借用一張圖說明一下:

世界坐標通過矩陣轉換成窗口坐標,然后通過窗口到視口的映射轉換成設備坐標。

我這里的說明省略了矩陣變換,其實從邏輯坐標到窗口坐標之間還要進行矩陣變換。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM