• 【golang-GUI开发】struct tags系统(一)


    我们已经介绍了qt的signalslot,现在该讲讲它的struct tags系统了。qt拥有多种的struct tags,我们会去一一了解它们。

    什么是struct tags?

    struct tag又叫做结构体标签,顾名思义,它就是用来给结构体字段做标记的。比如我们熟悉的JSON就使用了tags:

    type User struct {
        UserId   int    `json:"user_id" bson:"user_id"`
        UserName string `json:"user_name" bson:"user_name"`
    }
    

    tags由反引号包裹,name在:之前,value在:之后由双引号包裹。
    有了这些tags,我们的代码就可以很轻松的使用reflect来取得tags的name和name对应的值:

    u := &User{UserId: 1, UserName: "tony"}
    t := reflect.TypeOf(u)
    field := t.Elem().Field(0)
    fmt.Println(field.Tag.Get("json"))    // "user_id"
    fmt.Println(field.Tag.Get("bson"))    // "user_id"
    

    我们的qt正是依赖这一特性实现了Qt的moc系统,使用不同的tags除了可以实现signal和slot之外还能实现moc的多种功能,甚至是qt自己的一些扩展。

    “->” 和 “<-”

    在signal里我们已经介绍了auto,它具有很多的局限性,项目作者也表示auto应该尽量单独使用,不应该使用auto(...)的形式。而为了更方便的连接signal和slot,我们就需要用到-><-了。

    先看个示例,这次我们从官方的例子里节选一段:

    type Chart struct {
    	core.QObject
    	*charts.QChart
    
    	_ func() `constructor:"init"`
    
    	_ func() `slot:"handleTimeout,<-(this.m_timer.timeout)"`
    }
    

    对于槽handleTimeout,我们使用了<-,它和下面这句等价:

    this.m_timer.ConnectTimeout(this.handleTimeout)
    

    意思是将this.m_timer的Timeout信号和this.handleTimeout函数connect,当触发了this.m_timer的Timeout信号时这个函数也会被调用。
    你也可以不指定信号名称,默认会和signal tag指定的信号名同名的函数进行connect:

    _ func() `slot:"handleTimeout,<-(this.m_timer)"`
    

    _ func() `slot:"handleTimeout,<-(this.m_timer.handleTimeout)"`
    

    等价。

    我们再来看一下->的使用:

    import "controller"
    
    type dialogTemplate struct {
    	core.QObject
    
    	_ func() `constructor:"init"`
    
    	_ func(cident string) `signal:"show,<-(controller.Controller)"`
    	_ func(bool)          `signal:"blur,->(controller.Controller)"`
    }
    

    可以看到,我们对信号Blur使用了->,这个表达的含义与<-相反,它是将signal tag声明的信号或是slot tag声明的槽与->之后的函数进行connect,当你触发这个信号或是调用这个槽时,括号内的函数也会被调用,等价于:

    this.ConnectBlur(controller.Controller.blur)
    

    或是(如上面所说,可以省略函数名)

    this.ConnectBlur(controller.Controller)
    

    “->”和“<-”的一些使用规则

    上一段里我们已经提到可以在这两个tags里省略连接和被连接对象的函数名,这里还有几个规则:

    1. 括号里指定的可以是全局对象,包括导入的包里的可见对象,例如上个例子里的controller.Controller
    2. this代指当前对象的实例(可以理解为c++的this,python的self占位符,或者golang的receiver)。
    3. 括号里的内容还可以是this.StructField,也就是对象里的字段
    4. 对于想连接继承的QObject及其派生类或是其他类的signal/slot,目前只能使用this.BaseClass.method的形式(与auto类似),这一点作者表示会在以后改进。

    “->”和“<-”以及“auto”

    这三者都需要和signal/slot tag配合使用,他们都会自动connect信号和槽,但是它们也有许多不同。

    • 首先我们日常使用应该尽量使用singal:"signalName,auto"而不是auto(...)-><-,如果只是为了少写Connect*,那么不应使用后三者,因为除非你有大量的Connect*需要编写,否则容易影响代码阅读,特别是对连接对象是当前类实例的成员函数时。
    • -><-用于不同的对象之间进行交互,比起分散的Connect*调用,在struct tags里声明逻辑关系更易于维护。
    • -><-用于连接已有的信号和槽,如果想复用基类或者成员变量的signal和slot,你就需要-><-替代auto
    • 和QML交互时,也应该使用-><-连接来自QML的signals。

    客观上这三者都能极大的简化我们对signal/slot的实现和使用,所以根据不同的场景需求,我们需要选用合适的tags来简化我们的开发。

    下一篇文章我们将了解constructor这个tag,qt中的构造函数。
    如果对本篇有什么疑问或者建议,欢迎在评论中提出。
    祝玩得愉快!

  • 相关阅读:
    Leetcode--First Missing Positive
    Leetcode--LRU Cache
    java--遍历自定义数组
    爬网页?--Chrome帮你计算XPath
    log4j2配置
    winedt设置自动显示行号[latex]
    墓地雕塑-LA3708
    ctex moderncv版本更新--用latex写一个漂亮的简历
    用Jekyll在github上写博客——《搭建一个免费的,无限流量的Blog》的注脚
    用gameMaker做个小游戏
  • 原文地址:https://www.cnblogs.com/apocelipes/p/9392628.html
Copyright © 2020-2023  润新知