You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Cairo在GTK4+LGI的GtkDrawingArea中绘图?

解决GTK4+LGI中GtkDrawingArea绘制无内容及资源管理问题

一、GtkDrawingArea绘制无内容的修复方案

在GTK4的LGI绑定中,set_draw_func的回调参数要求与GTK3不同,核心问题大概率是参数不匹配导致绘制逻辑未执行:

  • 确保从Glade的Gtk.Builder中正确获取GtkDrawingArea对象,比如builder:get_object("你的绘图区ID")
  • set_draw_func的回调必须接收四个参数:widget, cr, width, height,少参数会直接导致回调不触发
  • 绘制前建议调用cr:save()保存上下文状态,绘制完成后调用cr:restore()恢复,避免影响后续绘制

修复后的关键代码片段:

local lgi = require 'lgi'
local Gtk = lgi.require 'Gtk'
local Cairo = lgi.require 'Cairo'

local builder = Gtk.Builder()
builder:add_from_file('main.ui')
local window = builder:get_object('main_window')
local drawing_area = builder:get_object('drawing_area')

-- 正确设置绘制回调
drawing_area:set_draw_func(function(widget, cr, width, height)
    -- 填充背景色
    cr:set_source_rgb(0.05, 0.05, 0.1)
    cr:paint()

    -- 替换为你的地心说太阳系绘制逻辑
    cr:set_source_rgb(1, 0.8, 0)
    cr:arc(width/2, height/2, 40, 0, 2*math.pi)
    cr:fill()
end)

window:show_all()
Gtk.main()

二、Cairo资源管理说明

  • Cairo上下文(cr):由GTK自动管理生命周期,绘制完成后无需手动调用销毁方法,GTK会自动回收资源
  • 手动创建的Cairo.Surface:比如你生成PNG时创建的surface,需要调用surface:finish()释放底层资源;如果是GTK传递的绘制surface,同样由GTK管理,无需手动处理

三、GTK4+LGI完整示例参考

以下是包含2×2布局、输入栏和绘图区的可运行示例:

local lgi = require 'lgi'
local Gtk = lgi.require 'Gtk'
local Cairo = lgi.require 'Cairo'

-- 主窗口
local window = Gtk.Window {
    title = '地心说太阳系演示',
    default_width = 800,
    default_height = 600,
}

-- 顶部输入栏
local input_entry = Gtk.Entry {
    placeholder_text = '输入参数...',
    margin_start = 10,
    margin_end = 10,
    margin_top = 10,
}

-- 2×2布局结构:垂直布局嵌套两个水平布局
local main_vbox = Gtk.Box {
    orientation = Gtk.Orientation.VERTICAL,
    spacing = 15,
    margin = 10,
}

local hbox_row1 = Gtk.Box {
    orientation = Gtk.Orientation.HORIZONTAL,
    spacing = 10,
}
local hbox_row2 = Gtk.Box {
    orientation = Gtk.Orientation.HORIZONTAL,
    spacing = 10,
}

-- 填充布局占位组件
for i=1,2 do
    hbox_row1:append(Gtk.Frame {
        label = '面板1-'..i,
        child = Gtk.Label { label = '内容区域' },
        valign = Gtk.Align.FILL,
        hexpand = true,
    })
    hbox_row2:append(Gtk.Frame {
        label = '面板2-'..i,
        child = Gtk.Label { label = '内容区域' },
        valign = Gtk.Align.FILL,
        hexpand = true,
    })
end

-- 绘图区
local solar_draw_area = Gtk.DrawingArea {
    height_request = 300,
    valign = Gtk.Align.FILL,
    hexpand = true,
}

-- 太阳系绘制逻辑
solar_draw_area:set_draw_func(function(widget, cr, w, h)
    -- 绘制背景
    cr:set_source_rgb(0.02, 0.02, 0.05)
    cr:paint()

    -- 绘制地球(中心)
    cr:set_source_rgb(0.2, 0.4, 0.8)
    cr:arc(w/2, h/2, 30, 0, 2*math.pi)
    cr:fill()

    -- 绘制轨道和行星
    cr:set_source_rgba(0.5, 0.5, 0.5, 0.3)
    cr:set_line_width(2)
    cr:arc(w/2, h/2, 80, 0, 2*math.pi)
    cr:stroke()

    cr:set_source_rgb(1, 0.6, 0.2)
    cr:arc(w/2 + 80, h/2, 15, 0, 2*math.pi)
    cr:fill()
end)

-- 组装布局
main_vbox:append(input_entry)
main_vbox:append(solar_draw_area)
main_vbox:append(hbox_row1)
main_vbox:append(hbox_row2)

window:set_child(main_vbox)
window:connect('destroy', Gtk.main_quit)

window:show()
Gtk.main()

内容的提问来源于stack exchange,提问作者aum hren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:31:02