Mint_21.3 drawing-area和goocanvas的FB笔记(一)

一、关于freebasic和goocanvas

Linux下的FreeBasic是C的一种实现,有指针、类、线程,正则表达式,可内嵌asm和其它语言c等,c的h库几乎都能改写后使用(不能直接用,它的.bi可从h近乎自动转换),老的Quick Basic语句也能使用,屏幕方式增加了 screenres x, y 按屏幕尺寸像素定义大小, 比如 screenres 1920, 1080等, 其它语言写成的.so动态库可以类似.h一样写.bi, 然后即可调用,最后编译成本地二制执行文件,调用sqlite, mysql, postgreSQL也行。它free, 功能比较全,稳定性比较好。c能用的界面库它都能用,比较典型的是gtk库,基于cairo的goocanvas也比较有趣。下面的图一是freeBasic操作goocanvas实现的items分组、变换、和模拟运动。

(图一、goocanvas表格图)

下图的上部分是cairo渲染的png图,下部分是goocanvas画线、矩形和文字显示。

(图二、cairo png和goo canvas画图)

下图的上部分是cairo渲染的pixbuf像素数据,下部分是goocanvas画线、矩形和文字显示。

(图三、pixbuf作为cairo的surface渲染)

下图的上部分是cairo渲染的语句绘图,下部分是goocanvas画线、矩形和文字显示。

二、界面设计笔记

界面垂直分成四个部分,上部cairo绘图区、label显示区、goocanvas绘图区、操作区。设计时可用glade作界面设计, box1留一个空位并置入一个gtxbox, ID为canvasbox,在编程时将goocanvas作为一个gtkwidget放入其中,大小也是程序中直接写,glade只需留出带gtkbox的空位即可。设计好后存成文件 glade_newui.glade, 程序中gtk_builder会取出widget属性和信号,程序中也可改写。

将widget作为GObject,定义其指针; 建gtkbuilder; 将glade中的widget与定义的指针对应起来,然后定义一个goocanvas并将写放入到预留的canbox中,最后将界面最大化。

DIM AS STRING GUISTR
DIM SHARED AS GtkBuilder PTR XML
DIM SHARED AS GObject PTR window1
DIM SHARED AS GObject PTR box1
DIM SHARED AS GObject PTR canbox
DIM SHARED AS GObject PTR button1
DIM SHARED AS GObject PTR button2
DIM SHARED AS GObject PTR button3
DIM SHARED AS GObject PTR button4
DIM SHARED AS GObject PTR label1
DIM SHARED AS GObject PTR drawarea1
DIM SHARED AS Gerror PTR errptr
Dim shared as GtkWidget PTR canvas
Dim shared as GooCanvasItem PTR root

XML = gtk_builder_new()
GUISTR="glade_newui.glade"

window1 = gtk_builder_get_object(XML, @"window")
box1 = gtk_builder_get_object(XML, @"box1")
canbox = gtk_builder_get_object(XML, @"canvasbox")
drawarea1 = gtk_builder_get_object(XML, @"drawarea1")
button1 = gtk_builder_get_object(XML, @"button1")
button2 = gtk_builder_get_object(XML, @"button2")
button3 = gtk_builder_get_object(XML, @"button3")
button4 = gtk_builder_get_object(XML, @"button4")
label1 = gtk_builder_get_object(XML, @"label1")

canvas = goo_canvas_new ()
root = goo_canvas_get_root_item (GOO_CANVAS (canvas))

gtk_widget_set_size_request (canvas, 600, 250)
gtk_widget_show (canvas)
gtk_container_add (GTK_CONTAINER (canbox), canvas)

gtk_window_maximize(GTK_WINDOW(window1))

三、cairo绘图笔记

glade设计时上部分是 drawingarea1 ,它有个 draw 信号(gtk3),后面写个回调函数的名称。

下面是回调函数,draw信号带来widget指针,cairo-context, 和用户数据指针(如果在glade设计时指定的话),接下来是取得drawingarea1的宽和高(如果界面是sizeable可变的,需要在使用时先取尺寸),然后画个白色的矩形,接着是判断自定义DrawfunctionFlag值,并根据值调用相应的绘图function函数。

