SlideShare a Scribd company logo
1 of 28
Download to read offline
GTK+ 陷阱与进阶技巧
     王勇
GTK+ 开发中遇到的陷阱
为什么整了半天, 多线程都不能工作?

哥, 你忘了在程序开始添加线程初始化代码了
吧?

在GTK+程序的最开始位置加入下面代码来支持
多线程开发:

 gtk.gdk.threads_init()
为什么我的自绘代码没起作用?

一般我们都通过添加信号 expose-event 回调来
自绘控件, 如果所有绘制代码都正确, 请检查
一下自绘函数是否返回 True, 比如下面代码:

def expose_event_foo(self, widget, event):
  cr = widget.window.cairo_create()
  # draw on cairo.
  return True
为什么自绘时子控件没有显示?

因为当自绘容器时返回 True, 如果不在返回
True 之前把重绘事件传递给子控件, 子控件就
没有机会调用相应的函数进行自绘, 实例代
码:

...
# draw on cairo.
propagate_expose(widget, event)
return True
propagate_expose 函数实现


def propagate_expose (widget, event):
  '''Propagate expose event to children.'''
  if "get_child" in dir(widget) and widget.get_child() !=
None:
      widget.propagate_expose(widget.get_child(), event)
怎么绘制1像素的线条?

因为Cairo默认是开启了反锯齿, 默认用
stroke 只能画出2像素的线, 有以下3种解决方
案:

1 临时关闭反锯齿
2 在目标坐标上添加 0.5 像素的偏移量
3 用 cr.rectange() 和 cr.fill() 替代 cr.stroke()
临时关闭反锯齿的代码
@contextmanager
def cairo_disable_antialias(cr):
  '''Disable cairo antialias temporary.'''
  # Save antialias.
  antialias = cr.get_antialias()
  cr.set_antialias(cairo.ANTIALIAS_NONE)
  try:
      yield
  except Exception, e:
      print 'with an cairo error %s' % e
  else:
      # Restore antialias.
      cr.set_antialias(antialias)

with cairo_disable_antialias(cr):
   ......
GTK+ 进阶技巧
怎么制作不规则的窗口?
不规则窗口的基本原理
GTK+ 不规则窗口代码, 步骤一:

 
 
# 创建形状位图。
x, y, w, h = rect.x, rect.y, rect.width, rect.height
bitmap = gtk.gdk.Pixmap(None, w, h, 1)
cr = bitmap.cairo_create()

 
GTK+ 不规则窗口代码, 步骤二:



# 清空画布。
cr.set_source_rgb(0.0, 0.0, 0.0)
cr.set_operator(cairo.OPERATOR_CLEAR)
cr.paint()
GTK+ 不规则窗口代码, 步骤三:



# 绘制窗口形状。
cr.set_source_rgb(1.0, 1.0, 1.0)
cr.set_operator(cairo.OPERATOR_OVER)
cr.arc(x + w / 2, y + h / 2, w / 2, 0, 2 * pi)
cr.fill()
GTK+ 不规则窗口代码, 步骤四:




# 窗口根据绘制图形裁剪窗口形状。
widget.shape_combine_mask(bitmap, 0, 0)
窗口阴影怎么做?
阴影绘制原理图
cr.clip()
怎么制作真透明的应用程序窗口?


1. 重定向窗口的 colormap 为窗口下方的屏幕
colormap。

2. 用透明色绘制整个窗口。

3 在透明的窗口上绘制不透明的控件。
透明窗口关键代码:
window.set_colormap(gtk.gdk.Screen().
get_rgba_colormap())

window.connect_after("expose-event", expose_window)

def expose_window(self, widget, event):
  cr = widget.window.cairo_create()
  rect = widget.allocation

  cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
  cr.set_operator(cairo.OPERATOR_SOURCE)
  cr.paint()

  .......
colormap tips:



因为 mplayer 是直接绘制在窗口上的, 所以
mplayer 的窗口不能用 colormap 来设置窗口透
明。
GTK+ 多线程程序设计要点



