Vala GtkTemplate:未找到 UI 资源

Posted

技术标签:

【中文标题】Vala GtkTemplate:未找到 UI 资源【英文标题】:Vala GtkTemplate: UI Resource not found 【发布时间】:2020-04-02 09:10:03 【问题描述】:

我正在尝试使用 GtkTemplate,但它确实无法正常工作。我已经定义了 .ui 文件资源,正确地调用它等等。

这是我的文件:

meson.build:

# project name and programming language
project('myproject', 'vala', 'c', version: '1.0.0')

# add resources to the executeable
gnome = import('gnome')
gresources = gnome.compile_resources(
    meson.project_name() + '.resources',
    'data/gresources.xml',
    c_name: 'resources'
)

executable(
    meson.project_name(),

    'src/OpenFileWindow.vala',
    'src/Main.vala',

    gresources,

    dependencies: [
        dependency('gtk+-3.0'),
        dependency('gio-2.0'),
    ],
    install: true
)

src/OpenFileWindow.vala:

using Gtk;

namespace MyProject 

    [GtkTemplate (ui="/ui/OpenFileWindow.ui")]
    public class OpenFileWindow : Window 
        [GtkChild]
        Button btn_browse;

        public OpenFileWindow() 

        

        [GtkCallback]
        private void btn_browse_clicked(Button btn) 
            stdout.printf("CLICKED");
        
    

ui/OpenFileWindow.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <template class="OpenFileWindow" parent="GtkWindow">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkButton" id="btn_browse">
        <property name="label">gtk-open</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="use_stock">True</property>
        <property name="image_position">top</property>
        <property name="always_show_image">True</property>
        <signal name="clicked" handler="myproject_openfilewindow_btn_browse_clicked" swapped="no"/>
      </object>
    </child>
  </template>
</interface>

数据/gresources.xml:

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/">
    <file preprocess="xml-stripblanks">ui/OpenFileWindow.ui</file>
  </gresource>
</gresources>

当我用介子和忍者构建时,它给出了这个错误:

valac -C --debug --debug --pkg gio-2.0 --pkg gtk+-3.0 --color=always --directory myproject@exe --basedir ../ --gresources=../data/gresources.xml ../src/OpenFileWindow.vala ../src/Main.vala

../src/OpenFileWindow.vala:6.5-6.40: error: UI resource not found: `/ui/OpenFileWindow.ui'. Please make sure to specify the proper GResources xml files with --gresources and alternative search locations with --gresourcesdir.
    public class OpenFileWindow : Window 

什么问题,我实在看不出来……谢谢!

【问题讨论】:

【参考方案1】:

GResource 是一个只读文件系统,用于嵌入到已编译二进制文件中的文件。在 Vala GUI 项目中,这可用于在二进制文件中存储图像、图标等。

GtkBuilder UI 定义文件也可以嵌入,Vala 通过[GtkTemplate][GtkChild][GtkCallback] 属性对此提供了额外的支持。这种支持的一部分包括编译时的类型检查。检查需要获取源文件并计算出 GResource 内存文件系统的文件名,这就是项目失败的地方。任何想要改进这一点的人都应该在 Vala 编译器中修补 codegen/valagtkmodule.vala。但是,目前,要让您的项目正常运行,您需要为资源使用更扁平的文件结构。

首先将data/gresource.xml移动到ui/目录。然后将prefix 更改为/ui。这意味着内存文件系统将使用与您在 Vala 代码中使用的 GtkTemplate 属性匹配的名称。还要从文件名中删除 ui/ 以提供平面目录结构:

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/ui/">
    <file preprocess="xml-stripblanks">OpenFileWindow.ui</file>
  </gresource>
</gresources>

还需要修改meson.build文件中gresources的定义:

gresources = gnome.compile_resources(
    meson.project_name() + '.resources',
    'ui/gresources.xml',
    source_dir: ['ui']
)

这使用source_dir 来保持引用在扁平目录结构中工作。

您现在应该不会再收到错误消息了。看看Geary 作为一个使用大量 GtkBuilder UI 文件的示例项目。该项目的 GResource 文件与其他文件位于同一目录中。

您的项目仍无法编译,因为 Vala 编译器已识别出[GtkCallback] 没有信号。这是一个名称解析问题,您只需将OpenFileWindow.ui 文件中的一行更改为:

<signal name="clicked" handler="myproject_openfilewindow_btn_browse_clicked" swapped="no"/>

<signal name="clicked" handler="btn_browse_clicked" swapped="no"/>

更新

为了让 Vala 编译器类型检查 GtkBuilder UI 定义文件,gresource.xml 只需要在一个共同的祖先目录中。这使得这样的资源目录结构成为可能:

resources/
├── components/
│   └── zoom-bar.ui
├── icons/
│   └── project.svg
├── layouts/
│   └── main-window.ui
├── themes/
│   ├── dark.css
│   └── light.css
└── filelist.gresource.xml

filelist.gresource.xml 文件需要 prefix/,但子目录从源文件复制到内存文件:

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/">
<file preprocess="xml-stripblanks" compressed="true">layouts/main-window.ui</file>
<file preprocess="xml-stripblanks" compressed="true">components/zoom-bar.ui</file>
</gresource>
</gresources>

这可以在 Vala 中通过以下方式访问:

[GtkTemplate (ui="/layouts/main-window.ui")]

meson.buildgnome.compile_resources()source_dir 参数仍然需要设置:

gresources = gnome.compile_resources(
    'project-resources',
    'resources/filelist.gresource.xml',
    source_dir: ['resources']
)

【讨论】:

感谢您提供非常好的信息和解决方案。成功了! @althomas 感谢您的回答。我正面临着与作者相同的问题。我试图按照您的指示进行操作,但似乎无法正确操作。我已经按照上述相同的布局重组了项目文件,但仍然无法正常工作。回购是here 看起来这是 Vala 处理 gresource.xml 文件中的一个错误,该错误已通过以下提交得到纠正。 gitlab.gnome.org/GNOME/vala/-/commit/…

以上是关于Vala GtkTemplate:未找到 UI 资源的主要内容,如果未能解决你的问题,请参考以下文章

错误:未找到:'dart:ui' import 'dart:ui' - Flutter

错误:未找到:'dart:ui' export 'dart:ui' show Offset;

dart:ui:1:错误:未找到:dart:ui。颤振/飞镖:

使用 Vala 进行日志记录

如何监控 vala 中的目录?

如何在 Vala 中使用 Qt GUI?