FUNCTION on_drawarea1_draw CDECL ALIAS "on_drawarea1_draw" ( _
  BYVAL widget AS GtkWidget PTR, _
  BYVAL cr AS cairo_t PTR, _
  BYVAL user_data AS gpointer) AS gboolean EXPORT

  'get drawingarea width and height
  VAR w = gtk_widget_get_allocated_width(widget)
  VAR h = gtk_widget_get_allocated_height(widget)
  
  'clear drawingarea surface
  DIM AS GdkRGBA col
  col.red = 1: col.green = 1: col.blue = 1: col.alpha = 1
  gdk_cairo_set_source_rgba(cr, @col)  
  cairo_rectangle(cr, 0, 0, w, h)
  cairo_fill(cr)
  cairo_stroke(cr)

  'do as per DrawfuctionFlag value
  If DrawfunctionFlag = 0 then
		on_drawarea1_draw1(widget, cr, user_data)
  elseif DrawfunctionFlag = 1 then
		on_drawarea1_draw2(widget, cr, user_data)
  elseif DrawfunctionFlag = 2 then
		on_drawarea1_draw3(widget, cr, user_data)
  End if
  
  'return a value as per function definition requirement			
  RETURN DrawfunctionFlag
 
END FUNCTION

功能一:用语句直接画个大圆,stroke 到界面上去。

FUNCTION on_drawarea1_draw1 CDECL ALIAS "on_drawarea1_draw1" ( _
  BYVAL widget AS GtkWidget PTR, _
  BYVAL cr AS cairo_t PTR, _
  BYVAL user_data AS gpointer) AS gboolean EXPORT

  VAR w = gtk_widget_get_allocated_width(widget)
  VAR h = gtk_widget_get_allocated_height(widget)

  DIM AS GdkRGBA col

  col.red = 1: col.green = 1: col.blue = 1: col.alpha = 1
  gdk_cairo_set_source_rgba(cr, @col)  
  cairo_rectangle(cr, 0, 0, w, h)
  cairo_fill(cr)
  
  col.red = 1: col.green = 0: col.blue = 0: col.alpha = 1
  gdk_cairo_set_source_rgba(cr, @col)  
  cairo_arc(cr, w/2, h/2, MIN(w/2, h/2), 0, 2 * G_PI)
  
  gdk_cairo_set_source_rgba(cr, @col)  		'Equal to ---> cairo_set_source_rgba (cr, 1 , 0 , 0 , 1)
  cairo_fill(cr)
  
  cairo_stroke(cr)
  RETURN FALSE

END FUNCTION

功能二:用pixbuf数据创建一个surface, 把创建的surface给 draw 信号的cr进行渲染,pixbuf 像素数据就用像素显示到界面上了。

Function on_drawarea1_draw2 cdecl( byval widget as GtkWidget ptr, _
								BYVAL cr AS cairo_t PTR, _
								byval userdata as gpointer) as gboolean 

	Dim surf as cairo_surface_t PTR
	surf = cairo_image_surface_create_for_data (@rgbbuf(0), CAIRO_FORMAT_ARGB32, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_WIDTH*4)
	cairo_set_source_surface(cr, surf, 50, 100)
	
	cairo_paint (cr)
	cairo_surface_destroy(surf)
	
	return TRUE
End function

pixbuf像素数据是个byte数组,一个彩色的像素点如果用rgb表示的话,需要r、g、b三个数据,每个数据一个byte,即8bit,三个数据是24位。数据表示为 Dim shared rgbbuf(IMAGE_WIDTH * IMAGE_HEIGHT * 3) as byte,是全部像素的字节数。

rgb格式加上alpha是rgba格式,因为多了个alpha, 所以Dim shared rgbbuf(IMAGE_WIDTH * IMAGE_HEIGHT * 4) as byte, 为全部像素的字节数。

函数cairo_image_surface_create_for_data的最后一个参数是一行像素的字节数,这样它就知道了断行显示,否则数据连在一起就分不开了。程序定义的是个数组,然后循环赋值。

#define IMAGE_WIDTH  256 
#define IMAGE_HEIGHT 256 

		Dim shared rgbbuf(IMAGE_WIDTH * IMAGE_HEIGHT * 4) as byte
		''create a 32-bit RGB image by adding alpha
		for y = 0 to IMAGE_HEIGHT-1 
			for x = 0 to IMAGE_WIDTH-1 
				rgbbuf(i+0) = y - (y and 31)					'' B
				rgbbuf(i+1) = (x \ 32) * 4 + y - (y and 31) 	'' G				
				rgbbuf(i+2) = x - (x and 31)					'' R
				rgbbuf(i+3) = &HFF								'' A
				
				i += 4
			next 
		next 	

上面的数据画出来的图是下面的格子图

功能三:调用png图片文件作为surface渲染

