繪圖簡介
Qt5繪畫系統能夠呈現矢量圖形,圖像,和大綱font-based文本。
我們也可以在程序中調用系統api自定義繪圖控件。
繪圖要在paintEvent()方法中實現。
在QPainter對象的begin()與end()方法間編寫繪圖代碼。
它會在控件或其他圖形設備上進行低級的圖形繪製。
案例說明
- 在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
- 相信大多 數人和我一樣,剛開始的時候都認爲 drawText() 的 x, y 是字符串左上角的座標,其實不然,它是字符串的第一個字符的 origin 的座標,y 是字體的 base line 的 y 座標。
- 本案例窗口顯示文本.
- 參考文章:https://blog.csdn.net/TemetNosce/article/details/78068520
demo.go
package main
import (
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/widgets"
"os"
)
/*
我們先以窗體內Unicode文本的繪製爲例。
在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
相信大多 數人和我一樣,剛開始的時候都認爲 drawText() 的 x, y 是字符串左上角的座標,其實不然,它是字符串的第一個字符的 origin 的座標,y 是字體的 base line 的 y 座標
*/
func InitUi() *widgets.QMainWindow {
// 創建窗口
app := widgets.NewQMainWindow(nil, 0)
// 設置窗口的標題
app.SetWindowTitle("Qt 教程")
// 設置窗口的位置和大小
app.SetGeometry2(300, 300, 300, 220)
// 設置窗口的圖標,引用當前目錄下的web.png圖片
app.SetWindowIcon(gui.NewQIcon5("images/app.ico"))
// 佈局窗口組件載體
widget := widgets.NewQWidget(app, core.Qt__Widget)
//widget.SetGeometry(core.NewQRect4(300, 300, 300, 220))
//widget.SetGeometry2(0, 0, 300, 220)
app.SetCentralWidget(widget)
// 狀態欄
app.StatusBar()
widget.ConnectPaintEvent(func(event *gui.QPaintEvent) {
qp := gui.NewQPainter2(widget)
//qp.Begin(widget)
qp.SetRenderHint(gui.QPainter__Antialiasing, true)
// 定義一個畫筆和一個字體用於繪製文本。
qp.SetFont(gui.NewQFont2("Times", 100, 0, true))
qp.SetPen2(gui.NewQColor3(0, 0, 0, 0))
//qp.DrawText3(150, 150, "jEh")
// 方法將文本繪製在窗體,顯示在中心
qp.DrawText4(event.Rect(), int(core.QTextStream__AlignCenter), "text", widget.Rect())
qp.End()
})
return app
}
func main() {
// 創建一個應用程序對象
// sys.argv參數是一個列表,從命令行輸入參數
widgets.NewQApplication(len(os.Args), os.Args)
// 初始化窗口
app := InitUi()
// 顯示組件
app.Show()
// 確保應用程序乾淨的退出
widgets.QApplication_Exec()
}
demo2.go
package main
import (
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/widgets"
"os"
)
/*
我們先以窗體內Unicode文本的繪製爲例。
在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
還是原來的問題,從 widget 的左上角開始繪製文本,那麼 y 就應該和 ascent 一樣大,但是怎麼得到 ascent 的值呢?難到需要我們記住每種字體的 ascent 的值嗎?這也是一種方法,如果願意,未嘗不可,但是,腦子夠用麼,幸好 QFontMetrics 就能夠給我們提供字體的信息,提供了很多函數,如取得 line height 用 height(),用 width() 計算字符串的寬度,ascent(), descent(), xHeight() 等, 函數的名字已經很好的表明它的作用,在此就不再一一介紹,更多的函數請參考 Qt 的幫助文檔。所以爲了達到我們的目的,只需要把 y = 0 修改爲 int y = metrics.ascent() 就可以了:
原文鏈接:https://blog.csdn.net/TemetNosce/article/details/78068520
*/
func InitUi() *widgets.QMainWindow {
// 創建窗口
app := widgets.NewQMainWindow(nil, 0)
// 設置窗口的標題
app.SetWindowTitle("Qt 教程")
// 設置窗口的位置和大小
app.SetGeometry2(300, 300, 300, 220)
// 設置窗口的圖標,引用當前目錄下的web.png圖片
app.SetWindowIcon(gui.NewQIcon5("images/app.ico"))
// 佈局窗口組件載體
widget := widgets.NewQWidget(app, core.Qt__Widget)
//widget.SetGeometry(core.NewQRect4(300, 300, 300, 220))
//widget.SetGeometry2(0, 0, 300, 220)
app.SetCentralWidget(widget)
// 狀態欄
app.StatusBar()
widget.ConnectPaintEvent(func(event *gui.QPaintEvent) {
qp := gui.NewQPainter2(widget)
//qp.Begin(widget)
qp.SetRenderHint(gui.QPainter__Antialiasing, true)
qp.SetFont(gui.NewQFont2("Times", 100, 0, true))
metrics :=qp.FontMetrics()
y := metrics.Ascent()
qp.DrawText3(0, y, "jEh")
qp.End()
})
return app
}
func main() {
// 創建一個應用程序對象
// sys.argv參數是一個列表,從命令行輸入參數
widgets.NewQApplication(len(os.Args), os.Args)
// 初始化窗口
app := InitUi()
// 顯示組件
app.Show()
// 確保應用程序乾淨的退出
widgets.QApplication_Exec()
}
demo3.go
package main
import (
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/widgets"
"os"
)
/*
我們先以窗體內Unicode文本的繪製爲例。
在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
還是原來的問題,從 widget 的左上角開始繪製文本,那麼 y 就應該和 ascent 一樣大,但是怎麼得到 ascent 的值呢?難到需要我們記住每種字體的 ascent 的值嗎?這也是一種方法,如果願意,未嘗不可,但是,腦子夠用麼,幸好 QFontMetrics 就能夠給我們提供字體的信息,提供了很多函數,如取得 line height 用 height(),用 width() 計算字符串的寬度,ascent(), descent(), xHeight() 等, 函數的名字已經很好的表明它的作用,在此就不再一一介紹,更多的函數請參考 Qt 的幫助文檔。所以爲了達到我們的目的,只需要把 y = 0 修改爲 int y = metrics.ascent() 就可以了:
原文鏈接:https://blog.csdn.net/TemetNosce/article/details/78068520
居中繪製文本
有了 QFontMetrics,想必對大家來說問題已經不大,得到字符串的寬、高、ascent,簡單的居中計算,就可以得到 origin 的座標了。
*/
func InitUi() *widgets.QMainWindow {
// 創建窗口
app := widgets.NewQMainWindow(nil, 0)
// 設置窗口的標題
app.SetWindowTitle("Qt 教程")
// 設置窗口的位置和大小
app.SetGeometry2(300, 300, 300, 220)
// 設置窗口的圖標,引用當前目錄下的web.png圖片
app.SetWindowIcon(gui.NewQIcon5("images/app.ico"))
// 佈局窗口組件載體
widget := widgets.NewQWidget(app, core.Qt__Widget)
//widget.SetGeometry(core.NewQRect4(300, 300, 300, 220))
//widget.SetGeometry2(0, 0, 300, 220)
app.SetCentralWidget(widget)
// 狀態欄
app.StatusBar()
widget.ConnectPaintEvent(func(event *gui.QPaintEvent) {
qp := gui.NewQPainter2(widget)
//qp.Begin(widget)
qp.SetRenderHint(gui.QPainter__Antialiasing, true)
qp.SetFont(gui.NewQFont2("Times", 100, 0, true))
rect :=core.NewQRect4(20, 20, 300, 200)
qp.DrawRect3(rect)
// 居中繪製文本
metrics :=qp.FontMetrics()
stringHeight := metrics.Ascent() + metrics.Descent() // 不算 line gap
stringWidth := metrics.AverageCharWidth() // 字符串的寬度
x := rect.X() + (rect.Width() - stringWidth) / 2
y := rect.Y() + (rect.Height() - stringHeight) / 2 + metrics.Ascent()
qp.DrawText3(x, y, "jEh")
// 繪製字符串的包圍矩形
y = rect.Y() + (rect.Height() - stringHeight) / 2
//qp.SetPen(core.Qt__lightGray)
qp.DrawRect2(x, y, stringWidth, stringHeight)
/*
把字體的包圍矩形也畫出來,這樣就能很清晰的看到字符串的居中效果了。也許你還會問,這不是還有一點點沒有居中嗎?這個和字體有關係,換成等寬字體如 Menlo 後就可以看到確實是完全居中的,說明 QFontMetrics 得到的字體信息沒問題,只是有的字體爲了美觀漂亮作了一些調整,對於這些字體如果要完全的居中效果的話,只好在使用上面的計算方式後再手動的微調一下就好了。
*/
qp.End()
})
return app
}
func main() {
// 創建一個應用程序對象
// sys.argv參數是一個列表,從命令行輸入參數
widgets.NewQApplication(len(os.Args), os.Args)
// 初始化窗口
app := InitUi()
// 顯示組件
app.Show()
// 確保應用程序乾淨的退出
widgets.QApplication_Exec()
}
demo4.go
package main
import (
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/widgets"
"os"
)
/*
我們先以窗體內Unicode文本的繪製爲例。
在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
還是原來的問題,從 widget 的左上角開始繪製文本,那麼 y 就應該和 ascent 一樣大,但是怎麼得到 ascent 的值呢?難到需要我們記住每種字體的 ascent 的值嗎?這也是一種方法,如果願意,未嘗不可,但是,腦子夠用麼,幸好 QFontMetrics 就能夠給我們提供字體的信息,提供了很多函數,如取得 line height 用 height(),用 width() 計算字符串的寬度,ascent(), descent(), xHeight() 等, 函數的名字已經很好的表明它的作用,在此就不再一一介紹,更多的函數請參考 Qt 的幫助文檔。所以爲了達到我們的目的,只需要把 y = 0 修改爲 int y = metrics.ascent() 就可以了:
原文鏈接:https://blog.csdn.net/TemetNosce/article/details/78068520
換行繪製文本
drawText() 繪製文本有兩種方式,不會自動換行和在給定的矩形中自動換行,下面就舉例說明,先繪製一行很長但不會自動換行的文本,然後在給定的矩形 QRect(20, 35, 200, 80) 裏繪製會自動換行,向右靠齊的文本(發現超出矩形的字符不顯示)
*/
func InitUi() *widgets.QMainWindow {
// 創建窗口
app := widgets.NewQMainWindow(nil, 0)
// 設置窗口的標題
app.SetWindowTitle("Qt 教程")
// 設置窗口的位置和大小
app.SetGeometry2(300, 300, 300, 220)
// 設置窗口的圖標,引用當前目錄下的web.png圖片
app.SetWindowIcon(gui.NewQIcon5("images/app.ico"))
// 佈局窗口組件載體
widget := widgets.NewQWidget(app, core.Qt__Widget)
//widget.SetGeometry(core.NewQRect4(300, 300, 300, 220))
//widget.SetGeometry2(0, 0, 300, 220)
app.SetCentralWidget(widget)
// 狀態欄
app.StatusBar()
widget.ConnectPaintEvent(func(event *gui.QPaintEvent) {
qp := gui.NewQPainter2(widget)
//qp.Begin(widget)
qp.SetRenderHint(gui.QPainter__Antialiasing, true)
text := "QPainter provides highly optimized functions to do " +
"most of the drawing GUI programs require. It can draw " +
"everything from simple lines to complex shapes " +
"like pies and chords. " +
"看看是否也支持中文呢,如果不支持那就悲劇了!"
rect := core.NewQRect4(20, 20, 300, 200)
qp.DrawRect3(rect) // 畫出矩形,可以看到超出此矩形的部分文本不可見
//core.Qt__TextWordWrap | core.Qt__AlignRight
qp.DrawText4(rect, int(core.Qt__TextWordWrap), text, rect)
qp.End()
})
return app
}
func main() {
// 創建一個應用程序對象
// sys.argv參數是一個列表,從命令行輸入參數
widgets.NewQApplication(len(os.Args), os.Args)
// 初始化窗口
app := InitUi()
// 顯示組件
app.Show()
// 確保應用程序乾淨的退出
widgets.QApplication_Exec()
}
demo5.go
package main
import (
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/widgets"
"os"
)
/*
我們先以窗體內Unicode文本的繪製爲例。
在我們的示例中,我們繪製一些Cylliric文本。文本垂直和水平對齊。
還是原來的問題,從 widget 的左上角開始繪製文本,那麼 y 就應該和 ascent 一樣大,但是怎麼得到 ascent 的值呢?難到需要我們記住每種字體的 ascent 的值嗎?這也是一種方法,如果願意,未嘗不可,但是,腦子夠用麼,幸好 QFontMetrics 就能夠給我們提供字體的信息,提供了很多函數,如取得 line height 用 height(),用 width() 計算字符串的寬度,ascent(), descent(), xHeight() 等, 函數的名字已經很好的表明它的作用,在此就不再一一介紹,更多的函數請參考 Qt 的幫助文檔。所以爲了達到我們的目的,只需要把 y = 0 修改爲 int y = metrics.ascent() 就可以了:
原文鏈接:https://blog.csdn.net/TemetNosce/article/details/78068520
文本的包圍矩形
一般顯示的寬度應該是確定的,關鍵是高度的計算,可以逐個字符的把他們的寬度加起來(不同的字體每個字符的寬度不一樣),當大於顯示的寬度就換行,高度也對應的加上一行的高度,這樣就能計算出最終的高度了,也就知道了顯示消息的矩形大小,使用這個方法就能自適應的顯示消息了。
雖然我們已經知道了自適應顯示消息的原理,但是如果是我們自己來計算實現,難度還是不小的,其實 Qt 已經給我們提供了相關的 API,使用 QFontMetrics::boundingRect() 可以計算出包圍文本的矩形,然後在用上面的方法繪製文本就可以了,下面的程序,改變窗口的寬度,能動態的計算出顯示文本所有內容的包圍矩形,解決了上面提到的在給定的矩形中,文本太長時顯示不全的問題
*/
func InitUi() *widgets.QMainWindow {
// 創建窗口
app := widgets.NewQMainWindow(nil, 0)
// 設置窗口的標題
app.SetWindowTitle("Qt 教程")
// 設置窗口的位置和大小
app.SetGeometry2(300, 300, 300, 220)
// 設置窗口的圖標,引用當前目錄下的web.png圖片
app.SetWindowIcon(gui.NewQIcon5("images/app.ico"))
// 佈局窗口組件載體
widget := widgets.NewQWidget(app, core.Qt__Widget)
//widget.SetGeometry(core.NewQRect4(300, 300, 300, 220))
//widget.SetGeometry2(0, 0, 300, 220)
app.SetCentralWidget(widget)
// 狀態欄
app.StatusBar()
widget.ConnectPaintEvent(func(event *gui.QPaintEvent) {
qp := gui.NewQPainter2(widget)
//qp.Begin(widget)
qp.SetRenderHint(gui.QPainter__Antialiasing, true)
text := "QPainter provides highly optimized functions to do " +
"most of the drawing GUI programs require. It can draw " +
"everything from simple lines to complex shapes " +
"like pies and chords. " +
"看看是否也支持中文呢,如果不支持那就悲劇了!"
width := widget.Width() - 40 // 顯示文本的寬度,爲窗口的寬度減去 40 像素
flags := int(core.Qt__TextWordWrap) // 自動換行
// 計算文本在指定寬度下的包圍矩形
metrics := qp.FontMetrics()
rect := core.NewQRect4(0, 0, width, 0)
textBoundingRect := metrics.BoundingRect3(rect, flags, text, 4, 4)
qp.Translate3(20, 20)
qp.DrawRect3(textBoundingRect)
qp.DrawText4(textBoundingRect, flags, text, rect)
qp.End()
})
return app
}
func main() {
// 創建一個應用程序對象
// sys.argv參數是一個列表,從命令行輸入參數
widgets.NewQApplication(len(os.Args), os.Args)
// 初始化窗口
app := InitUi()
// 顯示組件
app.Show()
// 確保應用程序乾淨的退出
widgets.QApplication_Exec()
}