手机版
你好,游客 登录 注册 搜索
背景:
阅读新闻

使用Python中的tkinter模块画树

[日期:2020-04-13] 来源:Linux公社  作者:醉落红尘 [字体: ]

Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。自从20世纪90年代初Python语言诞生至今,它逐渐被广泛应用于处理系统管理任务和Web编程。Python已经成为最受欢迎的程序设计语言之一。

tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口,Tk和Tkinter可以在大多数的Unix平台下使用,同样可以应用在Windows和Mac系统里,Tk8.0的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。

由于Tkinter是内置到Python的安装包中,只要安装好Python之后就能import Tkinter库、而且IDLE也是用Tkinter编写而成,对于简单的图形界面Tkinter还是能应付自如。

下面我们来看看如何使用Python中的tkinter模块画一棵漂亮的树。

代码可以到Linux公社资源站下载:

------------------------------------------分割线------------------------------------------

免费下载地址在 http://linux.linuxidc.com/

用户名与密码都是www.linuxidc.com

具体下载目录在 /2020年资料/4月/13日/使用Python中的tkinter模块画树/

下载方法见 http://www.linuxidc.com/Linux/2013-07/87684.htm

------------------------------------------分割线------------------------------------------

效果图如下:

使用Python中的tkinter模块画树

代码:

# -*- coding: utf-8 -*-

import Tkinter
import sys, random, math

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return "<Point>: (%f, %f)" % (self.x, self.y)

class Branch(object):
    def __init__(self, bottom, top, branches, level = 0):
        self.bottom = bottom
        self.top = top
        self.level = level
        self.branches = branches
        self.children = []

    def __str__(self):
        s = "Top: %s, Bottom: %s, Children Count: %d" % \
            (self.top, self.bottom, len(self.children))
        return s

    def nextGen(self, n = -1, rnd = 1):
        if n <= 0: n = self.branches
        if rnd == 1:
            n = random.randint(n / 2, n * 2)
            if n <= 0: n = 1
        dx = self.top.x - self.bottom.x
        dy = self.top.y - self.bottom.y
        r = 0.20 + random.random() * 0.2
        if self.top.x == self.bottom.x:
            # 如果是一条竖线
            x = self.top.x
            y = dy * r + self.bottom.y
        elif self.top.y == self.bottom.y:
            # 如果是一条横线
            x = dx * r + self.bottom.x
            y = self.top.y
        else:
            x = dx * r
            y = x * dy / dx
            x += self.bottom.x
            y += self.bottom.y
        oldTop = self.top
        self.top = Point(x, y)
        a = math.pi / (2 * n)
        for i in range(n):
            a2 = -a * (n - 1) / 2 + a * i - math.pi
            a2 *= 0.9 + random.random() * 0.2
            self.children.append(self.mkNewBranch(self.top, oldTop, a2))

    def mkNewBranch(self, bottom, top, a):
        dx1 = top.x - bottom.x
        dy1 = top.y - bottom.y
        r = 0.9 + random.random() * 0.2
        c = math.sqrt(dx1 ** 2 + dy1 ** 2) * r
        if dx1 == 0:
            a2 = math.pi / 2
        else:
            a2 = math.atan(dy1 / dx1)
            if (a2 < 0 and bottom.y > top.y) \
                or (a2 > 0 and bottom.y < top.y) \
                :
                a2 += math.pi
        b = a2 - a
        dx2 = c * math.cos(b)
        dy2 = c * math.sin(b)
        newTop = Point(dx2 + bottom.x, dy2 + bottom.y)
        return Branch(bottom, newTop, self.branches, self.level + 1)

