Python tkinter模块弹出窗口及传值回到主窗口操作详解


Posted in Python onJuly 28, 2017

本文实例讲述了Python tkinter模块弹出窗口及传值回到主窗口操作。分享给大家供大家参考,具体如下:

有些时候,我们需要使用弹出窗口,对程序的运行参数进行设置。有两种选择

一、标准窗口

如果只对一个参数进行设置(或者说从弹出窗口取回一个值),那么可以使用simpledialog,导入方法:

from tkinter.simpledialog import askstring, askinteger, askfloat

完整例子

import tkinter as tk
from tkinter.simpledialog import askstring, askinteger, askfloat
# 接收一个整数
def print_integer():
  res = askinteger("Spam", "Egg count", initialvalue=12*12)
  print(res)
# 接收一个浮点数
def print_float():
  res = askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
  print(res)
# 接收一个字符串
def print_string():
  res = askstring("Spam", "Egg label")
  print(res)
root = tk.Tk()
tk.Button(root, text='取一个字符串', command=print_string).pack()
tk.Button(root, text='取一个整数', command=print_integer).pack()
tk.Button(root, text='取一个浮点数', command=print_float).pack()
root.mainloop()

二、自定义窗口

如果要设置的参数个数超过两个,那么tkinter提供的标准窗口就处理不了了。

这就需要自定义一个窗口,那么问题来了:怎样将自定义窗口中的数据传回主窗口?

百度查询,不外乎两种方法:全局变量(global)、对象变量([]、{}等),都不是我想要的。

然后,去 stackoverflow 逛了一下,综合了个问题的答案,得到两个本人比较满意的方案。

一种是松耦合,另一种是紧耦合

1)松耦合

说明:

主窗类,继承了 tk.Tk
弹窗类,继承了 tk.Toplevel

要点:

弹窗,将多个数据,打包,放入一个名为 username 的私有 list 对象,销毁弹窗
主窗,待弹窗运行后,通过wait_window方法,取得弹窗的名为 username 私有变量

完整代码:

import tkinter as tk
'''松耦合'''
# 弹窗
class MyDialog(tk.Toplevel):
  def __init__(self):
    super().__init__()
    self.title('设置用户信息')
    # 弹窗界面
    self.setup_UI()
  def setup_UI(self):
    # 第一行(两列)
    row1 = tk.Frame(self)
    row1.pack(fill="x")
    tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)
    self.name = tk.StringVar()
    tk.Entry(row1, textvariable=self.name, width=20).pack(side=tk.LEFT)
    # 第二行
    row2 = tk.Frame(self)
    row2.pack(fill="x", ipadx=1, ipady=1)
    tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)
    self.age = tk.IntVar()
    tk.Entry(row2, textvariable=self.age, width=20).pack(side=tk.LEFT)
    # 第三行
    row3 = tk.Frame(self)
    row3.pack(fill="x")
    tk.Button(row3, text="取消", command=self.cancel).pack(side=tk.RIGHT)
    tk.Button(row3, text="确定", command=self.ok).pack(side=tk.RIGHT)
  def ok(self):
    self.userinfo = [self.name.get(), self.age.get()] # 设置数据
    self.destroy() # 销毁窗口
  def cancel(self):
    self.userinfo = None # 空!
    self.destroy()
# 主窗
class MyApp(tk.Tk):
  def __init__(self):
    super().__init__()
    #self.pack() # 若继承 tk.Frame ,此句必须有!
    self.title('用户信息')
    # 程序参数/数据
    self.name = '张三'
    self.age = 30
    # 程序界面
    self.setupUI()
  def setupUI(self):
    # 第一行(两列)
    row1 = tk.Frame(self)
    row1.pack(fill="x")
    tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)
    self.l1 = tk.Label(row1, text=self.name, width=20)
    self.l1.pack(side=tk.LEFT)
    # 第二行
    row2 = tk.Frame(self)
    row2.pack(fill="x")
    tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)
    self.l2 = tk.Label(row2, text=self.age, width=20)
    self.l2.pack(side=tk.LEFT)
    # 第三行
    row3 = tk.Frame(self)
    row3.pack(fill="x")
    tk.Button(row3, text="设置", command=self.setup_config).pack(side=tk.RIGHT)
  # 设置参数
  def setup_config(self):
    # 接收弹窗的数据
    res = self.ask_userinfo()
    #print(res)
    if res is None: return
    # 更改参数
    self.name, self.age = res
    # 更新界面
    self.l1.config(text=self.name)
    self.l2.config(text=self.age)
  # 弹窗
  def ask_userinfo(self):
    inputDialog = MyDialog()
    self.wait_window(inputDialog) # 这一句很重要!!!
    return inputDialog.userinfo
if __name__ == '__main__':
  app = MyApp()
  app.mainloop()

2)紧耦合

说明:

主窗类,继承了 tk.Tk
弹窗类,继承了 tk.Toplevel

要点:

弹窗,显式地保存父窗口,显式地修改父窗口数据,显式地更新父窗口部件,最后销毁弹窗
主窗,待弹窗运行后,通过wait_window方法,返回 None

完整代码:

import tkinter as tk
'''紧耦合'''
# 弹窗
class PopupDialog(tk.Toplevel):
  def __init__(self, parent):
    super().__init__()
    self.title('设置用户信息')
    self.parent = parent # 显式地保留父窗口
    # 第一行(两列)
    row1 = tk.Frame(self)
    row1.pack(fill="x")
    tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)
    self.name = tk.StringVar()
    tk.Entry(row1, textvariable=self.name, width=20).pack(side=tk.LEFT)
    # 第二行
    row2 = tk.Frame(self)
    row2.pack(fill="x", ipadx=1, ipady=1)
    tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)
    self.age = tk.IntVar()
    tk.Entry(row2, textvariable=self.age, width=20).pack(side=tk.LEFT)
    # 第三行
    row3 = tk.Frame(self)
    row3.pack(fill="x")
    tk.Button(row3, text="取消", command=self.cancel).pack(side=tk.RIGHT)
    tk.Button(row3, text="确定", command=self.ok).pack(side=tk.RIGHT)
  def ok(self):
    # 显式地更改父窗口参数
    self.parent.name = self.name.get()
    self.parent.age = self.age.get()
    # 显式地更新父窗口界面
    self.parent.l1.config(text=self.parent.name)
    self.parent.l2.config(text=self.parent.age)
    self.destroy() # 销毁窗口
  def cancel(self):
    self.destroy()
# 主窗
class MyApp(tk.Tk):
  def __init__(self):
    super().__init__()
    # self.pack() # 若继承 tk.Frame,此句必须有!!!
    self.title('用户信息')
    # 程序参数
    self.name = '张三'
    self.age = 30
    # 程序界面
    self.setupUI()
  def setupUI(self):
    # 第一行(两列)
    row1 = tk.Frame(self)
    row1.pack(fill="x")
    tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)
    self.l1 = tk.Label(row1, text=self.name, width=20)
    self.l1.pack(side=tk.LEFT)
    # 第二行
    row2 = tk.Frame(self)
    row2.pack(fill="x")
    tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)
    self.l2 = tk.Label(row2, text=self.age, width=20)
    self.l2.pack(side=tk.LEFT)
    # 第三行
    row3 = tk.Frame(self)
    row3.pack(fill="x")
    tk.Button(row3, text="设置", command=self.setup_config).pack(side=tk.RIGHT)
  # 设置参数
  def setup_config(self):
    pw = PopupDialog(self)
    self.wait_window(pw) # 这一句很重要!!!
    return
if __name__ == '__main__':
  app = MyApp()
  app.mainloop()

效果图

Python tkinter模块弹出窗口及传值回到主窗口操作详解

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python处理中文编码和判断编码示例
Feb 26 Python
python简单的函数定义和用法实例
May 07 Python
Python ValueError: invalid literal for int() with base 10 实用解决方法
Jun 21 Python
Python抓取电影天堂电影信息的代码
Apr 07 Python
一些常用的Python爬虫技巧汇总
Sep 28 Python
Python实现公历(阳历)转农历(阴历)的方法示例
Aug 22 Python
Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
Mar 19 Python
Django分组聚合查询实例分享
Apr 29 Python
Python3爬虫中Ajax的用法
Jul 10 Python
django Model层常用验证器及自定义验证器详解
Jul 15 Python
Python语言编写智力问答小游戏功能
Oct 13 Python
Python实现信息管理系统
Jun 05 Python
Python单体模式的几种常见实现方法详解
Jul 28 #Python
深入浅出分析Python装饰器用法
Jul 28 #Python
分享一个可以生成各种进制格式IP的小工具实例代码
Jul 28 #Python
Python使用sorted排序的方法小结
Jul 28 #Python
python发送邮件实例分享
Jul 28 #Python
Python分治法定义与应用实例详解
Jul 28 #Python
Python更新数据库脚本两种方法及对比介绍
Jul 27 #Python
You might like
PHP4(windows版本)中的COM函数
2006/10/09 PHP
PHP错误提示的关闭方法详解
2013/06/23 PHP
解析php中的escape函数
2013/06/29 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
javascript 常用代码技巧大收集
2009/02/25 Javascript
Javascript this指针
2009/07/30 Javascript
js模拟类继承小例子
2010/07/17 Javascript
JQuery优缺点分析说明
2011/04/10 Javascript
jquery的$getjson调用并获取远程的JSON字符串问题
2012/12/10 Javascript
js获取指定日期前后的日期代码
2013/08/20 Javascript
jQuery中prependTo()方法用法实例
2015/01/08 Javascript
javascript仿百度输入框提示自动下拉补全
2016/01/07 Javascript
JS+HTML5实现图片在线预览功能
2017/07/22 Javascript
jQuery实现table中两列CheckBox只能选中一个的示例
2017/09/22 jQuery
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
2017/11/20 Javascript
基于JavaScript 性能优化技巧心得(分享)
2017/12/11 Javascript
Vue三层嵌套路由的示例代码
2018/05/05 Javascript
vue权限路由实现的方法示例总结
2018/07/29 Javascript
小程序云开发实战小结
2018/10/25 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
jQuery 图片查看器插件 Viewer.js用法简单示例
2020/04/04 jQuery
JavaScript 空间坐标的使用
2020/08/19 Javascript
JavaScript实现切换多张图片
2021/01/27 Javascript
[28:57]EG vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/16 DOTA
Python3多线程基础知识点
2019/02/19 Python
python实现本地批量ping多个IP的方法示例
2019/08/07 Python
Python3查找列表中重复元素的个数的3种方法详解
2020/02/13 Python
Python HTMLTestRunner可视化报告实现过程解析
2020/04/10 Python
打造完美自荐信
2014/01/24 职场文书
教师党员群众路线教育实践活动心得体会
2014/11/04 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
淘宝客服专员岗位职责
2015/04/07 职场文书
信息技术课教学反思
2016/02/23 职场文书
驾驶员安全责任协议书
2016/03/22 职场文书
2016年教师党员公开承诺书
2016/03/24 职场文书