本质上GTK+是不能多线程同时访问并绘制设备,
但是我们可以通过多个非图形化线程来分离出耗
时的后台操作, 并发送图形化代码至主线程执
行来有效提高界面的响应速度和交互体验。
GTK+ 多线程原理图



               耗时
用户操作           的后
的主线程
               台计
               算
GTK+ 多线程步骤


1. 添加非图形化线程, 并传入图形回调函数。

2. 运行非图形化后台计算。

3. 当耗时计算完成时, 发送图形回调函数至主
线程执行。
发送图形回调至主线程执行

def post_gui(func):
  '''Post GUI code in main thread.'''
  def wrap(*a, **kw):
       gtk.gdk.threads_enter()
        ret = func(*a, **kw)
        gtk.gdk.threads_leave()
       return ret
  return wrap

@post_gui
def render_func(...):
怎么渐变绘制?


1. 建立线性变化范围

2. 建立线性变换

3. 绘制图形
渐变绘制关键代码

pat = cairo.LinearGradient(x, y, x, y + h)

for (pos, color) in linear_colors:
   add_color_stop_rgba(pat, pos, color)

cr.rectangle(x, y, w, h)
cr.fill()
GTK+ 代码里面充满很多陷阱和技巧, 就像一
匹烈马, 开始的时候让人很抓狂,但是一旦你
熟悉了它的性格, 你就会感觉非常顺手。

More Related Content

Similar to Gtk+陷阱与进阶技巧

KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
Stipc Nsysu
 
Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門
Chui-Wen Chiu
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
Shuo Chen
 
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
HO-HSUN LIN
 
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
NCUDSC
 
手把手教你把Vim改装成一个IDE编程环境(图文)
手把手教你把Vim改装成一个IDE编程环境(图文)手把手教你把Vim改装成一个IDE编程环境(图文)
手把手教你把Vim改装成一个IDE编程环境(图文)
King Hom
 
Google map api接口整理
Google map api接口整理Google map api接口整理
Google map api接口整理
lileinba
 
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
Will Huang
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
yiditushe
 

Similar to Gtk+陷阱与进阶技巧 (20)

利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek
 
用最潮的 Java script 盡情開發 kde qt 程式
用最潮的 Java script 盡情開發 kde qt 程式用最潮的 Java script 盡情開發 kde qt 程式
用最潮的 Java script 盡情開發 kde qt 程式
 
LLVM introduction
LLVM introductionLLVM introduction
LLVM introduction
 
Introduction of Reverse Engineering
Introduction of Reverse EngineeringIntroduction of Reverse Engineering
Introduction of Reverse Engineering
 
全新的Qt5
全新的Qt5全新的Qt5
全新的Qt5
 
Android 智慧型手機程式設計
Android 智慧型手機程式設計Android 智慧型手機程式設計
Android 智慧型手機程式設計
 
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
KSDG_007_Web 編程另闢蹊徑-GWT,Dart,TypeScript介紹與比較
 
Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
 
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
Microsoft CNTK, Cognitive Toolkit 微軟深度學習工具
 
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
 
twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹
 
论 Python 与设计模式。
论 Python 与设计模式。论 Python 与设计模式。
论 Python 与设计模式。
 
手把手教你把Vim改装成一个IDE编程环境(图文)
手把手教你把Vim改装成一个IDE编程环境(图文)手把手教你把Vim改装成一个IDE编程环境(图文)
手把手教你把Vim改装成一个IDE编程环境(图文)
 
Borland C++Builder 入門課程
Borland C++Builder 入門課程Borland C++Builder 入門課程
Borland C++Builder 入門課程
 
Google map api接口整理
Google map api接口整理Google map api接口整理
Google map api接口整理
 
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
 
2021laravelconftwslides12
2021laravelconftwslides122021laravelconftwslides12
2021laravelconftwslides12
 
我用Django做页游
我用Django做页游我用Django做页游
我用Django做页游
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
 

Gtk+陷阱与进阶技巧