探索记录

170116

Chap1内容Review

新的一周开始新的探索,上周的“回顾”环节做的并不是很到位,还需要“反刍”,先记录在“下一步行动”中。

查看Chap2的卡包

延续着开智给自己的“意外”,以前以为GUI不重要,只是最后的一个“壳”而已,但是现在看起来这个内容并不简单。关于OOP,一般软件工程专业会在学习C之后下个学习C++的学习中花费相当长的时间来说明这到底是什么一个抽象的概念。竟然在Chap2中云淡风轻的登场了......看来又是“一场恶战”,继续努力吧,勇士们。

Python的GUI

在尝试卡包提供的链接前,我尝试了一下Google“python gui”,排名第一的是GUI Programming in Python以及“简版”内容

了解tkinter

从Google和卡包得到的信息是一致的:利用thinker。当然Google的答案还有更多的可能性,比如说放弃GUI,采用web+html5的模式,这是以后可以考虑的事情。

Google"python Tkinter"得到文档25.1. tkinter — Python interface to Tcl/Tk和文档Tkiner

Q:Tcl、Tk、Tkiner分别是什么?

从文档可以知道的信息如下:

  • 这是一个模块的名称,该模块经常用于Python的GUI编程
  • 该模块并不是Python的原生代码,但是已经约定俗成了
  • 有很多的相关文档

翻了一下文档,的确是“浩如烟海”,这一次希望尝试新的方式(尽快动手编程),准备做如下探索:

  • 明确到底哪里才是官方文档
  • youtube找到了一个相关的简单的教程,看一下,做快速入门
  • Google搜索"python tkiner"
  • stack overflow 搜索"python tkiner"

第一个小程序

基于上面的想法,把youtube的Python GUI with Tkinter - 1 - Introduction在project敲了一遍,做了最基本的实现。心里不再慌张,虽然很简单,但是有底了,也大概知道了形式:

  • 类的实例化形成一个又一个的对象(和matplotlib的作图类似)
  • 针对对象进行函数操作
  • 通过mainloop保证程序的一直执行,GUI可以一直存在。

找到Tutorial

看了一些文档,都指向了tkdocstcl。前者不像官方文档,后者主要是tcl和tk的内容相关,和tkinter又是什么关系呢?

在tkdocs中的案例A First (Real) Example尝试了一下可以运行。

开始逐渐了解tk的套路:

  • 实例化对象(这个对象可以看作最基本的图形对象)
  • 对象的元素进行赋值(增加属性)
  • 增加框架(具体是什么还需要进一步了解)
  • 输入值和鼠标操作进行定义(还需要更多了解)
  • root.mainloop()保证图形化对象的执行

对应的问题:

  • 终端运行时,如何终止文件的运行?(窗口可以直接关闭,但是自己还不会停止终端)
  • 对应的对象和函数去哪里找?(继续看这个tutorial然后是官方文档)

自己的小程序

看了那么多,蠢蠢欲动,立刻开始动手写起来,一边写一边理解吧。

  • 第一个小程序:先输出root
    • 即便如此,还是出错,包引入和Tk()函数的大小写问题等等
    • 成功输出
  • 增加title 其他的尝试总是会报错,root对象貌似是最基础的对象,有一点像“背景”,继续看文档。

文档

http://www.tkdocs.com/tutorial/index.html 清晰

170119

前两天生病,今天恢复,从之前未看完的TkDocs开始。虽然这两天没有写作业,但大脑并没有停止思考,看到内容依然很亲切。

Frame

在frame的函数中frame = ttk.Frame(parent)提到了ttk模块,之前也见到过,没有仔细了解。这里的ttk应该是Python的模块,回到官网搜索ttk:找到文档25.2. tkinter.ttk — Tk themed widgets。文档说明了Tk themed widgets。

