输入半径,计算圆的周长、面积、球体体积,并画出这个圆。拖动条、输入框和图像控件的数据保持一致!
fedora下测试通过
代码如下:
#https://github.com/robberphex/gtk-example-calcareafrom gi.repository import gtk, gdk, gdkpixbuffrom pil import image, imagedrawfrom io import bytesiofrom math import pi
class model: ”’ 模型类 存储半径,计算周长、面积、体积 ”’
def __init__(self): self._radius = 0
def setradius(self, radius): self._radius = float(radius)
def getradius(self): return self._radius
def getperimeter(self): return pi * self._radius * 2
def getarea(self): return self._radius ** 2 * pi
def getvolume(self): return 4 * pi * self._radius ** 3 / 3
class controller: ”’ 控制器类 控制视图和模型的更新 ”’
def __init__(self, model): self.model = model self._observers = []
def addobserver(self, observer): self._observers.append(observer)
def setradius(self, radius): model.setradius(radius) self.notify()
def notify(self): for observer in self._observers: observer.update()
class textview: ”’ 文字视图类 处理文本输入框的视图 ”’
def __init__(self, model, rentry, pentry, aentry, ventry): ”’ :type model model ”’ self.model = model self.rentry = rentry self.pentry = pentry self.aentry = aentry self.ventry = ventry
def update(self): self.rentry.set_text(‘%2.2f’ % self.model.getradius()) self.pentry.set_text(‘%2.2f’ % self.model.getperimeter()) self.aentry.set_text(‘%2.2f’ % self.model.getarea()) self.ventry.set_text(‘%2.2f’ % self.model.getvolume())
class scaleview: ”’ 拖动条视图 处理拖动条的视图 ”’
def __init__(self, model, scale): ”’ :type model model ”’ self.model = model self.scale = scale
def update(self): self.scale.set_value(self.model.getradius())
class imageview: ”’ 图像视图 处理图像的视图 ”’
@classmethod def imgtopixbuf(cls, img): ”’ :type img image ”’ buff = bytesio() img.save(buff, ‘ppm’) contents = buff.getvalue() buff.close()
loader = gdkpixbuf.pixbufloader.new_with_type(‘pnm’) loader.write(contents) pixbuf = loader.get_pixbuf() loader.close() return pixbuf
@classmethod def ellipse(cls, radius): ”’ :type radius int ”’ image = image.new(“rgba”, (300, 300), “white”) draw = imagedraw.draw(image) minor = 150 – radius major = 150 + radius draw.ellipse((minor, minor, major, major), outline=’red’) pixbuf = imageview.imgtopixbuf(image) return pixbuf
def __init__(self, model, image): self.model = model self.image = image
def update(self): radius = self.model.getradius() pixbuf = imageview.ellipse(radius) self.image.set_from_pixbuf(pixbuf)
class mainwindow(gtk.window): ”’ 主窗口类 负责整体界面的显示 ”’
def textcallback(self, widget, controller): ”’ 文本输入回调 ”’ try: radius = float(widget.get_text()) controller.setradius(radius) except valueerror as e: pass
def scalecallback(self, widget, controller): ”’ 拖动条回调 ”’ radius = widget.get_value() controller.setradius(radius)
def __init__(self): gtk.window.__init__(self, title=”title”)
self.set_default_size(600, 400) self.set_position(gtk.windowposition.center)
hbox = gtk.hbox(spacing=5) self.add(hbox)
vbox = gtk.vbox(spacing=5) hbox.pack_start(vbox, true, true, 2)
table = gtk.table.new(4, 2, false) vbox.pack_start(table, true, true, 2)
label = gtk.label(‘半径:’) table.attach_defaults(label, 0, 1, 0, 1) label = gtk.label(‘周长:’) table.attach_defaults(label, 0, 1, 1, 2) label = gtk.label(‘面积:’) table.attach_defaults(label, 0, 1, 2, 3) label = gtk.label(‘体积:’) table.attach_defaults(label, 0, 1, 3, 4)
self.radiusentry = gtk.entry.new() self.radiusentry.connect(‘changed’, self.textcallback, controller) table.attach_defaults(self.radiusentry, 1, 2, 0, 1) self.perimeterentry = gtk.entry.new() self.perimeterentry.set_sensitive(false) self.perimeterentry.set_text(‘周长’) table.attach_defaults(self.perimeterentry, 1, 2, 1, 2) self.areaentry = gtk.entry.new() self.areaentry.set_sensitive(false) self.areaentry.set_text(‘面积’) table.attach_defaults(self.areaentry, 1, 2, 2, 3) self.volumeentry = gtk.entry.new() self.volumeentry.set_sensitive(false) self.volumeentry.set_text(‘体积’) table.attach_defaults(self.volumeentry, 1, 2, 3, 4)
self.scale = gtk.hscale.new_with_range(0, 100, 1) self.scale.connect(‘value-changed’, self.scalecallback, controller) vbox.pack_start(self.scale, false, false, 2)
pixbuf = gdkpixbuf.pixbuf.new(gdkpixbuf.colorspace.rgb, true, 8, 300, 300) pixbuf.fill(0xaaaaaaaa) self.image = gtk.image.new_from_pixbuf(pixbuf) hbox.pack_start(self.image, true, true, 2)
self.connect(‘delete-event’, gtk.main_quit)
model = model()controller = controller(model)
if __name__ == ‘__main__’: gdk.threads_init() gdk.threads_enter() win = mainwindow()
iv = imageview(model, win.image) controller.addobserver(iv)
tv = textview(model, win.radiusentry, win.perimeterentry, win.areaentry, win.volumeentry) controller.addobserver(tv)
sv = scaleview(model, win.scale) controller.addobserver(sv)
win.show_all() gtk.main() gdk.threads_leave()