频道栏目
首页 > 资讯 > Python > 正文

《Python编程》笔记(八)

17-03-02        来源:[db:作者]  
收藏   我要投稿

tkinter之旅(一)

组件的外观配置:主要调用config方法或者初始化的时候添加配置选项。
def main():
    root = Tk()
    label_font = ('Droid Sans', 20, 'bold')
    label = Label(root, text='你好,欢迎来到GUI的世界!')
    label.config(bg='blue', fg='white')
    label.config(font=label_font)
    print(len(label['text']) + 5)
    label.config(height=5, width=len(label['text']) * 2)
    label.pack(expand=YES, fill=BOTH)
    root.mainloop()

main()

一些常用的标签或者类似组件的通用配置介绍:

颜色:bg顾名思义,就是设置背景色;fg则用于设置前景色。颜色支持简单的颜色名称如blue或者十六进制字符串如#ff0000。 大小:设置组件的大小(height和width。 字体:字体设置参数由一个三元组提供(字体名称, 字体大小, 字体类型)。常用的字体类型如下: normal:正常 romam:罗马 italic:斜体 underline:下划线 overstrike:加粗 组合:bold italic

其他自定义外观的配置选项:

边框和浮凸: bd=N可以设置组件的边框宽度; relief=S可以指定一种边框类型: FLAT:扁平 SUNKEN:凹陷 RAISED:凸起 GROOVE:凹槽 SOLID:加粗 RIDGE:脊状 光标:cursor="gumby"可以将鼠标指针设置为Gumby图形。其他常用的有watch(手表)、pencil(铅笔)、crdss(十字)和hand2(手形2)。 状态:某些组件支持状态属性设置,从而影响到外观。state常用的选项:DISABLED(禁用)、NORMAL(正常)、READONLY等。 留白:通过padx=N和pady=N选项来设置,可以为组件周围添加额外的空间。此外,可以在pack调用中也可以对这两个选项设置。

综合的示例:

# 普通实现
def main():
    # 这里的padx, pady设置是给标签周围留白
    button = Button(text='FooBar', padx=10, pady=10)
    button.config(cursor='gumby')
    button.config(bd=8, relief=RAISED)
    button.config(bg='dark blue', fg='white')
    button.config(font=('Source Code Pro', 20, 'underline italic'))
    button.pack()
    # 这个是给Button组件留白,相应地会改变默认的窗口大小
    button.pack(padx=30, pady=30)
    mainloop()

# 使用类继承实现
class ThemeButton(Button):
    def __init__(self, master=None, cnf={}, **kw):
        # super(ThemeButton, self)调用会返回一个类似`Button`的`self`,然后
        # 调用父类的`__init__`函数即可。
        # 直接使用`Button.__init__(...)`会出错!
        super(ThemeButton, self).__init__(master, cnf, **kw)
        self.pack()
        self.config(padx=10,
                    pady=10,
                    cursor='gumby',
                    bd=8,
                    relief=RAISED,
                    bg='blue',
                    fg='white',
                    font=('Source Code Pro', 20, 'underline italic')
        )

ThemeButton(text='FooBar').pack(padx=30, pady=30)

所有的tkinter的GUI都有一个应用程序的根窗口,无论该窗口是默认创建的还是显示调用Tk()创建的。一般会在根窗口中封装最重要和使用时间最长的组件。 Toplevel组件对象可以帮助创建任意数量的独立窗口,这些窗口可以根据需要生成或弹出。所创建的每个Toplevel对象都会创建新的窗口,并且自动将新窗口添加到程序的GUI事件循环处理流中(无需调用new_window.mainloop()激活)。Toplevel多用于实现多窗口显示、弹出模态和非模态对话框等。
def toplevel_demo():
    win1 = Toplevel()
    win1.title('win1')
    win2 = Toplevel()
    win2.title('win2')
    Button(text='Quit', command=sys.exit).pack()
    Button(win1, text='Win1: Close', command=win1.destroy).pack()
    Button(win2, text='Win1: Close', command=win2.destroy).pack()
    mainloop()

顶层窗口协议介绍:

拦截关闭:protocol,可以在点击关闭按钮后拦截关闭事件,比如win.protocol('WM_DELETE_WINDOW', lambda: None)表示忽略关闭操作。 关闭一个窗口(及其子窗口):destroy。 关闭所有的窗口:quit,事实上是终止有效的mainloop调用。 窗口标题设置:win.title(string)。 窗口图标:win.iconbitmap(path_to_your_icon)。 几何管理:顶层窗口是其他组件的容器,顶层窗口组件自身永远不会封装(或者网格化、放置)。可以调用maxsize()获取最大化窗口大小(屏幕尺寸,[宽度,高度]二元组);geometry(宽* 高+x+y)设置窗口的初始大小。 状态:iconify和withdraw方法可以隐藏并消除一个正在使用的窗口;deiconify会重绘被隐藏或删除的窗口。state可以查询或改变状态:iconic, withdrawn, normal。 菜单:每个顶层窗口都可以有自己的菜单。

可以通过组件的master属性得到组件的所属者。

对话框:所有的标准对话框调用都是模态的,并且标准对话框在显示时会阻塞程序的主窗口。 简单的对话框示例:
def callback():
    if askyesno('Verify', 'Are sure about it?'):
        showwarning('Yes', 'Quit now...')
    else:
        showinfo('No', 'Quit has been canceled')


def main():
    errmsg = 'Sorry, no Spam allowed!'
    Button(text='Quit', command=callback).pack(fill=X)
    Button(text='Spam', command=(lambda: showerror('Spam', errmsg))).pack(fill=X)
    mainloop()
标准对话框模块主要有:filedialog, colorchooser, messagebox, simpledialog,以下给出综合的示例代码:
from tkinter import *
import tkinter.messagebox as messagebox
import tkinter.filedialog as filedialog
import tkinter.colorchooser as colorchooser
import tkinter.simpledialog as simpledialog


FONT_NORMAL = ('Droid Sans', 10, 'normal')
FONT_BOLD = ('Droid Sans', 12, 'bold')


class MButton(Button):
    def __init__(self, master=None, cnf={}, **kw):
        super(MButton, self).__init__(master, cnf, **kw)
        self.config(font=FONT_NORMAL)
        self.pack(side=LEFT, expand=YES, fill=Y)


class MLabel(Label):
    def __init__(self, master=None, cnf={}, **kw):
        super(MLabel, self).__init__(master, cnf, **kw)
        self.pack(side=TOP, expand=YES, fill=X)
        self.config(font=FONT_BOLD)


class MFrame(Frame):
    def __init__(self, master=None, cnf={}, **kw):
        super(MFrame, self).__init__(master, cnf, **kw)
        self.pack(side=TOP, expand=YES, fill=X, pady=10)
        self.label = None
        self.make_widgets()

    def make_widgets(self):
        pass

    def print_result(self, text):
        if self.label:
            self.label.config(text='测试结果:{}'.format(text))


class MessageBoxFrame(MFrame):
    def __init__(self, master=None, cnf={}, **kw):
        super(MessageBoxFrame, self).__init__(master, cnf, **kw)

    def make_widgets(self):
        MLabel(self, text='消息对话框演示')
        self.label = MLabel(self, text='等待测试...')
        MButton(self, text='Ask Yes No', command=self.yesno_demo)
        MButton(self, text='Ask Ok Cancel', command=self.okcancel_demo)
        MButton(self, text='Question', command=self.question_demo)
        MButton(self, text='Retry', command=self.retrycancel_demo)
        MButton(self, text='Yes No Cancel', command=self.yesnocancel_demo)
        MButton(self, text='Show Error', command=self.showerror_demo)
        MButton(self, text='Show Info', command=self.showwarning_demo)
        MButton(self, text='Show Warning', command=self.showinfo_demo)

    def yesno_demo(self):
        self.print_result(messagebox.askyesno('Yes No', 'Yes or No? Give me your answer.'))

    def okcancel_demo(self):
        self.print_result(messagebox.askokcancel('Ok Cancel', 'Do you want to quit?'))

    def question_demo(self):
        self.print_result(messagebox.askquestion('Question', 'No question here.'))

    def retrycancel_demo(self):
        self.print_result(messagebox.askretrycancel('Retry', 'Do you want to retry or not?'))

    def yesnocancel_demo(self):
        self.print_result(messagebox.askyesnocancel('Yes No Cancel', 'You know what?'))

    def showerror_demo(self):
        self.print_result(messagebox.showerror('Error', 'Nothing happened here.'))

    def showwarning_demo(self):
        self.print_result(messagebox.showwarning('Warn', 'Nothing happened here.'))

    def showinfo_demo(self):
        self.print_result(messagebox.showinfo('Info', 'Nothing happened here.'))


