如何在 GTK 中更新绘制小部件和仅此小部件

问题描述

我有以下小部件层次结构时:

  • 窗口
    • 盒子
      • 绘图区 1
      • 绘图区 2

我在绘图区 1 上调用 queue_draw 然后绘图区 2 也更新(绘制)。出于性能原因,这种行为是否有意?我可以防止这种情况发生并仅更新绘图区域 1。

编辑:添加一个最小的例子:

#!/usr/bin/env python3

import pgi
pgi.require_version('Gtk','3.0')
from pgi.repository import Gtk,Gdk,GdkPixbuf
import cairo

class DrawingArea(Gtk.DrawingArea):
    def __init__(self,id):
        super().__init__()

        self.id = id
        self.vexpand = True
        self.hexpand = True

        self.connect("draw",self.on_draw)

    def on_draw(self,area,context):
        print ("on_draw ",self.id)
        context.set_source_rgb (1,0)
        context.rectangle (0,20,20)
        context.fill ()
        return False

class Window(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_title("Test Draw Radial Gradient")
        self.set_default_size(400,200)
        self.connect("destroy",Gtk.main_quit)

        self.drawingArea1 = DrawingArea (1)
        self.drawingArea2 = DrawingArea (2)

        Box = Gtk.Box ()
        Box .pack_start (self.drawingArea1,True,0)
        Box .pack_start (self.drawingArea2,0)

        button = Gtk.Button.new_with_label("Click Me")
        Box .pack_start (button,0)
        button.connect("clicked",self.on_click_me_clicked)

        self.add(Box)

    def on_click_me_clicked(self,button):
        print ("Button clicked")
        self.drawingArea1.queue_draw()

window = Window()
window.show_all()
Gtk.main()

解决方法

除非我误解了 Gtk 源代码,否则这是某种预期行为。 queue_draw 导致部分窗口失效,并递归更新小部件。很可能(这只是猜测!)它告诉 box 重绘,而 box 重绘它的所有子元素。

无论如何,您的小部件应该随时准备好重新绘制。如果用户调整窗口大小——它会重绘很多次。如果他最小化并恢复窗口 - 又是一次重绘。

首先,确保你的重绘是一个真正的瓶颈。其次,我建议实施某种缓存或代理:与小部件大小相同的开罗表面,当您的数据更改时,您将其绘制在那里,而在重绘时,您只需在小部件的表面上绘制该表面。另一种方法是在另一个线程中准备可绘制对象(如果您使用 python,这是有问题的),但同样:从一些测量开始,看看重绘是否真的很慢。