class Tree(object):
    def __init__(self, root, canvas, bottom, top, branches = 3, depth = 3):
        self.root = root
        self.canvas = canvas
        self.bottom = bottom
        self.top = top
        self.branches = branches
        self.depth = depth
        self.new()

    def gen(self, n = 1):
        for i in range(n):
            self.getLeaves()
            for node in self.leaves:
                node.nextGen()
        self.show()

    def new(self):
        self.leavesCount = 0
        self.branch = Branch(self.bottom, self.top, self.branches)
        self.gen(self.depth)
        print "leaves count: %d" % self.leavesCount

    def chgDepth(self, d):
        self.depth += d
        if self.depth < 0: self.depth = 0
        if self.depth > 10: self.depth = 10
        self.new()

    def chgBranch(self, d):
        self.branches += d
        if self.branches < 1: self.branches = 1
        if self.branches > 10: self.branches = 10
        self.new()

    def getLeaves(self):
        self.leaves = []
        self.map(self.findLeaf)

    def findLeaf(self, node):
        if len(node.children) == 0:
            self.leaves.append(node)

    def show(self):
        for i in self.canvas.find_all():
            self.canvas.delete(i)
        self.map(self.drawNode)
        self.canvas.tag_raise("leaf")

    def exit(self, evt):
        sys.exit(0)

    def map(self, func = lambda node: node):
        # 遍历树
        children = [self.branch]
        while len(children) != 0:
            newChildren = []
            for node in children:
                func(node)
                newChildren.extend(node.children)
            children = newChildren

    def drawNode(self, node):
        self.line2(
#        self.canvas.create_line(
                node.bottom.x,
                node.bottom.y,
                node.top.x,
                node.top.y,
                fill = "#100",
                width = 1.5 ** (self.depth - node.level),
                tags = "branch level_%d" % node.level,
            )

        if len(node.children) == 0:
            # 画叶子
            self.leavesCount += 1
            self.canvas.create_oval(
                    node.top.x - 3,
                    node.top.y - 3,
                    node.top.x + 3,
                    node.top.y + 3,
                    fill = "#090",
                    tag = "leaf",
                )

        self.canvas.update()

    def line2(self, x0, y0, x1, y1, width = 1, fill = "#000", minDist = 10, tags = ""):
        dots = midDots(x0, y0, x1, y1, minDist)
        dots2 = []
        for i in range(len(dots) - 1):
            dots2.extend([dots[i].x,
                dots[i].y,
                dots[i + 1].x,
                dots[i + 1].y])
        self.canvas.create_line(
                dots2,
                fill = fill,
                width = width,
                smooth = True,
                tags = tags,
            )

def midDots(x0, y0, x1, y1, d):
    dots = []
    dx, dy, r = x1 - x0, y1 - y0, 0
    if dx != 0:
        r = float(dy) / dx
    c = math.sqrt(dx ** 2 + dy ** 2)
    n = int(c / d) + 1
    for i in range(n):
        if dx != 0:
            x = dx * i / n
            y = x * r
        else:
            x = dx
            y = dy * i / n
        if i > 0:
            x += d * (0.5 - random.random()) * 0.25
            y += d * (0.5 - random.random()) * 0.25
        x += x0
        y += y0
        dots.append(Point(x, y))
    dots.append(Point(x1, y1))
    return dots

if __name__ == "__main__":
    root = Tkinter.Tk()
    root.title("Tree")
    gw, gh = 800, 600
    canvas = Tkinter.Canvas(root,
            width = gw,
            height = gh,
        )
    canvas.pack()
    tree = Tree(root, canvas, Point(gw / 2, gh - 20), Point(gw / 2, gh * 0.2), \
        branches = 2, depth = 8)
    root.bind("n", lambda evt: tree.new())
    root.bind("=", lambda evt: tree.chgDepth(1))
    root.bind("+", lambda evt: tree.chgDepth(1))
    root.bind("-", lambda evt: tree.chgDepth(-1))
    root.bind("b", lambda evt: tree.chgBranch(1))
    root.bind("c", lambda evt: tree.chgBranch(-1))
    root.bind("q", tree.exit)
    root.mainloop()

更多Python相关信息见Python 专题页面 https://www.linuxidc.com/topicnews.aspx?tid=17

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址https://www.linuxidc.com/Linux/2020-04/162885.htm

linux
相关资讯       Python tkinter 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款