《Python编程》笔记(十)

来源:互联网 发布:mac下载迅雷链接 编辑:程序博客网 时间:2024/05/15 06:23

tkinter之旅(三)

  • 在tkinter库中,可以添加顶层窗口菜单和基于框架的菜单。前者适用于整个窗口,后者可以作为内嵌组件。
  • 创建顶层窗口菜单的一般步骤:
    • 创建顶层的Menu作为窗口组件的子组件,并将窗口的menu属性设置为新Menu
    • 对每个下拉式对象,创建一个新的Menu作为顶层Menu的子组件,并在add_cascade方法中将新的Menu设置为顶层Menu的下拉显示对象;
    • 为上一步骤中创建的每个下拉Menu添加菜单选项,使用add_command方法的command选项来设定回调;
    • 通过创建新Menu作为子菜单,以及使用add_cascade方法连接相应父菜单和子菜单的方法,添加下拉式子菜单。
  • 创建顶层菜单的代码实例:
def make_menus(master=None):    # 创建顶层Menu    root_menu = Menu(master)    # 创建下拉菜单    file_menu = Menu(root_menu)    # 添加项目    # underline指定快捷键    file_menu.add_command(label='Open', command=on_menu_click, underline=0)    file_menu.add_command(label='Save', command=on_menu_click, underline=0)    # 添加分割    file_menu.add_separator()    file_menu.add_command(label='Exit', command=sys.exit, underline=0)    # 连接到主菜单    root_menu.add_cascade(label='File', menu=file_menu, underline=0)    # 创建带有子下拉菜单的项目    # `tearoff`用于控制是否消除菜单中出现的虚线。该虚线是一种快捷方式,可以单击它打开菜单窗口!    edit_menu = Menu(root_menu, tearoff=False)    edit_menu.add_command(label='Cut', command=on_menu_click, underline=0)    edit_menu.add_command(label='Paste', command=on_menu_click, underline=0)    root_menu.add_cascade(label='Edit', menu=edit_menu, underline=0)    sub_menu = Menu(edit_menu, tearoff=False)    sub_menu.add_command(label='Foo', command=on_menu_click, underline=0)    sub_menu.add_command(label='Bar', command=on_menu_click, underline=0)    edit_menu.add_cascade(label='Others', menu=sub_menu, underline=0)    # 记得把菜单添加到窗口中!    master.config(menu=root_menu)def main():    root = Tk()    make_menus(root)    root.mainloop()

  • 每个顶层窗口都可以有一个菜单栏,包括使用Toplevel组件创建的弹出窗口。
  • 基于Frame的菜单可以用来作为大型界面中的内嵌部件来添加菜单。通常可以创建一个Menubutton并置于Frame中,然后将Menu组件与Menubutton相关联,再将Frame与顶层容器窗口相关联,即可得到一个菜单。
def make_menu(master):    menubar = Frame(master)    menubar.pack(side=TOP, fill=X)    file_button = Menubutton(menubar, text='File', underline=0)    file_button.pack(side=LEFT)    file_menu = Menu(file_button)    file_menu.add_command(label='Open...', command=None, underline=0)    file_menu.add_command(label='Save...', command=None, underline=0)    file_button.config(menu=file_menu)
  • Optionmenu会提供一个多选项的下拉菜单,类似于ComboBox控件:
def main():    r = Tk()    opt_mail_sever = StringVar(r)    opt_mail_servers = OptionMenu(r, opt_mail_sever, 'Gmail', 'Yahoo', '163', 'Outlook', command=lambda x: showinfo('Choice', x))    opt_mail_servers.pack(fill=X)    opt_mail_sever.set('Yahoo')    r.mainloop()
  • 创建窗口下方的工具栏的方法:在窗口底部填充框架,设置为只能水平伸展即可。
  • 一个综合的示例:演示如何生产菜单栏和工具栏(这在一般的应用中是非常常见的组合),并且使用这个程序打开图片查看。由于代码较长,所以托管在github中,点击查看

  • Listbox组件:

    • 插入条目:list.insert('end', label)或者list.insert(END, label)
    • 不存在command选项来设置回调,不过可以使用绑定事件的方法来达到目的
    • 获取选中的条目索引:list.curselection(),实际返回的是个元组,记录被选中的条目index
    • 获取条目的标签:list.get(index),此外,可以使用list.get(ACTIVE)或者list.get('active')获取选中的条目标签
    • selectmode参数可以用于指定单选或多选模式,默认只允许单选。支持四种设置:SINGLE, BROWSE(Default mode), MULTIPLE, EXTENDED
  • Scrollbar组件通常用于和Listbox搭配,方便地进行列表的滚动。设置方法:

# 会自动按照比例调整滚动条和列表框# 在初始化的时候,可以给滚动条添加# orient='horizontal'即可得到水平滚动条scrollbar.config(command=listbox.yview)listbox.config(yscrollcommand=scrollbar.set)
  • tkinter中每一个可以滚动的对象(Listbox, Entry, Text, Canvas)都可以通过内置的yviewxview方法来处理垂直或水平滚动调整,yscrollcommandxscrollcommand选项用于激活相关滚动条的回调处理器。所有的滚动条都有command选项。需要注意的是,要尽量先pack滚动条,这样在窗口缩小后,保证滚动条最后消失,用户体验更佳。
  • 实例:构建一个Listbox用于显示系统字体,并且添加垂直和水平滚动条,详细代码请点击这里查看。

  • Text组件:tkinter强大的组件之一,可以提供可观的功能。Text组件支持复杂字体设置、图片嵌入、无限制撤销等。

  • Text组件的内容是Python字符串,用\n分隔多行。
  • Text组件的索引:既可以确认行,也可以确认列。1.0表示低1行第0列(注意行数从1开始计数):