Ttk comes with 17 widgets, eleven of which already existed in tkinter: Button, Checkbutton, Entry, Frame, Label, LabelFrame, Menubutton, PanedWindow, Radiobutton, Scale and Scrollbar. The other six are new: Combobox, Notebook, Progressbar, Separator, Sizegrip and Treeview. And all them are subclasses of Widget.

对于相同的插件,可以直接覆盖,用下面的代码:

from tkinter import *
from tkinter.ttk import *

在外观上两个模块的内容是有差别的,特别是对样式的控制上,ttk统一进行管理。这是从官方文档的到的信息。

不管这些了,回到Frame上来,先用代码实现,本想在“02_my_first_tkinter”继续写,不过考虑到单个文件处理单个问题的原则,新建文件0201。

label

到label时发现,不显示内容啊,在0201的frame下也是不显示。于是上网搜索,“tkinter label does not appear”,没有直接的找到答案,相关问题代码都有XX.pack(),测试发现的确是这个问题。BOC

entry

测试了entry,出现了输入框,但是如何显示中文,如何有更多效果还不清楚。搜索Google没有合适的答案,突然想到如果复制过去呢?目前看是可以复制过去的。后续操作呢?继续探索

170121

这两天家里人又生病,工作出现紧急事务,今天做不完无法按时交作业了,保持最小行动,先强力完成作业。

题目分析

打开卡包分析作业的基本要求,应该是在frame的基础上,加上一个录入框,一个显示内容的插件,三个按钮。 事件是

  • 录入框输入对应的内容后显示对应的天气情况,输入错误给出错误提示
  • 点击help按钮弹出help的内容提示
  • 点击history按钮弹出history的内容提示
  • 点击quit后弹出之前的历史查询内容,退出程序
  • 加入插件后,各个插件的排列是有顺序的

优化的工作是(有时间再做,没有时间则放到以后)

  • 完成后考虑上一次作业的代码不动,本次作业调用上次作业的代码,实现代码复用
  • 利用其他的GUI包实现该功能。
  • 深入了解OOP
  • 深入了解TKinter,从TKinter的角度理解OOP

问题探索思路

前几次的探索我已经初步可以把需要的widgets展示出来,下面要做的几件事情

  • 让widgets的排列更有序
  • 考虑如何设置页面的大小
  • 如何设置页面的交互
    • 输入框的事件
    • 按钮的事件
    • text部分的展示事件

解决排序问题

直接Google"how to arrange widgets on tkinter"看前三个答案

看完这些代码有一个感觉,这里的tkinter,高手们在用类的方式进行组织,自己目前先实现,后续要优化代码,通过类的方式来实现。

修改代码

准备尝试利用 Layout management in Tkinter,这篇文章的编程习惯非常好,以后需要拿来借鉴。代码的前缀和功能说明很清晰,结构也尽可能的进行封装,调用main函数组织主函数等等。提到的代码修改后形成自己的展示框架。以后慢慢吃透这个展示框架,再做一个计算器的小项目,内化为自己的东西。

新建了0301的文件进行修改。

  • 修改了import的包名,保证不报错
  • 尝试修改内容的大小,后面的两个参数的含义还不是很清晰
  • 修改按钮名称,新增一个按钮

到目前,完成了初步的框架搭建

新建输入框

新建文件0302,复制刚才的内容。

新建了Label和Entry Widgets,但是还没有摸透属性,先简单修改属性配置,能够正常显示和使用。

输入框的几个问题

  • 中文录入的问题
  • 输入框需要在向下一些

调整输入框的位置

直接Google"how to make widget to the bottom of frame in tkinter",看前两个

考虑的方式是通过新建frame,把两个widgets放到原来frame,通过pack调整frame的位置来实现输入框的下移。和最初实现按钮下移是一个道理。修改代码后实现,但是frame的几个属性值尚不明确具体功能。

中文输入