surf = cairo_image_surface_create_from_png("fblogo.png")

其它不用改动。

Function on_drawarea1_draw3 cdecl( byval widget as GtkWidget ptr, _
								BYVAL cr AS cairo_t PTR, _
								byval userdata as gpointer) as gboolean 
	
	Dim surf as cairo_surface_t PTR
	surf = cairo_image_surface_create_from_png("fblogo.png")
	cairo_set_source_surface(cr, surf, 200, 100)
	cairo_paint (cr)
	cairo_surface_destroy(surf)
	return TRUE
End function

这三个功能通过DrawFunctionFlag的值来选择,公共变量DrawFunctionFlag的值是由操作区的button press动作赋值的。代码写在了函数里,先是改变它的值,然后取得button click信号带过来的user_data这个widget的尺寸,在glade设计时带过来的drawingarea1,所以这里的user_data就是drawingarea1, 下面的一句是驱动drawingarea的draw信号动作的关键一句:

gtk_widget_queue_draw_area (GTK_WIDGET(user_data), 0, 0, w, h)

它是个需要重绘的矩形区,这里是全部区域,也可以是部分需要更新的区域,比如画实时曲线时的很小一部分变化,不过图小的时候全绘也不会有速度问题的。全绘的话,也可以去掉后面的_area,就直接是全绘了,后面的参数也省了。

Function setDrawfunctionFlag CDECL ALIAS "setDrawfunctionFlag" ( _
		BYVAL widget AS GtkWidget PTR, _
		BYVAL user_data AS gpointer) AS gboolean EXPORT

		if DrawfunctionFlag + 1 >2 then
			DrawfunctionFlag = 0
		else
			DrawfunctionFlag += 1
		end if
		
		VAR w = gtk_widget_get_allocated_width(GTK_WIDGET(user_data))
		VAR h = gtk_widget_get_allocated_height(GTK_WIDGET(user_data))
		gtk_widget_queue_draw_area (GTK_WIDGET(user_data), 0, 0, w, h)		

		Return TRUE
End Function

surface可以通过pixbuf产生,cairo-context可以由surface产生,可以操作cr在surface上绘图。如果释放掉surface产生的cr, 将surface作为界面送来cr的源surface,数据的图就渲染到界面上去了,类似内存考贝后叠加成新图片。goocanvas是基于cairo的,但用它绘图方式上有些不同,需要另外的方法处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417285.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

178文章复现:基于matlab的微震图像去噪

文章复现:基于matlab的微震图像去噪,利用同步压缩连续小波变换进行自动微震去噪和起始检测,SS-CWT 可对时间和频率变化的噪声进行自适应过滤,可以去除小幅值信号中的大部分噪声,检测地震事件并估算地震发生时间。程序已…

浏览器卡顿解决办法 —— DNS设置

1.Windows - 设置 2.网络和Internet 3.以太网 - 更改适配器选项 4.点击你现在用的网络 (WLAN或以太网),右键属性 5.双击IPv4协议,DNS地址首选114.114.114.114 南京信风网络科技有限公司,成立于2000年,是一家位于中国南京的高…

SpringBoot 自定义注解实现操作日志记录

文章目录 前言正文一、项目结构介绍二、核心类2.1 核心注解2.1.1 CLog 日志注解2.1.2 ProcessorBean 处理器bean 2.2 切面类2.3 自定义线程池2.4 工具类2.4.1 管理者工具类 2.5 测试2.5.1 订单创建处理器2.5.2 订单管理者2.5.3 订单控制器2.5.4 测试报文2.5.5 测试结果 附录1、…

数据结构·栈和队列

1. 栈 1.1 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一段称为栈顶,另一端称为栈底。 栈中的数据元素遵守 后进先出 LIFO(Last In First Out)的原则,后进来的数…

[linux]进程信号(信号的概念,信号的产生方式,信号的相关接口、指令,函数,信号怎么保存(原理),信号怎么处理)

目录 一、信号的概念 二、信号的产生方式 通过键盘发送信号 通过系统调用,指令 异常 软件条件 三、信号怎么保存(原理) 信号其他相关常见概念 在内核中表示 sigset_t 四、信号的相关接口、指令,函数 signal sigpr…

数据结构--树的遍历

数据结构--树的遍历 1. 前序中序后序遍历2. 前序中序后序遍历代码 1. 前序中序后序遍历 2. 前序中序后序遍历代码 /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */// 前序遍历顺序&#xff1…

SQL函数学习记录

