zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Qt开发之Go篇(七)

2023-09-11 14:17:49 时间

部件提升

Qt中的部件提升非常有用,我们可以在现有的部件基础之上增加一些我们自己个性化的需求。然而由于Go语言的特性,和therecipe/qt的完成度,对于使用部件提升需要一些技巧。

LED-需求描述

假定我们希望实现一个简单的LED显示部件,这个部件有一个属性State,通过设置布尔值可以显示红和绿两种状态。

这个功能有多种方式可以实现,我们可以通过扩展QLabel,并通过调用setPicturesetPixmap来实现,也可以扩展QWidget,并通过重写paintEvent来实现,这里我们使用后者。

手撸的实现方式

让我们先手撸一下,完整代码如下:

package main

import (
    "os"

    "github.com/therecipe/qt/core"
    "github.com/therecipe/qt/gui"
    "github.com/therecipe/qt/widgets"
)

type Led struct {
    *widgets.QWidget
    State bool
}

func NewLed(p widgets.QWidget_ITF) *Led {
    var par *widgets.QWidget
    if p != nil {
        par = p.QWidget_PTR()
    }
    w := &Led{QWidget: widgets.NewQWidget(par, 0)}
    w.State = true
    w.ConnectPaintEvent(w.paintEvent)
    return w
}

func (c *Led) paintEvent(evt *gui.QPaintEvent) {
    var color *gui.QColor
    if c.State == false {
        color = gui.NewQColor3(255, 0, 0, 128)
    } else {
        color = gui.NewQColor3(0, 255, 0, 128)
    }
    painter := gui.NewQPainter2(c)
    painter.SetBrush(gui.NewQBrush3(color, core.Qt__SolidPattern))
    painter.DrawEllipse3(0, 0, c.Width()-1, c.Height()-1)
}

func main() {
    widgets.NewQApplication(len(os.Args), os.Args)
    window := widgets.NewQDialog(nil, 0)
    window.Resize2(400, 200)
    gridLayout := widgets.NewQGridLayout(window)
    led1 := NewLed(window)
    gridLayout.AddWidget(led1)
    led2 := NewLed(window)
    led2.State = false
    gridLayout.AddWidget2(led2, 0, 1, 0)
    window.Show()
    widgets.QApplication_Exec()
}

运行效果如图:

可以看到,和C++或者pyQt代码上有几点不同。首先,由于Go语言没有继承,需要利用结构体的组合来实现类似继承的功能,因此在创建自定义部件类型的时候有一些差异。其次,既然继承不存在了,那么重写自然也不存在,因此,新的paintEvent需要通过ConnectPaintEvent显式地指定。

使用Designer

我们会发现,手撸起来还是挺烦的,尤其是窗口复杂了之后,那么如何用Designer来简化操作呢?(当你看完这节你会发现,就算用了Designer也一样烦……)

首先,用Designer画一个窗口,放两个QWidget,右键点击部件,选择提升为,打开对话框,咱们还叫LED

之后在工程目录下新建一个ui文件夹,将窗口保存到ui文件夹内(假装叫lesson7.ui)。之后运行qtdeploy(会失败)或者qtrcc。此时可以看到在ui目录下多了一个uic_lesson7.go。之后我们需要将ui文件夹改名,否则再次运行qtdeploy时,我们对uic_lesson7.go中做的所有改动都会被覆盖。假设我们更名为myui。我们将之前代码中关于led的部分复制到uic_lesson7.go中。并修改Dialog结构体定义和SetupUI函数中关于LED的部分,将之前的widgets.去掉。修改main.go,如下:

package main

import (
    "os"
    ui "test/myui"

    "github.com/therecipe/qt/widgets"
)

func main() {
    widgets.NewQApplication(len(os.Args), os.Args)
    window := ui.NewDialog(nil)
    window.Show()
    window.Led2.State = false
    widgets.QApplication_Exec()
}

显示效果也是一样的。

通过Designer可以一定程度上简化界面代码编写,但是涉及到提升的这部分,由于therecipe/qt转换ui的过程中,并没有区分自定义部件和原生部件,因此还需要开发者对生成的uic文件进行修改。关于uic生成部分代码见github中的rcc函数,感兴趣的同学也可以自行修改。