发现有小伙伴有类似的问题,#190,大概看了一下,初步判断是ActiveTcl的版本问题。 Google直接搜索英文效果不好,搜索中文找到解决MAC版 IDLE 不支持中文输入法帖子,里面提到了官网链接,通过There is important information about IDLE, Tkinter, and Tcl/Tk on Mac OS X here.链接到IDLE and tkinter with Tcl/Tk on macOS。这里的说明就比较清楚了。

需要下载的是8.5.18.0。家里网不好,明天到单位继续尝试。

展示结果的Widget

Google搜"which tkinter widget can be used display text content",The Tkinter Text Widget说明了用text的disable状态即可。

简单的试验成功,把text放入frame1,并且设置state为disable。

至此,图形界面的设计完成。明天开始对事件的探索(补齐中文输入法输入内容的部分)

170122

增加事件?

先Google了增加事件Events and Bindings有一些抽象,所以继续Google"tkinter how to add event when click button",期望找到一个实例。How to handle a Button click event给了很好的实例。

立刻实践,新建类的方法,可以正常的print到终端中,下一步是print到屏幕的text中。

在中间做了各种搜索,但是效果不好,于是冷静一下,先把能加的功能加上,回来再做展示。(让大脑放松,换一个思路)

增加quit基本功能

quit功能比较简单,搜索就能找到,但是在quit之前打印history的信息还没有实现,还有退出前弹出选择框也可以考虑,稍后再琢磨吧。

文字打印

文字打印很快就找到了txt.insert()函数,但自己对类不熟悉,在类中定义方法时需要调用类函数中的变量时报错,显示没有这个变量(‘NameError: name 'txt' is not defined’)。如果解决了这个问题,文字输出应该不是问题。

