当前位置: 首页 > 文档资料 > PyGTK 教程 >

15 PyGTK 中的自定义部件

优质
小牛编辑
116浏览
2023-12-01

你是否曾经看到一个程序就在想,一个特别的GUI项目是怎样被创建的呢?或许每个程序员都想知道。然后你就看看你最喜欢的GUI库提供的部件列表。但是你找不到它。工具包一般只提供最常见的部件,例如按钮,文本部件,滑动器等等。没有哪个工具包提供所有可能的部件。

实际上有两种工具包——简朴的工具包和重量级的工具包。FLTK工具包是一种简朴的工具包。它仅仅提供最基本的部件和呈现方法,但是程序员可以自己创建一个更加复杂的部件。wxWidgets是一个重量级的工具包,它有相当多的部件。但是它也不提供更加专业的部件。例如一个速度仪表部件,一个用来检测CD能被烧制的容量的部件(例如:在nero中就有)。工具包也通常不会有图表。

程序员必须通过他们自己来创建一个这样的部件。他们可以通过工具包中提供的绘画工具做到。这里有两种可行的方法。一是,程序员可以更改或者增强现有的部件;或者二是,程序员从零起创建一个部件。

Burning widget

这是一个我们从零起创建的一个部件的例子。这个部件能够在各种媒体烧制程序中见到,就像Nero Burning ROM。

Code:burning.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
# ZetCode PyGTK tutorial 
#
# This example creates a burning
# custom widget
#
# author: Jan Bodnar
# website: zetcode.com 
# last edited: April 2011
import gtk
import cairo
class Burning(gtk.DrawingArea):
    def __init__(self, parent):
      
        self.par = parent
        super(Burning, self).__init__()
        self.num = ( "75", "150", "225", "300", 
            "375", "450", "525", "600", "675" )
        self.set_size_request(-1, 30)
        self.connect("expose-event", self.expose)
    def expose(self, widget, event):
      
        cr = widget.window.cairo_create()
        cr.set_line_width(0.8)
        cr.select_font_face("Courier", 
            cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        cr.set_font_size(11)
        width = self.allocation.width
     
        self.cur_width = self.par.get_cur_value()
        step = round(width / 10.0)
        till = (width / 750.0) * self.cur_width
        full = (width / 750.0) * 700
        if (self.cur_width >= 700):
            
            cr.set_source_rgb(1.0, 1.0, 0.72)
            cr.rectangle(0, 0, full, 30)
            cr.save()
            cr.clip()
            cr.paint()
            cr.restore()
            
            cr.set_source_rgb(1.0, 0.68, 0.68)
            cr.rectangle(full, 0, till-full, 30)
            cr.save()
            cr.clip()
            cr.paint()
            cr.restore()
        else:
            cr.set_source_rgb(1.0, 1.0, 0.72)
            cr.rectangle(0, 0, till, 30)
            cr.save()
            cr.clip()
            cr.paint()
            cr.restore()
       
        cr.set_source_rgb(0.35, 0.31, 0.24)
        
        for i in range(1, len(self.num) + 1):
            cr.move_to(i*step, 0)
            cr.line_to(i*step, 5)
            cr.stroke()
            
            (x, y, width, height, dx, dy) = cr.text_extents(self.num[i-1])
            cr.move_to(i*step-width/2, 15)
            cr.text_path(self.num[i-1])
            cr.stroke()
       
        
class PyApp(gtk.Window): 
    def __init__(self):
        super(PyApp, self).__init__()
        
        self.set_title("Burning")
        self.set_size_request(350, 200)        
        self.set_position(gtk.WIN_POS_CENTER)
        self.connect("destroy", gtk.main_quit)
        self.cur_value = 0
       
        vbox = gtk.VBox(False, 2)
        
        scale = gtk.HScale()
        scale.set_range(0, 750)
        scale.set_digits(0)
        scale.set_size_request(160, 40)
        scale.set_value(self.cur_value)
        scale.connect("value-changed", self.on_changed)
                
        fix = gtk.Fixed()
        fix.put(scale, 50, 50)
        
        vbox.pack_start(fix)
        
        self.burning = Burning(self)
        vbox.pack_start(self.burning, False, False, 0)
        self.add(vbox)
        self.show_all()
        
        
    def on_changed(self, widget):
        self.cur_value = widget.get_value()
        self.burning.queue_draw()
    def get_cur_value(self):
        return self.cur_value
PyApp()
gtk.main()

我们在窗口的底部放置了以DrawingArea区域,准备手动绘制整个部件。所有重要的代码都属于Burning类的expose()方法。这个部件以图像的形式展现了一个媒体总的容量和空余可用的空间。这个部件被一个标尺部件所控制。我们自定义部件的最小值为0,最大值为750。如果我们到达值700,我们就开始用红色绘制它。这个一般在提示超容量烧录了。

self.num = ( "75", "150", "225", "300", "375", "450", "525", "600", "675" )

这些数字会在burning部件上显示。它们指示的是一个媒体的容量。

self.cur_width = self.par.get_cur_value()

这两行是从标尺部件上获取当前的数据。我们从父部件获得了父部件,然后我们获得了当前值。

till = (width / 750.0) * self.cur_width
full = (width / 750.0) * 700

till参数是判定将要绘制的总共大小。这个值来自滑动器部件。它是整个区域的一个比例。fill参数是判定我们从哪里开始用红色来绘制。

cr.set_source_rgb(1.0, 1.0, 0.72)
cr.rectangle(0, 0, till, 30)
cr.save()
cr.clip()
cr.paint()
cr.restore()

这些代码这里在媒体满值之前绘制了一个黄色的矩形。

(x, y, width, height, dx, dy) = cr.text_extents(self.num[i-1])
cr.move_to(i*step-width/2, 15)
cr.text_path(self.num[i-1])
cr.stroke()

这些代码这里在burning部件上绘制数字。我们将正确的计算TextExtents到文本的位置。

def on_changed(self, widget):
    self.cur_value = widget.get_value()
    self.burning.queue_draw()

我们从标尺部件获得值,将其存储在cur_value变量中留待后用。我们重画burning部件。

Figure:Burning Widget

在这章中,我们用PyGTK创建了一个自定义的部件。