日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python tkinter多窗口的交互问题:子窗口无法获取数据

發布時間:2024/5/15 python 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python tkinter多窗口的交互问题:子窗口无法获取数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python tkinter多窗口的交互問題:子窗口無法獲取數據

tkinter第二個、第三個子窗口數據不能交互響應的解決方法

先說結論:第二個、第三個子窗口生成時,不能用tk.Tk(),而應改為tk.Toplevel(),問題解決。

問題描述

最近在用tk、ttk開發一個仿真軟件時,當在主窗口(tk.Tk()生成)點擊相關設置按鍵時,調用另一模塊中的函數(通過import導入),函數執行過程中彈出第二個或更多的子窗口,在子窗口輸入數據或點擊相關按鍵時,發現子窗口的交互數據無法獲得!而同樣的代碼段如果放入主窗口則沒有問題!
下圖為問題出現的場景

點擊person行的參數設置,選擇自定義模式時,調用另一模塊中的函數,彈出新的窗口。
主腳本代碼為:

person_par_set = ttk.Combobox(type_table, width=10) # 初始化 person_par_set["values"] = ("Default", "User-defined") person_par_set.current(0) # 選擇第一個 def go_person_par_set(*args): # 事件var_number = eval(number_set.get()) # 將對應的字符型數值轉換為數字var_person_prop = eval(person_prop.get())var_person_par = person_par_set.get()var_person_label = person_label.cget("text")var_person = {'label': var_person_label, 'prop': var_person_prop, 'par': var_person_par}person_row.set(var_person) # 將字典型以字符串形式賦值給控件型變量set_person(var_number, var_person) # 調用另一模塊中的函數,實現person的設置 person_par_set.bind("<<ComboboxSelected>>", go_person_par_set) # 綁定事件,(下拉列表框被選中時,綁定go()函數)

調用的函數代碼為:

def set_person(var_number, var_person): # 進行person型成員的設置person_number = round(var_number * var_person['prop'] * 0.01, 0) # 四舍五入取0位小數p = int(person_number)if var_person['par'] == "Default":tf_data = np.random.uniform(0, 1, p) # 生成0~1之間,p個均勻分布的隨機數# 為將list中每個數字保留2位,將list轉為numpy數組,然后對numpy進行操作,最后將numpy再轉為數組。tf_data = np.array(tf_data)tf_data = np.round(tf_data, 2) # round不能用于list,可用于arraytf_data = list(tf_data)np.save('person_par.npy', tf_data)elif var_person['par'] == "User-defined":win_person = tk.Tk() # 待詳細設置person屬性的子窗口win_person.title('Person Properties Settings')wid = sub_window(win_person) # 調用sub_window函數,設置窗口,并返回窗口的寬度值tf_table = ttk.LabelFrame(win_person, text='information set', labelanchor='n')tf_table.grid(column=0, row=3, padx=8, pady=15) # row,column指示相對行號和列號,非絕對位置;padx,y為掛靠坐標位置tf_radva = tk.IntVar()tf_radva.set(99)def radCall(*args):print(tf_radva.get())curRad1 = ttk.Radiobutton(tf_table, text="平均分布", value=1, variable=tf_radva, command=radCall)curRad1.grid(column=0, row=0, sticky=tk.W)curRad2 = ttk.Radiobutton(tf_table, text="正態分布", value=2, variable=tf_radva, command=radCall)curRad2.grid(column=0, row=1, sticky=tk.W)tf_data = np.random.normal(0.5, 0.1, p) # 生成0~1之間,p個均勻分布的隨機數# 為將list中每個數字保留2位,將list轉為numpy數組,然后對numpy進行操作,最后將numpy再轉為數組。tf_data = np.array(tf_data)tf_data = np.round(tf_data, 2) # round不能用于list,可用于arraytf_data = list(tf_data)np.save('person_par.npy', tf_data)

彈出設置窗口

上述代碼設計為:tf_radva初值設置為99;當radio按鈕被選中時,其值(分別為1,2)會賦給tf_radva,通過tf_radva這個IntVar型控件變量指向radio的variable的方式。擬實現的效果為,當選中<平均分布radio>時,打印1;選中<正態分布>時,打印2。而真實情況是,無論選中哪個radio,都打印99,功能不能實現。而將此段代碼放于主窗口的某個位置而不彈出新窗口的話,則功能能夠實現。

問題分析

  • 經反復測試,代碼功能沒有問題。我一度認為是,調用后臺函數時,后臺函數使用變量的生存周期問題,“在次腳本中tf_radva不能指向對應radio的variable(或者說,這種指向是臨時性的,因為次腳本的函數生存周期是臨時性,臨時性的內存分配,在窗口響應時,該臨時內存存儲地址未持續到響應事件進行時卻已結束)”,——如果說是變量生存周期的問題,那么每次點擊radio時,卻有事件的響應,每次都打印99,而不是不打印。即事件有響應,那么在響應期,變量是生存的——不是該原因。既然不是變量的生存周期問題,而確實tf_radva未指向對應radio的variable,即程序在執行variable=tf_radva時,未能將tf_radva指向當前窗口radio的變量,而此問題出現在兩個窗口共存的情況下。或者可以這樣認為,系統此時在確認哪一個是“活躍窗口”發生了問題,需要確定哪一個窗口是active的。
  • 耗費了一上午的時間,經反復查閱與搜索論壇,發現問題所在。將子窗口生成時代碼改為tk.Toplevel()即可
  • win_person = tk.Toplevel() # 待詳細設置person屬性的子窗口

    ——Toplevel(頂級窗口)組件是一個獨立的頂級窗口,這種窗口通常擁有標題欄、邊框等部件。
    ——何時使用 Toplevel 組件?
    ——Toplevel 組件通常用在顯示額外的窗口、對話框和其他彈出窗口上。
    ——Tkinter Toplevel:頂層部件的工作,直接由窗口管理器管理的窗口。他們不必在它們上面的父widget

    參考博文

    參考博文
    https://blog.csdn.net/liyuan3970/article/details/82874653
    Toplevel(頂層)
    https://blog.csdn.net/m0_37264397/article/details/79101630

    總結

    以上是生活随笔為你收集整理的Python tkinter多窗口的交互问题:子窗口无法获取数据的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。