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中struct模块对字节流/二进制流的操作教程
Jan 21 Python
python通过elixir包操作mysql数据库实例代码
Jan 31 Python
JavaScript实现一维数组转化为二维数组
Apr 17 Python
python 统计数组中元素出现次数并进行排序的实例
Jul 02 Python
linux安装Python3.4.2的操作方法
Sep 28 Python
使用Python的turtle模块画国旗
Sep 24 Python
Django中自定义查询对象的具体使用
Oct 13 Python
python如果快速判断数字奇数偶数
Nov 13 Python
Python Tkinter模块 GUI 可视化实例
Nov 20 Python
Python捕获异常堆栈信息的几种方法(小结)
May 18 Python
python通过cython加密代码
Dec 11 Python
Python 避免字典和元组的多重嵌套问题
Jul 15 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
php程序效率优化的一些策略小结
2010/07/17 PHP
PHP实现获取文件后缀名的几种常用方法
2015/08/08 PHP
php基于mcrypt_encrypt和mcrypt_decrypt实现字符串加密解密的方法
2016/07/12 PHP
PHP使用mysqli同时执行多条sql查询语句的实例
2019/03/22 PHP
PHP实现计算器小功能
2020/08/28 PHP
javascript读取RSS数据
2007/01/20 Javascript
jquery select 设置默认选中的示例代码
2014/02/07 Javascript
Jquery EasyUI中弹出确认对话框以及加载效果示例代码
2014/02/13 Javascript
jQuery select表单提交省市区城市三级联动核心代码
2014/06/09 Javascript
Javascript中使用A标签获取当前目录的绝对路径方法
2015/03/02 Javascript
jQuery中$this和$(this)的区别介绍(一看就懂)
2015/07/06 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
node.js require() 源码解读
2015/12/13 Javascript
深入理解angularjs过滤器
2016/05/25 Javascript
ReactNative页面跳转实例代码
2016/09/27 Javascript
js控制台输出的方法(详解)
2016/11/26 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
浅谈Vuejs中nextTick()异步更新队列源码解析
2017/12/31 Javascript
Vue2.5通过json文件读取数据的方法
2018/02/27 Javascript
vue-router 2.0 跳转之router.push()用法说明
2020/08/12 Javascript
如何在vue中使用kindeditor富文本编辑器
2020/12/19 Vue.js
vue 组件基础知识总结
2021/01/26 Vue.js
[03:42]2018完美盛典-《加冕》
2018/12/16 DOTA
Python求导数的方法
2015/05/09 Python
Python实现更改图片尺寸大小的方法(基于Pillow包)
2016/09/19 Python
一个月入门Python爬虫学习,轻松爬取大规模数据
2018/01/03 Python
Java编程迭代地删除文件夹及其下的所有文件实例
2018/02/10 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
yy司仪主持词
2014/03/22 职场文书
乡村文明行动实施方案
2014/03/29 职场文书
高三物理教学反思
2016/02/20 职场文书
大学生军训心得体会5篇
2019/08/15 职场文书
导游词之河北滦平金山岭长城
2019/10/16 职场文书
pytorch model.cuda()花费时间很长的解决
2021/06/01 Python
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
2021/06/05 Python
OpenCV-Python模板匹配人眼的实例
2021/06/08 Python