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 简易计算器程序,代码就几行
Aug 29 Python
python实现udp数据报传输的方法
Sep 26 Python
Django中使用locals()函数的技巧
Jul 16 Python
python结合selenium获取XX省交通违章数据的实现思路及代码
Jun 26 Python
SVM基本概念及Python实现代码
Dec 27 Python
matlab中实现矩阵删除一行或一列的方法
Apr 04 Python
python 请求服务器的实现代码(http请求和https请求)
May 25 Python
Pycharm 创建 Django admin 用户名和密码的实例
May 30 Python
python3.5安装python3-tk详解
Apr 26 Python
python 中如何获取列表的索引
Jul 02 Python
Python简易版图书管理系统
Aug 12 Python
python批量替换文件名中的共同字符实例
Mar 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
PHP has encountered an Access Violation
2007/01/15 PHP
PHP中的array数组类型分析说明
2010/07/27 PHP
php小经验:解析preg_match与preg_match_all 函数
2013/06/29 PHP
PHP实现递归复制整个文件夹的类实例
2015/08/03 PHP
PHP中Array相关函数简介
2016/07/03 PHP
utf-8编码引起js输出中文乱码的解决办法
2010/06/23 Javascript
JavaScript事件委托的技术原理探讨示例
2014/04/17 Javascript
在JavaScript中使用NaN值的方法
2015/06/05 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
JS组件Bootstrap Select2使用方法详解
2020/04/17 Javascript
使用bootstrapValidator插件进行动态添加表单元素并校验
2016/09/28 Javascript
JS识别浏览器类型(电脑浏览器和手机浏览器)
2016/11/18 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
2018/07/03 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
layui table动态表头 改变表格头部 重新加载表格的方法
2019/09/21 Javascript
vue实现文字加密功能
2019/09/27 Javascript
Vue开发环境跨域访问问题
2020/01/22 Javascript
vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案
2021/03/01 Vue.js
[01:01:29]2018DOTA2亚洲邀请赛 4.4 淘汰赛 VP vs Liquid 第一场
2018/04/05 DOTA
浅谈用Python实现一个大数据搜索引擎
2017/11/28 Python
python使用requests模块实现爬取电影天堂最新电影信息
2019/04/03 Python
详解CSS3实现响应式手风琴效果
2020/06/10 HTML / CSS
HTML5 Canvas实现放大镜效果示例
2020/03/25 HTML / CSS
美国社交购物市场:MassGenie
2019/02/18 全球购物
英国亚马逊官方网站:Amazon.co.uk
2019/08/09 全球购物
婚鞋、新娘鞋、礼服鞋、童鞋:Nina Shoes
2019/09/04 全球购物
应届毕业生个人自我评价
2013/09/20 职场文书
公共事业管理本科生求职信
2013/10/07 职场文书
白酒市场开发计划书
2014/01/09 职场文书
电气工程及其自动化专业毕业生自荐信
2014/06/21 职场文书
高速铁道技术专业求职信
2014/08/09 职场文书
综合实践活动报告
2015/02/05 职场文书
摩登时代观后感
2015/06/03 职场文书
民主生活会主持词
2015/07/01 职场文书
Python文件的操作示例的详细讲解
2021/04/08 Python
MySQL索引失效的典型案例
2021/06/05 MySQL