首页 > 解决方案 > 使用闪亮的驱动程序将更改发布到窗口

问题描述

我需要显示image.RGBA我正在运行的模拟生成的一系列帧,并且我正在尝试使用闪亮来这样做。在熟悉包的同时,我尝试运行一个简单的示例,与提供的示例非常相似,但我不明白背后的逻辑Window.Publish,以及更改何时显示在屏幕上。

根据and的文档UploadFill

填充 Window 时,在调用 Publish 之前不会有任何可见的效果。

但是,当我w.Publish在上传缓冲区或填充窗口后调用时,我只看到一个黑色窗口。

奇怪的是,如果我在事件循环中使用相同的行上传或填充窗口,则窗口会更新:移动鼠标时我看到背景颜色发生变化,并且在调整窗口大小时绘制了正方形,即使我没有调用w.Publish在事件循环内。

// create a Window
winSize := image.Point{900, 600}
w, err := s.NewWindow(&screen.NewWindowOptions{
    Width:  winSize.X,
    Height: winSize.Y,
    Title:  "Viewer",
})
if err != nil {
    log.Fatalf("s.NewWindow: %+v", err)
}
defer w.Release()

// create a Buffer
size0 := image.Point{30, 30}
b, err := s.NewBuffer(size0)
if err != nil {
    log.Fatalf("s.NewBuffer: %+v", err)
}
defer b.Release()

// fill the buffer with a color
white := color.RGBA{255, 255, 255, 255}
draw.Draw(b.RGBA(), b.RGBA().Bounds(), &image.Uniform{white}, image.Point{0, 0}, draw.Src)

// draw the buffer on the window
w.Upload(image.Point{40, 40}, b, b.Bounds())

// publish the changes
w.Publish()

// at this point I see a black window

var sz size.Event
for {
    e := w.NextEvent()
    switch e := e.(type) {

    default:

    case key.Event:
        if e.Code == key.CodeEscape {
            return
        }

    case mouse.Event:
        // this works, the background changes and the square is drawn
        v := uint8(rand.Intn(255))
        w.Fill(image.Rectangle{image.Point{}, winSize}, color.RGBA{v, v, v, 255}, draw.Src)
        w.Upload(image.Point{30, 30}, b, b.Bounds())

    case size.Event:
        // this works, the background changes and the square is drawn
        sz = e
        w.Fill(sz.Bounds(), color.RGBA{80, 80, 80, 255}, draw.Src)
        w.Upload(image.Point{30, 30}, b, b.Bounds())

    case paint.Event:
        log.Printf("paint.Event: %T %+v", e, e)
    }
}
  1. 为什么调用发布时窗口没有更新?
  2. 为什么即使没有调用发布,窗口也会在循环内更新?
  3. 为什么一个size事件会产生一个paint事件?我留下的那条日志行是在大小事件之后打印的,但不是mouse事件。

如果使用纹理,将缓冲区上传到纹理,然后将纹理复制到窗口,也会发生同样的事情。

我只需要一个具有快速绘图和基本事件处理功能的最小 UI,而且这个包看起来非常易于使用,但如果有其他简单的选项,我可以接受。

编辑

当我在 Ubuntu 20.04 上运行它时,我相信使用的驱动程序是 X11,所以我查看了 Publish的实现,并且有一条评论可以解释为什么调用 publish 不需要实际绘制,但对同步很有用:

func (w *windowImpl) Publish() screen.PublishResult {
    // This sync isn't needed to flush the outgoing X11 requests. Instead, it
    // acts as a form of flow control. Outgoing requests can be quite small on
    // the wire, e.g. draw this texture ID (an integer) to this rectangle (four
    // more integers), but much more expensive on the server (blending a
    // million source and destination pixels). Without this sync, the Go X11
    // client could easily end up sending work at a faster rate than the X11
    // server can serve.
    w.s.xc.Sync()

    return screen.PublishResult{}
}

但我仍然不明白为什么即使使用显式发布调用,在循环外绘图也不起作用。

干杯!

标签: gouser-interface

解决方案


推荐阅读