class ColorChooserFrame(MFrame):
    def __init__(self, master=None, cnf={}, **kw):
        super(ColorChooserFrame, self).__init__(master, cnf, **kw)

    def make_widgets(self):
        MLabel(self, text='颜色选择演示')
        self.label = MLabel(self, text='等待测试...')
        MButton(self, text='选择颜色', command=self.askcolor_demo)

    def askcolor_demo(self):
        r = colorchooser.askcolor('blue')
        self.print_result(r)
        self.label.config(fg=r[-1])


class SimpleDialogFrame(MFrame):
    def __init__(self, master=None, cnf={}, **kw):
        super(SimpleDialogFrame, self).__init__(master, cnf, **kw)

    def make_widgets(self):
        MLabel(self, text='简单对话框演示')
        self.label = MLabel(self, text='等待测试...')
        MButton(self, text="输入字符串",
                command=lambda: self.print_result(simpledialog.askstring('Input', 'Your name: ')))
        MButton(self, text="输入整数",
                command=lambda: self.print_result(simpledialog.askstring('Input', 'Your age: ')))
        MButton(self, text="输入浮点数",
                command=lambda: self.print_result(simpledialog.askstring('Input', 'Your height: ')))


class FileDialogFrame(MFrame):
    def __init__(self, master=None, cnf={}, **kw):
        super(FileDialogFrame, self).__init__(master, cnf, **kw)

    def make_widgets(self):
        MLabel(self, text='文件对话框演示')
        self.label = MLabel(self, text='等待测试...')
        MButton(self, text='打开目录', command=lambda: self.print_result(filedialog.askdirectory()))
        MButton(self, text='打开文件', command=lambda: self.print_result(filedialog.askopenfile()))
        MButton(self, text='选择文件名', command=lambda: self.print_result(filedialog.askopenfilename()))
        MButton(self, text='选择多个文件名', command=lambda: self.print_result(filedialog.askopenfilenames()))
        MButton(self, text='打开多个文件', command=lambda: self.print_result(filedialog.askopenfiles()))
        MButton(self, text='保存为...', command=lambda: self.print_result(filedialog.asksaveasfile()))
        MButton(self, text='保存为文件名...', command=lambda: self.print_result(filedialog.asksaveasfilename()))


def main():
    MessageBoxFrame()
    ColorChooserFrame()
    SimpleDialogFrame()
    FileDialogFrame()
    mainloop()


if __name__ == '__main__':
    main()



自定义对话框支持任意接口,会创建一个带有附加组件的Toplevel的弹出式窗口,并安排一个回调处理程序来获取用户的对话框输入并负责销毁窗口。如果是模态窗口,则需要通过给出窗口输入焦点来等待答复,并且同时使其他窗口无效且等待事件。 模态对话框中锁定其他窗口并等待答复的普遍构建模式:
win.focus_set() win.grab_set():设置后用户不能和其他窗口交互 win.wait_window() 一个简单的模态对话框示例:
def dialog():
    win = Toplevel()
    Label(win, text='You see see.').pack()
    Button(win, text='Ok', command=win.destroy).pack()

    # 这里很关键,否则就不是模态对话框了
    win.focus_set()
    win.grab_set()
    win.wait_window()

    print('Dialog exit.')


def main():
    Button(text='Open dialog', command=dialog).pack()
    mainloop()

参考

Stack Overflow: Tkinter Attribute Error.
相关TAG标签
上一篇:编码练习——Java-2-流程控制
下一篇:ASP.NET Core依赖注入解读及使用Autofac替代实现
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站