看了Basic Python Tutorial 38 - Using Text and Entry Widgets,把txt改成self.txt,终于不报错了,还不知道为什么:(。但是text还是不显示内容,突然想到之前看文档貌似说过如果用了disable,就不能insert。去掉了disable,果然可以正常打印!!!增加了换行符,可以正常换行了。

但是还是可以在Text中自己添加内容,找一下如何处理这个问题,Google"make tkinter text widget can not type",果然有这个问题Is there a way to make the Tkinter text widget read only?,一个方法是平时设置为disable,需要使用时打开,用完了再关上,试一下,立刻修改代码,问题解决。

获取数据

Google“tkinter how to read from entry widget after press enter”想通过回车控制数据的读入,但是效果不好。退一步先完成通过按钮的数据录入。 在页面增加了搜索按钮,写入了搜索的函数,和前面一样,修改了entry1为self.entry1,在定义函数时增加了变量self的带入。 已经可以在点击按钮时,在终端输出对应的内容。

后续可能做的优化:

  • 输入的内容有误时直接返回有误信息在Entry Widget,然后重新输入。或者把内容输出在Text Widget中。
  • 增加回车后的内容录入。

准备带入之前的程序

到目前为止,最基本的知识点都已经得到了测试,程序的基本框架也有了,下面要把之前的程序融入进来,形成自己的程序了。

新建v01版本的内容,结合之前的函数内容进行整合。为了完成作业,先把上一次的代码复制粘贴过来,优化的时候再考虑如何做到代码复用。

help函数调整

Help的函数拷贝过来进行加工,先在终端输出,然后在txt widget输出,完成~

log文件的问题

review的时候发现一个问题,如果log文件被人为删除怎么办?更合适的做法应该是在该目录下检查是否有log文件,如果有延续使用,如果没有则新建该文件。 现在先自己新建log文件,有时间时加入检查程序。 此次优化了log的格式,没必要用log.txt,直接用log做二进制文件名即可

字典型数据的生成

之前一直在折腾界面,实际上数据还是需要进行字典化的处理的,所以原来的函数还需要在main中执行。直接拷贝后调整格式,加入print函数确认执行效果,全部OK。

输入数据的判断

把大量的Chap1代码拷贝进来之后,开始尝试运行。 第一个报错“NameError: name 'd' is not defined”,初步判断时对字典数据在何时定义导致的问题。我在dict_maker定义了字典d,但是后面进入类找不到这个字典,字典不是全局的。google"python how to call global dictionary",没有合适的答案。查看代码后,尝试把d = {}拿出函数试一下,暂时是OK的,还没有发现问题。

之前的利用字符显示内容的代码保留了,所以在输入框输入h或者quit会产生对应的效果,脑洞大开,快捷键是不是就是这么做出来的呢?算是一个小彩蛋吧。

继续进行测试,之前中文输入法录入的问题没有很好的解决,所以先粘贴中文进去测试,能够正常在终端输出,现在要把终端的结果改到text上输出。 北京 上海 南宁 淮安 日本

新增了一个类方法,用于在屏幕上输出天气状况的内容,没有报错,但是终端OK,屏幕没有。后来想到是传参数的,问题,第一个参数默认为self,但是input并没有传进来,另外d字典是全局的,所以传入input参数即可,测试OK。这里有一个小问题自己需要注意,形参和实参是一样的,后面再来调整吧。

新的问题是换行不生效,如何调整,还有输入错误时的提示内容。

输入错误的问题处理完毕,新增了一个函数用来输出报错信息。不过也多了一个优化点,因为有三个输出函数的内容很一致,是否可以优化为一个函数,稍后再考虑。

现在无论是正确的数据还是错误的数据都能够屏幕打印了,但是换行没有解决。另外检查代码时在考虑while true是否可以优化。

换行的问题是反斜线的问题,处理完即可。

历史信息的录入和输出

之前已经新建了log,在判断后录入信息,现在需要读取内容,粘贴了上一次的file_read函数,进行调试。由于读取内容后要在text上显示,所以取消函数,直接写在类方法historyButton_click中。

退出前的打印

直接调用historyButton_click函数即可,可是用户并不能看到具体内容,有什么意义呢?呃,没有想明白。

解决中文输入法的问题

目前尚未解决,都是通过粘贴的方式完成程序。下面集中处理该问题。

感受

先解决问题,再研究知识

看文档花了太多时间,应该更结合实际的作业来了解知识点。保持最小的知识点完成作业之后再从解决问题的角度继续探索知识点。不要被自己过去的经验束缚。 知识点够用就行,继续向下探索,而不是一直停留在知识点本身,浪费了大量的解决问题的时间。 如果这一次一上来看了文档的大概就立刻着手解决问题可能会快很多,并且通过回顾的时候仔细阅读文档习得更多知识点,优化自己的程序。 我之所以会选择先系统的看文档,是因为之前Data103课后review的经验,反思发现忘记了一个事实,那是在review,不是在解题的初期。谨记。

再次反思自己做的不好的地方,需要澄清,对于知识点的探索有必要,建议找准作业需要的知识点,单独新建文件后把知识点相关的配置先试验,并且自己单独新建文件,更换场景尝试,成功即表示OK。其他内容继续延续上面的观点。

看代码的作用

自己之前一直有一个小小的误区,觉得看别人的代码并不是一个很好的学习习惯。大妈上次的回答还是很疑惑,为什么要主动的看别人的代码来学习?我以往都是被动的看代码。 这一次看到了Layout management in Tkinter的代码有一点感觉,这个代码内容写的很美,自然的想吸取里面的精华,TKinter之外,有很多的内容可以学习和借鉴,要不断的内化。 看别人的代码也是一个主动学习的过程,吃透高手的内隐知识还真得靠着看代码来实现了。好像还没有看到一本书(也许是自己太浅薄)将如何形成良好的Coding习惯,以及哪些代码是好的Coding习惯。这个太琐碎了,如果有小伙伴知道请告诉我。 所以另一个点是时刻保持好奇心,保持敏感的觉察度,观察代码和思考代码,特别是拿到了高手的代码,一行都不要放过,把所有的腿毛全部豪下来,一根都不剩。

Google、优质代码、线索

我们应该如何实践码代码这件事情? 从Google开始,这一次作业特别明显。Data103的初期我还会百度代码,现在越发觉得那个内容是有问题的,百度出来的结果大部分是博客的内容,非常的碎片化,而且信息量极其有限。但是Google之后,充满了优质的教程、问题解决方案,很少看到个人的博客,如果有,也是高质量的整体内容,无论是针对问题的解决还是一个完整的信息组块说明。大概率事件还会得到信息源头的链接。 在优质的代码资源里,才有可能实现上面说到的看代码。而看代码又是怎么一回事?是一种索引,我以前的学习方法很依赖:教。现在看来,除了十几年的学习生涯被灌输习惯之外,一只没有找到优质的搜索引擎也是很大的问题。大学阶段大量的时间,现在回忆起来搜索到的很多都是垃圾信息,在垃圾信息里无限的放大了编程这件事情的复杂度,枯燥无味的教程提供了巨大的信息量,自己又缺乏组块化的能力,无法把内容消化,很快感受到了知识的诅咒。 反过来说,Google到优质的内容,借助这些内容进行Coding学习可能更符合认知科学的原理,本身并不存在固有的知识体系,借助一个又一个“卡片”式的高质量的代码学习,会发现很多自己的知识盲点,再进行高质量的搜索和实践,逐渐形成自己的编程知识“神经网络”。

无法记住所有代码?

当我回忆Chap1的内容时,发现自己好像什么也不会。让我有些焦虑,如何应对呢?

下一步行动

  • Chap1的作业内容的总结回顾
    • 查看其他小伙伴的代码,更新“大腿报告”
    • 查看自己的流水记录
    • 研究“优秀实践”卡包
    • 组织线下沟通时进行代码review(根据参与者的情况准备内容)
    • 更新自己学到的知识点,内化后整理到“教程”中去
  • GUI的探索
    • 完成作业后:放弃GUI,采用web+html5的模式
    • 研究OOP,重构自己的代码
  • 形成自己的代码命名规则和文档命名规则

其他

待看


170126

解决中文问题

  • 下载 ActiveTcl8.5.18.0.298892-macosx10.5-i386-x86_64-threaded.dmg 正常安装。
  • 查看现在tkinter引用的版本
    • 查看方法
      python3 --version
      import tkinter
      tkinter._test()
      tkinter.Tcl().eval('info patchlevel')
      
  • 通过安装包安装 ActiveTcl8.5.18
  • 尝试brew重新安装python3,问题仍然未解决
  • 定位问题的尝试策略:

Uninstall Active TCL Mac

How to uninstall Python 2.7 on a Mac OS X 10.6.4?

4. Using Python on a Macintosh

最终受 @hsdiamhsd894 的提示,下载了Python3.5,重新安装,终于改变了tkinter连接的ActiveTcl的版本为8.5.18。

个人经验总结如下:

  • 调整步骤

    • 下载 ActiveTcl8.5.18.0.298892-macosx10.5-i386-x86_64-threaded.dmg 正常安装。
    • 卸载现在的Python3版本,安装最新版Python3(3.6),测试版本代码如下:
      python3 --version
      
    • 进入python3,测试连接的版本,代码如下:
      python3
      import tkinter
      tkinter.Tcl().eval('info patchlevel')
      
    • 如果成功,完成。如果失败,卸载Python3.6,重新安装3.5,利用上面代码再次测试。目前自己测试的结果是可以实现的。
  • 问题说明

    • Python3的Tkinter模块不会自动转换连接ActiveTcl的版本,所以需要重新安装Python3
    • 自己测试后发现Python3.6没有转换ActiveTcl版本,但是3.5可以顺利实现。在3.5测试成功再次卸载后安装3.6还是没有成功,只能再次安装3.6.
      • 可能的原因是Python3.6有bug,要么是自己在删除Python3.6时没有删除完整(但是Python3.5同样的步骤,是可行的。)

results matching ""

    No results matching ""