• Python打造一个词云制作软件


    参数字典

    自从做了热榜的词云之后,就越来越觉得词云的表达力真的很强,所以合计是不是可以为WordCloud做一个界面,来更加直观地操作。

    既然以WordCloud为核心,那么界面的组件自然要和WordCloud的参数意义绑定,每个参数在界面中都对应一个提示组件,比如Lable,和一个输入组件,比如Entry。此外,这些参数都是可设的,那么在对应一个组件的同时,也应该对应一个StringVar。

    简单起见,现在只挑选几个必备的参数,来演示这个逻辑的实现方法

    参数说明适用组件参数
    width词云宽度Spinbox100-2000, 10
    height词云高度Spinbox100-2000, 10
    scale缩放Spinbox0.5-10, 0.1
    输入文本路径对话框
    输出词云路径对话框
    font_path字体文件路径路径对话框

    将这些参数封装成一个字典,内容如下

    wcDct = {
        "词云宽度" : {
            "Ctrl": ttk.Spinbox, 
            "paras" : {"from_":100, "to":2000, "increment":10},
            "default":800,
            "call" : "width"},
        "词云宽度" : {
            "Ctrl": ttk.Spinbox, 
            "paras" : {"from_":100, "to":2000, "increment":10},
            "default":450,
            "call" : "height"},
        "图像缩放" : {
            "Ctrl": ttk.Spinbox, 
            "paras" : {"from_":0.5, "to":10, "increment":0.1},
            "default":1,
            "call" : "scale"},
        "输入路径" : {"Ctrl": DialogButton},
        "输出路径" : {"Ctrl": DialogButton},
        "字体路径" : {"Ctrl": DialogButton, "call" : "font_path"},
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    其中,DialogButton是自定义的一个组件,主要包括一个按钮和一个输入框,点击按钮可以弹出文件对话框。

    布局

    有了这个字典,就可以据此来布局了

    class DrawWords(ttk.Frame):
        def __init__(self, master, **options):
            super().__init__(master, **options)
            self.pack()
            self.words = None
            self.initWidgets()
        
        def initWidgets(self):
            frm = ttk.Frame(self)
            frm.pack(side=tk.LEFT, fill=tk.Y)
            self.initPara(frm)
    
        def setOneSpinBox(self, frm, key):
            ttk.Label(frm, width=8, text=key).pack(side=tk.LEFT)
            v = wcDct[key]      # 组件参数
            n = v["call"]       # 调用名
            self.spins[n] = v["ctrl"](frm, **v["paras"])
            self.spins[n].set(v["default"])
            self.spins[n].pack(side=tk.LEFT)
        
        def setOneDiaButton(self, frmPara, key):
            frm = ttk.Frame(frmPara)
            frm.pack(side=tk.TOP, fill=tk.X)
            ttk.Label(frm, width=8, text=key).pack(side=tk.LEFT)
            v = wcDct[key]
            n = v["call"] if 'call' in v else key
            self.paths[n] = v["ctrl"](frm, **v['paras'])
            self.paths[n].pack(side=tk.LEFT)
            if 'default' in v:
                self.paths[n].set(v['default'])
    
        def initPara(self, frmPara):
            self.spins = {}
            frm = ttk.Frame(frmPara)
            frm.pack(side=tk.TOP, fill=tk.X)
            for key in ["词云宽度", "词云高度"]:
                self.setOneSpinBox(frm, key)
    
            self.paths = {}
            for key in ["输入路径", "输出路径", "字体路径"]:
                self.setOneDiaButton(frmPara, key)
                    
            frm = ttk.Frame(frmPara)
            frm.pack(side=tk.TOP, fill=tk.X)
            ttk.Button(frm, text="输出词云", 
                command=self.genWordCloud).pack(side=tk.LEFT)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在布局过程中,对SpinBox类型的变量和DialogButton型的变量分别做了不同的处理,并且为它们分别设计了全局变量字典self.spins和self.paths,以便于调用。

    布局结果如下

    在这里插入图片描述

    其中,genWordCloud用于词云输出,考虑到分词的准确性,这里仍然采用jieba进行分词,并为分词专门设计一个函数,其最终实现如下。

        def splitWords(self):
            p = self.paths["输入路径"].get()
            with open(p, encoding='utf8') as f:
                text = f.read()
            words = jieba.lcut(text)
            self.words = [w for w in words if len(w)>1] # 取出长度大于1的词
    
        def genWordCloud(self):
            dct = {}
            for key in ['width', 'height', 'font_path']:
                if key in self.spins:
                    dct[key] = int(self.spins[key].get())
                if key in self.paths:
                    dct[key] = self.paths[key].get()        
            cloud = WordCloud(**dct)
            self.splitWords()
            cloud.generate(" ".join(self.words))
            p = self.paths["输出路径"].get()
            if not (p.endswith('.png') or p.endswith('.svg')):
                p = p+".png"
            cloud.to_file(p)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试结果

    最后,按照惯例,做一下测试

    if __name__ == "__main__":
        root = tk.Tk()
        DrawWords(root).pack(side=tk.TOP, fill=tk.BOTH)
        root.mainloop()
    
    • 1
    • 2
    • 3
    • 4

    效果如下

    在这里插入图片描述

  • 相关阅读:
    目录和文件管理
    iOS 17.1 新版发布,修复辐射超标问题
    计算机毕业设计SSM草海帮帮帮【附源码数据库】
    Java进阶知识——反射
    内外通、效益增 | 数商云•瓴犀产品3.0开启全方位精准精细化协同模式
    在 C# CLR 中学习 C++ 之了解 namespace
    视觉SLAM十四讲学习笔记--第七讲视觉里程计学习笔记总结(1)
    java Spring Boot日志输出格式配置方法
    平衡三进制分布式计算
    基于Springboot实现高校社团管理系统
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/132470515