Go-Qt5开发之绘制文本(34)

绘图简介

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()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值