使用PangoCairo在Gnome Shell扩展圆形中居中显示文本失败求助
Gnome Shell扩展:PangoCairo文本居中问题修复
问题分析
你的代码存在几个关键问题导致文本无法正确居中:
- 未恢复旋转变换:绘制进度圆弧时执行了
cr.rotate(-Math.PI/2),但后续没有恢复这个旋转状态就绘制文本,导致文本被旋转90度,且坐标系方向错乱。 - 缺少垂直居中处理:
text_show函数只计算了水平方向的偏移,没有考虑文本的垂直高度,导致文本在垂直方向偏离圆心。 - 像素尺寸与缩放坐标系不兼容:画布已通过
cr.scale(width, height)做了缩放,get_pixel_size()获取的是实际像素值,直接用于缩放后的坐标系计算偏移会导致位置错误,应使用Pango的逻辑尺寸转换为用户坐标系。 - 多余的画笔移动:
text_show末尾的cr.relMoveTo(w / 2, 0)属于无效操作,会干扰画笔位置但不影响文本显示。
修改后的代码
draw_stuff(canvas, cr, width, height) { cr.setSourceRGBA(1,1,1,0.2); cr.save(); cr.setOperator(Cairo.Operator.CLEAR); cr.paint(); cr.restore(); cr.setOperator(Cairo.Operator.OVER); cr.scale(width, height); cr.setLineCap(Cairo.LineCap.BUTT); cr.setLineWidth(0.08); cr.translate(0.5, 0.5); // 绘制外圈 cr.arc(0, 0, 0.4, 0, Math.PI * 2); cr.stroke(); // 绘制进度弧:保存旋转前状态,旋转后绘制,然后恢复 cr.save(); cr.setSourceRGBA(1,1,1,0.8); cr.rotate(-Math.PI/2); cr.arc(0,0, 0.4, 0, this.currentR /100 * 2 * Math.PI); cr.stroke(); cr.restore(); // 恢复旋转,保证后续绘制在原始坐标系 // 绘制内圈 cr.setSourceRGBA(1,1,1,0.9); cr.arc(0,0, 0.25, 0, 2 * Math.PI); cr.fill(); // 绘制文本 cr.moveTo(0, 0); cr.setSourceRGBA(0,0,0,0.9); this.text_show(cr, "WoW"); return true; } update() { this.currentR = 60; // 注意:不要每次update都重复连接draw信号,应该在初始化时连接一次 // this._canvas.connect("draw", this.draw_stuff.bind(this)); this._canvas.invalidate(); } text_show(cr, showtext, font = "DejaVuSerif Bold 16") { let pl = PangoCairo.create_layout(cr); pl.set_text(showtext, -1); pl.set_font_description(Pango.FontDescription.from_string(font)); PangoCairo.update_layout(cr, pl); // 获取布局的逻辑尺寸(Pango单位,1单位=1/1024像素),转换为像素 let [w, h] = pl.get_size(); w /= Pango.SCALE; h /= Pango.SCALE; // 转换为缩放后的坐标系偏移:获取画布缩放因子,计算居中偏移 const scaleX = cr.getMatrix().xx; const scaleY = cr.getMatrix().yy; cr.relMoveTo(-w / (2 * scaleX), -h / (2 * scaleY)); PangoCairo.show_layout(cr, pl); }
关键修改说明
- 恢复旋转状态:绘制进度弧时用
save()和restore()包裹,确保后续文本绘制在未旋转的坐标系中,避免文本方向错误。 - 垂直居中处理:新增文本高度的偏移计算
-h/(2*scaleY),实现垂直方向的居中对齐。 - 适配缩放坐标系:使用
get_size()获取Pango逻辑尺寸,转换为像素后除以画布缩放因子,确保偏移量在缩放后的坐标系中精准对应。 - 移除无效代码:删除
text_show末尾多余的cr.relMoveTo(w / 2, 0),避免干扰画笔位置。 - 优化信号连接:
update函数中不要重复绑定draw信号,应在扩展初始化阶段连接一次,防止多次绑定导致重复绘制。
内容的提问来源于stack exchange,提问作者Raihan Ahamed
相关产品推荐
相关产品推荐

