使用HeaderBar Python和Gtk3在透明窗口上绘制

使用HeaderBar Python和Gtk3在透明窗口上绘制,python,gtk,pygtk,Python,Gtk,Pygtk,我对下面的代码有点小问题。它创建了一个GtkWindow,使其可绘制,这样我就可以使用cairo on draw事件在其上绘制。然后我添加了一个GtkHeaderBar和一个简单的按钮小部件 from gi.repository import Gtk import cairo def draw_callback(widget,cr): if widget.transparency: cr.set_source_rgba(0,0,0,0.5) else: cr.set_s

我对下面的代码有点小问题。它创建了一个GtkWindow,使其可绘制,这样我就可以使用cairo on draw事件在其上绘制。然后我添加了一个GtkHeaderBar和一个简单的按钮小部件

from gi.repository import Gtk
import cairo

def draw_callback(widget,cr):
  if widget.transparency:
    cr.set_source_rgba(0,0,0,0.5)
  else:
    cr.set_source_rgb(0,0,0)   

  cr.set_operator(cairo.OPERATOR_SOURCE)
  cr.paint()
  cr.set_operator(cairo.OPERATOR_OVER)

win= Gtk.Window()
win.connect('delete-event', Gtk.main_quit)
win.set_app_paintable(True)
screen = win.get_screen()
visual = screen.get_rgba_visual()
win.transparency = False

if visual and screen.is_composited():
  win.set_visual(visual)
  win.transparency = True
else:
  print('System doesn\'t support transparency')
  win.set_visual(screen.get_system_visual)

win.connect('draw', draw_callback)

win.add(Gtk.Button(label='test'))
bar = Gtk.HeaderBar(title='title')
bar.set_has_subtitle(False)
bar.set_show_close_button(True)
win.set_titlebar(bar)
win.show_all()

Gtk.main()
draw_回调将绘制窗口背景,但此背景如下所示:

这就像cairo上下文没有相同大小的窗口一样。绘制的部分和窗口外的部分似乎不响应鼠标事件(例如,我无法从该部分抓取窗口)

如果我不使用头棒,我就不会有这个问题

这适用于ruby 2.2和Gtk3绑定

我的python版本是Python3和最新的Gtk模块

编辑:

问题仍然存在:

def size_allocation_cb(widget, rectangle):
  widget.x = rectangle.x
  widget.y = rectangle.y
  widget.width = rectangle.width
  widget.height = rectangle.height

win.connect('size-allocate', size_allocation_cb)

def draw_callback(widget,cr):
  if widget.transparency:
    cr.set_source_rgba(0,0,0,0.5)
  else:
    cr.set_source_rgb(0,0,0)   

  cr.set_operator(cairo.OPERATOR_SOURCE)
  cr.rectangle(widget.x, widget.y, widget.width, widget.height)
  cr.fill()
  cr.set_operator(cairo.OPERATOR_OVER)

当您有一个标题栏时,窗口完全在客户端绘制,包括阴影(出于某种原因)。您需要调用
cairo_rectangle()
或其他一些函数,最好使用GtkWindow子对象的大小分配(而不是大小请求!),将
cairo_paint()
剪裁到正确的大小。

默认大小不是大小分配。一旦开始向窗口添加更多小部件,您可能会开始注意到奇怪的大小。改为使用大小分配。这是小部件分配给real的矩形。很抱歉,我做了错误的测试,不得不取消验证您的答案。我已将我的主窗口连接到一个大小分配事件,以便获得良好的窗口大小,但问题仍然是一样的。您想要分配窗口的直接子窗口。使用
window.add(xxx)
xxx
是直接子项。@andlabs,您说的是“直接子项”。如果我只想在整个客户区画画怎么办?我必须添加一个绘图区域小部件来填充窗口吗?嗨,你找到解决方案了吗?我很惊讶“窗户装饰”是在窗户区域内绘制的。