聚合函数 函数是编程语言的基础之一,在对数字的运算中,我们用的最多的就是聚合函数,本篇接下来就详细阐述下SQL中聚合函数的运用。 什么是聚合函数(aggregate function)? 聚合函数指的是对一组值执行计算…

MYSQL05高级_查看修改存储引擎、InnoDB和MyISAM对比、其他存储引擎介绍

文章目录 ①. 查看、修改存储引擎②. InnoDB和MyISAM对比③. Archive引擎 - 归档④. Blackhole引擎丢数据⑤. CSV - 引擎⑥. Memory引擎 - 内存表⑦. Federated引擎 - 访问远程表⑧. Merge引擎 - 管理多个MyISAM⑨. NDB引擎 - 集群专用 ①. 查看、修改存储引擎 ①. 查看mysql提…

C++ 之LeetCode刷题记录(三十六)

😄😊😆😃😄😊😆😃 开始cpp刷题之旅。 目标:执行用时击败90%以上使用 C 的用户。 16. 最接近的三数之和 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你…

备战蓝桥杯Day20 - 堆排序的实现

一、每日一题 蓝桥杯真题之互质数的个数 我的解法: 两个数互质,说明两个数的最大公约数是1,定义了一个函数判断两个数的最大公约数,再在循环中判断,并实现计数。可以实现运行,缺点是时间复杂度很高&#…

【Leetcode每日一题】二分查找 - 寻找旋转排序数组中的最小值(难度⭐⭐)(22)

1. 题目解析 Leetcode链接:153. 寻找旋转排序数组中的最小值 这个题目乍一看很长很复杂,又是旋转数组又是最小值的 但是仔细想想,结合题目给的示例,不难看出可以用二分的方法来解决 核心在于找到给定数组里面的最小值 2. 算法原…

预训练大模型LLM的PEFT之—— Prefix Tuning

简介 Prefix Tuning是2021.01提出来的,在它之前,我们使用prompt主要是人工设计模板或者自动化搜索模板,也就是prompt范式的第一阶段,就是在输入上加上prompt文本,再对输出进行映射。这种离散模板对模型的鲁棒性很差。…

如何在Window系统部署BUG管理软件并结合内网穿透实现远程管理本地BUG

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…

MYSQL学习笔记:索引

MYSQL学习笔记:索引 文章目录 MYSQL学习笔记:索引索引的分类索引的创建删除索引优化B树索引B树InnoDB主键和二级索引树聚集索引与非聚集索引哈希索引INNODB的自适应哈希索引索引和慢查询 用索引也是要涉及磁盘I/O的操作的索引也是一种数据结构&#xff0…

c语言day4 运算符 表达式 三大控制结构

1: 2: 输入一个年月日 计算这是这一年的第几天 17 int year,month,day;18 printf("请输入年份 月份 日期");19 scanf("%d %d %d",&year,&month,&day);20 int feb28;21 if(year%40&&year%1…

哈工大中文mistral介绍(Chinese-Mixtral-8x7B)

Chinese-Mixtral-8x7B基于Mistral发布的模型Mixtral-8x7B进行了中文扩词表增量预训练。扩充后的词表显著提高了模型对中文的编解码效率,并通过大规模开源语料对扩词表模型进行增量预训练,使模型具备了强大的中文生成和理解能力。 开源地址见https://gith…

前端-DOM树

dom树描述网页元素关系的一个专有名词,如html内包含了head、body,而head内包含meta、title、script等,body内包含div等元素;网页所有内容都在document里面,网页内容以树状形式排列,所以称之为dom树 dom树内…

centos服务配置springboot服务开机启动

在做后端服务运维时,经常遇到服务器重启时,需要移动一堆后端服务。服务器故障自动重启时,通常无人通知。把springboot服务的jar包配置开机启动太有必要了,虽然不是很复杂,这里记录一下太有必要了。 创建jar包启动和停…

看完这篇,终于理解如何制作产品使用说明书啦!

制作产品说明书是一项重要的任务,它不仅提供了产品的详细信息,还可以帮助用户正确地使用和维护产品,确保产品说明书的质量和可使用性。在制作产品说明书时,掌握注意事项,可以帮助你更加高效地制作产品说明书。以下是Lo…

lv20 QT主窗口

熟悉创建主窗口项目 1 QAction 2 主窗口 菜单栏:fileMenu menuBar()->addMenu(tr("&File")); 工具栏:fileToolBar addToolBar(tr("File")); 浮动窗:QDockWidget *dockWidget new QDockWidget(tr("Dock W…