<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #(24):Qt 繪制系統簡介 Qt 的繪圖系統允許使用相同的 API 在屏幕和其它打印設備上進行繪制。整個繪圖系統基于`QPainter`,`QPainterDevice`和`QPaintEngine`三個類。 `QPainter`用來執行繪制的操作;`QPaintDevice`是一個二維空間的抽象,這個二維空間允許`QPainter`在其上面進行繪制,也就是`QPainter`工作的空間;`QPaintEngine`提供了畫筆(`QPainter`)在不同的設備上進行繪制的統一的接口。`QPaintEngine`類應用于`QPainter`和`QPaintDevice`之間,通常對開發人員是透明的。除非你需要自定義一個設備,否則你是不需要關心`QPaintEngine`這個類的。我們可以把`QPainter`理解成畫筆;把`QPaintDevice`理解成使用畫筆的地方,比如紙張、屏幕等;而對于紙張、屏幕而言,肯定要使用不同的畫筆繪制,為了統一使用一種畫筆,我們設計了`QPaintEngine`類,這個類讓不同的紙張、屏幕都能使用一種畫筆。 下圖給出了這三個類之間的層次結構(出自 Qt API 文檔): [![](https://box.kancloud.cn/2015-12-29_5682324e4dad6.png)](http://files.devbean.net/images/2012/10/paint-system.png) 上面的示意圖告訴我們,Qt 的繪圖系統實際上是,使用`QPainter`在`QPainterDevice`上進行繪制,它們之間使用`QPaintEngine`進行通訊(也就是翻譯`QPainter`的指令)。 下面我們通過一個實例來介紹`QPainter`的使用: ~~~ //!!! Qt4/Qt5 class PaintedWidget : public QWidget { Q_OBJECT public: PaintedWidget(QWidget *parent = 0); protected: void paintEvent(QPaintEvent *); }; ~~~ 注意我們重寫了`QWidget`的`paintEvent()`函數。這或許是我們在理解了 Qt 事件系統之后首次實際應用。接下來就是`PaintedWidget`的源代碼: ~~~ //!!! Qt4/Qt5 PaintedWidget::PaintedWidget(QWidget *parent) : QWidget(parent) { resize(800, 600); setWindowTitle(tr("Paint Demo")); } void PaintedWidget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawLine(80, 100, 650, 500); painter.setPen(Qt::red); painter.drawRect(10, 10, 100, 400); painter.setPen(QPen(Qt::green, 5)); painter.setBrush(Qt::blue); painter.drawEllipse(50, 150, 400, 200); } ~~~ 在構造函數中,我們僅僅設置了窗口的大小和標題。而`paintEvent()`函數則是繪制的代碼。首先,我們在棧上創建了一個`QPainter`對象,也就是說,每次運行`paintEvent()`函數的時候,都會重建這個`QPainter`對象。注意,這一點可能會引發某些細節問題:由于我們每次重建`QPainter`,因此第一次運行時所設置的畫筆顏色、狀態等,第二次再進入這個函數時就會全部丟失。有時候我們希望保存畫筆狀態,就必須自己保存數據,否則的話則需要將`QPainter`作為類的成員變量。 `QPainter`接收一個`QPaintDevice`指針作為參數。`QPaintDevice`有很多子類,比如`QImage`,以及`QWidget`。注意回憶一下,`QPaintDevice`可以理解成要在哪里去繪制,而現在我們希望畫在這個組件,因此傳入的是 this 指針。 `QPainter`有很多以 draw 開頭的函數,用于各種圖形的繪制,比如這里的`drawLine()`,`drawRect()`以及`drawEllipse()`等。當繪制輪廓線時,使用`QPainter`的`pen()`屬性。比如,我們調用了`painter.setPen(Qt::red)`將 pen 設置為紅色,則下面繪制的矩形具有紅色的輪廓線。接下來,我們將 pen 修改為綠色,5 像素寬(`painter.setPen(QPen(Qt::green, 5))`),又設置了畫刷為藍色。這時候再調用 draw 函數,則是具有綠色 5 像素寬輪廓線、藍色填充的橢圓。 運行一下我們的程序,可以看到最終效果: [![](https://box.kancloud.cn/2015-12-29_5682324e5f463.png)](http://files.devbean.net/images/2012/10/paint-demo.png) 我們會在后面的章節詳細介紹畫筆`QPen`和畫刷`QBrush`的屬性。 另外要說明一點,請注意我們的繪制順序,首先是直線,然后是矩形,最后是橢圓。按照這樣的繪制順序,可以看到直線是第一個繪制,位于最下一層;矩形是第二個繪制,在中間一層;橢圓是最后繪制,在最上層。 如果了解 OpenGL,肯定聽說過這么一句話:OpenGL 是一個狀態機。所謂狀態機,就是說,OpenGL 保存的只是各種狀態。比如,將畫筆顏色設置成紅色,那么,除非你重新設置另外的顏色,它的顏色會一直是紅色。`QPainter`也是這樣,它的狀態不會自己恢復,除非你使用了各種設置函數。因此,如果在上面的代碼中,我們在橢圓繪制之后再畫一個矩形,它的樣式還會是綠色 5 像素的輪廓線以及藍色的填充,除非你顯式地調用了設置函數進行狀態的更新。這是大多數繪圖系統的實現方式,包括 OpenGL、`QPainter`以及 Java2D。正因為`QPainter`是一個狀態機,才會引出我們前面曾經介紹過的一個細節問題:由于`paintEvent()`是需要重復進入的,因此,需要注意第二次進入時,`QPainter`的狀態是不是和第一次一致,否則的話可能會造成閃爍的現象。這個閃爍并不是由于雙緩沖的問題,而是由于繪制狀態的快速切換。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看