tkinter内嵌对话框

  • 引言
  • tkinter的对话框
  • 自带对话框
  • 构思
  • 布局
  • 结构
  • 解决方案
  • 创造内嵌输入框
  • 界面布局
  • 返回输入内容
  • 完整代码例子
  • 在TinEngine中的效果
  • 初版
  • 使用TinUI绘制
  • 结语

引言

说起对话框,它在程序应用界面中扮演着一个举足轻重的角色,通过对话框,可以更好地与使用者进行交互或者是信息提示,同时还能够减少应用界面本身的位置占用,在界面开发中很有用处。

但是要面对一个显示问题,有时需要对话框频繁弹出,以此来处理各种交互任务。可对于使用者而言,一会一个对话框弹出来,打扰对电脑的正常使用,是很影响对一个应用的感受的,这会使使用效果大大降低。

那么怎么解决这个问题,就需要用到内嵌对话框,使对话框显示在应用窗口中。

tkinter的对话框

自带对话框

众所周知,在tkinter中,输入框在simpledialog中,当使用这个输入对话框后,会弹出一个输入窗口。如果使用得多了,就会频繁弹出这种输入窗口,让人难免有些厌倦。那么现在,我们开始以输入对话框为例子,开始研究内嵌对话框。

构思

布局

和tkinter自带的输入对话框一样,我们的对话框也需要一个输入框(Entry)接受输入内容,然后通过按钮(Button)返回输入内容。

结构

此外,内嵌输入框还要做到一个功能——如果过对话框没有关闭,程序不能继续执行。也就是说,当对话框出现时,程序不能够再自己运行,要获得输入内容后才能够继续运行。

相信很多人(特别是刚入手tkinter的)看到这就很为难。因为,目前没有任何资料详细说明tkinter的对话框是怎么做到的,除非自己去研究simpledialog的源码。不过,我现在告诉大家,tkinter根本没有原生对话框(文件对话框除外),我们看到的simpledialog都是当年的Python开发大神们码出来的(此处应怀有感激心)。在这篇文章,我不打算详细分析simpledialog的源码,因为我也没有完全看懂。但是我们可以依据其中的基本思路,创造出新的输入对话框。

解决方案

为了完成tkinter的内嵌输入对话框,我们需要用到一个重要函数:wait_window(window)。这个函数存在于每一个tkinter窗口和组件。而且,tkinter中的输入框就是以这个为基础构建的。

这个函数的作用:暂停界面程序,直到被指定的组件被销毁或者是删除。

不要因为这个函数的字面意思而误解其参数的含义。window不只是tkinter窗口(toplevel/tk),也可以是组件(widget)

创造内嵌输入框

界面布局

这个很随意,因为只是例子:

root=Tk()
#...省略主窗口布局代码
def askstring(master,text):
    #主体框架
    frame=tk.Frame(master,bg='black',cursor='arrow',highlightthickness=3)
    #文本提示/说明
    label=tk.Label(frame,bg='black',fg='white',text=text)
    label.pack(side='top',fill='x',pady=10)
    #输入框
    entry=tk.Entry(frame,bg='white',fg='black',font=self['font'],relief='flat')
    entry.insert(0,word)
    entry.pack(side='top',fill='x',pady=10)
    #确认按钮
    button=ttk.Button(frame,text='确认')
    button.pack(side='top',fill='x')
    #内嵌输入对话框
    frame.place(x=0,y=0,width=self.winfo_width())
    #暂停程序
    master.wait_window(frame)

def test():
    a=askstring(root)
    print(a)
root.after(1000,test)
root.mainloop()

返回输入内容

因为我们使用了wait_window使界面暂停,所有当按钮被单击,或者是在输入框按下回车时,我们将输入的结果作为主窗口的一个属性,然后再删除内嵌输入框,返回这个值:

def askstring(master,text):
    #...
    #输入框
    entry=tk.Entry(frame,bg='white',fg='black',font=self['font'],relief='flat')
    entry.insert(0,word)
    entry.bind('<Return>',lambda event:over_askstring(master,frame,entry))
    entry.pack(side='top',fill='x',pady=10)
    #确认按钮
    button=ttk.Button(frame,text='确认',command=lambda:over_askstring(master,frame,entry))
    button.pack(side='top',fill='x')
    #内嵌输入对话框
    #...
    return master.askstring_result
def over_askstring(master,frame,entry):
    master.askstring_result=entry.get()
    frame.destroy()

完整代码例子

root=Tk()
#...省略主窗口布局代码
def askstring(master,text):
    #主体框架
    frame=tk.Frame(master,bg='black',cursor='arrow',highlightthickness=3)
    #文本提示/说明
    label=tk.Label(frame,bg='black',fg='white',text=text)
    label.pack(side='top',fill='x',pady=10)
    #输入框
    entry=tk.Entry(frame,bg='white',fg='black',font=self['font'],relief='flat')
    entry.insert(0,word)
    entry.bind('<Return>',lambda event:over_askstring(master,frame,entry))
    entry.pack(side='top',fill='x',pady=10)
    #确认按钮
    button=ttk.Button(frame,text='确认',command=lambda:over_askstring(master,frame,entry))
    button.pack(side='top',fill='x')
    #内嵌输入对话框
    frame.place(x=0,y=0,width=self.winfo_width())
    #暂停程序
    master.wait_window(frame)
    return master.askstring_result
def over_askstring(master,frame,entry):
    master.askstring_result=entry.get()
    frame.destroy()

def test():
    a=askstring(root)
    print(a)
root.after(1000,test)
root.mainloop()

在TinEngine中的效果

初版

Python tkinter清除主界面 tkinter 清空frame_Python tkinter清除主界面

使用TinUI绘制

Python tkinter清除主界面 tkinter 清空frame_输入框_02


Python tkinter清除主界面 tkinter 清空frame_TinUI_03


结语

这是在tkinter中的一个小创意,其界面布局在这篇文章中只是简单说明一下,还可以继续优化。本篇文章只提供思路。