text.insert('1.0', 'hello')  # 开始处插入文本text.delete('1.0', END) # 开始处删除所有文本text.get('1.0', END+'-1c') # 获取从开始到结尾所有内容,实际是`end-1c`,结尾处倒回一列,去掉`\n`
  • 指定前面一个字符:+1c,前面一行:+1l
  • Text标志:除了用行、列两个可以用于记录位置的字符串,还可以使用标志名——两个字符间位置的象征性名称,来传递位置信息。标志是新文本在插入或删除时,发生移动的虚拟位置。标志总是指向它的初始位置,即使随着时间位置移动到了新的行和列。创建标志,需要使用mark_set方法,并设置字符串名和索引以确定逻辑位置。mark_unset方法用于删除标志。
  • Text标签:Text组件字符串中与一个或多个字符串相关的符号名称。可以用来表示需要的任何位置,带标签的条目是以开始和结尾索引来命名的,这样可以被传递给基于位置的调用。

    • SEL_FIRST, SEL_LAST等效:sel.first, sel.last

      # 获取选中的文本selected_text = text.get('sel.first', 'sel.last') 
    • 添加和移除标签:

      # 所有文本标签text.tag_add('alltext', '1.0', END)# 指定选定位置text.tag_add(SEL, index1, index2)# 移除选定text.tag_remove(SEL, '1.0', END)# 删除标签text.tag_delete(...)
    • text.see()方法可以显示指定的位置(必要时会自动滚动)

  • 基于Text组件构建的简易的编辑器,编辑器代码详见这里,另外还有ScrolledText的一种实现方法。以下是运行截图:

  • tkinter剪切板接口:

self.clipboard_clear()self.clipboard_append(text)self.clipboard.get(selection='CLIPBOARD')
  • 虽然tkinter允许插入和查看一些未知编码(如bytes)的文本,但是它以str类型返回。
  • 字符串的解码值并不依赖于它的编码方案,一旦解码,字符串和编码就没有关联了,只有一个Unicode字符的序列(码点)。所以,真正需要关心的是在与文件发生转换时关心编码的问题。
>>> b'AÄBäC>>> b.encode('utf-8').decode('utf-8') == b.encode('latin-1').decode('latin-1')True # Amazing!
  • 将文本作为字节处理时需要关注的问题:

    • 除非字符串总是使用平台默认设置,否则需要知道文本模式下用于读和写的编码类型,以及二进制模式下手工解码或者编码的编码类型;
    • 只要可以处理字符串的字符,就可以使用几乎任何编码来写文件,但是至少要提供一种编码,与现有数据的二进制格式兼容,以便写入;
    • 不需要通过了解编码模式来读取文本,该文本是以二进制模式下的bytes形式显示的,但Text组件返回的str内容要求保存时必须编码,以便写入。
  • 可以在二进制模式下打开文件读取字节,从而将编码问题转给Tk库,但是由于Tk库本身的限制,还是可能会出现无法支持的编码。此外,一些由文本解码执行的有效性检查也无法进行。

  • 标签的高级功能:
    • 标签含有设置颜色、字体、制表符、行间距和对齐方式的格式属性;如果需要同时对文本中的多个部分进行设置,可以将这些部分与标签相关联,使用tag_config方法对标签应用格式设置;
    • 标签还有相关的事件绑定,可以将超链接之类应用到Text组件中,单击文本可以触发标签事件处理器。使用tag_bind方法可以做绑定设置。
  • Text组件高级应用示例:
def main():    text = Text(font=('Droid Sans', 16, 'normal'), width=30, height=15)    text.pack(fill=BOTH, expand=YES)    # 添加几行用于测试的文本    text.insert('1.0', 'Hello\n')    text.insert('2.0', 'World\n')    text.insert('3.0', 'Tkinter Text\n')    # 使用tag设置不同的字体样式    text.tag_add('hello', '1.0', '1.5')    text.tag_config('hello', background='black', foreground='white')    text.tag_add('world', '2.0', '2.5')    text.tag_config('world', font=('', 24, 'bold italic'))    text.tag_add('text', '3.8', '3.12')    text.tag_config('text', background='green')    text.tag_bind('text', '<Button-1>', echo)    # 嵌入Button组件    bt = Button(text, text='Foo bar', command=lambda: echo(None))    bt.pack(side=RIGHT)    # 嵌入图片    # 下面这个调用后,窗口大小会自动调整到合适尺寸,否则处于非常小的状态    text.window_create(END, window=bt)    text.insert(END, '\n\n')    img = ImageTk.PhotoImage(Image.open('/home/lab/dog.jpg'))    text.image_create(END, image=img)    mainloop()

版权声明

  1. 本文由 Christopher L 发表,采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。请确保你已了解许可协议,并在 转载 时声明。
  2. 本文固定链接:http://blog.chriscabin.com/coding-life/python/python-basic/1214.html。

——来自 PyPoster,让博客发布更轻松!

0 0