PySimpleGUI:如何在辅助 window 中绑定元素?

PySimpleGUI: How does one bind elements in a secondary window?

我有一个主要 window 元素,key = -PATIENT-。当我退出元素时,函数 运行s 将条目大写并更新元素。都好。我还有一个带有元素的辅助 window,key = -NAME-。我希望能够绑定辅助 window 元素,这样当我退出它时,它也会 运行 一个类似的函数来将条目大写并更新元素。这是我遇到问题的地方。 当在 -PATIENT- 元素中输入姓名时,在 FocusOut 上,该姓名会被大写并对照姓名列表进行检查。如果名称不在列表中,弹出窗口会询问是否应将其放入辅助 window 元素中。如果是,则完成此操作。但是,如果从下拉菜单(编辑)中将新名称添加到辅助 window 的 -NAME- 元素,则如果名称是小写,则将其首字母更改为大写的函数应该运行。我无法让此绑定为辅助 window 工作。我附上一个简单的示例程序(代码)来说明问题。请帮忙

    #CashBook.py
import PySimpleGUI as sg
import tkinter as tk
from tkinter import ttk
from tkcalendar import Calendar, DateEntry
import sqlite3
import datetime as dt
import time
from prettytable import PrettyTable
import subprocess, sys
from tkinter.filedialog import askopenfilename


sg.ChangeLookAndFeel('GreenTan')#LightGrey

menu_def = [['File', ['Open', 'Save', 'Exit'  ]],      
           ['Edit', ['Add a Patient','Add a Supplier']],
           ['Reports',['List of patients', 'List of suppliers','Income.....',['by category','by procedure','by patient'],'Expenses by category.....',['by category','by type','by supplier'],],],
           ['Help', 'About...'],]


layout1=[
[sg.T('Patient name:'),sg.In(size=(15,1),key='-PATIENT-')],
[sg.T('')],
[sg.T('')],
]

tabgrp=[[sg.TabGroup([[sg.Tab('Receipts',layout1,key='-RECEIPTS-'),#,title_color='Green',border_width=10,background_color='White',tooltip='Enter receipts',element_justification='centre'),
]], tab_location='topleft',
                       title_color='Red', tab_background_color='Purple',selected_title_color='Green',
                       selected_background_color='Gray', border_width=5)]] 
layout3=[
[sg.T('Closing balance: '),sg.In(size=10,key='_CLOSBAL_'),sg.Push(),sg.Button('Close',button_color='red')]]

layout=[
[sg.Menu(menu_def, )], 
[sg.Push(),sg.T('FootSmart Cash Book',font=('Verdana',24,'bold'),text_color='turquoise'),sg.Push()],
[sg.Push(),sg.T('Enter transaction details in one of the TABS below',font=('Verdana',18,'bold'),text_color ='turquoise'),sg.Push()],
[sg.T('')],
[sg.T('')],
[sg.T('')],
]

layout += tabgrp + layout3
window =sg.Window('Cash Book', layout, finalize=True)
""" Try the binding here. It does not work"""
#window.find_element['-NAME-'].bind('<FocusOut>','FOCUS OUT')

def capitalise_new_patient_names():

    name=values(add_patient_window(['-NAME-']))
    newname=name.title()
    msg=''
    print(newname)
    
def add_patient_window():
    """
    Function to create secondary window
    """

    add_patient_layout=[
        
        [sg.Push(),sg.T('Add a patient',text_color='blue',font=40),sg.Push()],
        [sg.T('')],
        [sg.T('Patient name'),sg.Push(),sg.In(newname,size=20, key='-NAME-')],
    ]

    add_patient_window=sg.Window('Add a new patient', add_patient_layout, modal=True,finalize=True)#Secondary window

    while True:                             # Event loop for secondary window

        event,values=add_patient_window.read()  # Read secondary window
        if event in (None,'Quit'):
            break

        elif event==window('-NAME-FOCUS OUT'):
            capitalise_new_patient_names()
    """Try binding here. Also does not work"""
    #window.find_element['-NAME-'].bind('<FocusOut>','FOCUS OUT')
       
    add_patient_window.close()
   
#'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'
window['-PATIENT-'].bind('<FocusOut>','FOCUS OUT')

def capitalise_patient_names():
    name=values['-PATIENT-']
    Newname=name.title()
    msg=''
    print(Newname)
    window['-PATIENT-'].update(Newname)

while True:
    event, values = window.read()
    print(event, values)
    if event in (sg.WIN_CLOSED, 'Cancel','Close'):
        break
    elif event=='Add Patient':
        add_patient_window()

    elif event=='Add a Patient':
        newname=""
        add_patient_window()
       
    elif event == '-PATIENT-FOCUS OUT':

        capitalise_patient_names()

        pat_name=values['-PATIENT-']

        if not pat_name in ['Nicky Betts','Frank Aldridge','']:

            print('This is a new patient ' + pat_name)

            reply=sg.PopupOKCancel('Warning!', 'This is a new patient. Add patient?')

            if reply=='OK':

                newname=values['-PATIENT-'].title()
               
                add_patient_window()

            elif reply=='Cancel':

                continue
    
window.close()

我三天前不是已经回复过这个问题了吗?

此处发现三个问题

  • 通过 window[key] 查找元素以调用函数 window.find_element(key),而不是 window.find_element[key]
  • 不要对函数和变量使用相同的名称,例如
def add_patient_window():
    ...
    add_patient_window=sg.Window('Add a new patient', add_patient_layout, modal=True,finalize=True)#Secondary window
  • window 中未定义键为“-NAME-”的元素,因此应在 window add_patient_window 中绑定,而不是在 window window 中绑定.

替换

...
window =sg.Window('Cash Book', layout, finalize=True)
window.find_element['-NAME-'].bind('<FocusOut>','FOCUS OUT')
...
def add_patient_window():
...
    add_patient_window=sg.Window('Add a new patient', add_patient_layout, modal=True,finalize=True)
...

来自

...
window =sg.Window('Cash Book', layout, finalize=True)
...
def add_patient_window():
...
    patient_window=sg.Window('Add a new patient', add_patient_layout, modal=True,finalize=True)
    patient_window.find_element('-NAME-').bind('<FocusOut>','FOCUS OUT')
    # or patient_window['-NAME-'].bind('<FocusOut>','FOCUS OUT')
...

由于很多问题,我无法从您的代码中找到编程逻辑,所以这里临时代码仅供参考,可能removed/deleted后者。

import PySimpleGUI as sg

def add_patient_window(name):
    layout=[
        [sg.Push(),
         sg.T('Add a patient', text_color='blue',font=40),
         sg.Push()],
        [sg.T()],
        [sg.T('Patient name'),
         sg.Push(),
         sg.In(name, size=20, key='-NAME-')],
        [sg.Button('OK'), sg.Button('Cancel')],
    ]
    window = sg.Window('Add a new patient', layout, modal=True, finalize=True)
    # window['-NAME-'].bind('<FocusOut>', 'FOCUS OUT')
    name = None
    event, values = window.read()
    if event == 'OK':       # if event == '-NAME-FOCUS OUT':
        name = values['-NAME-'].title()
    window.close()
    return name

font18 = ('Verdana', 18, 'bold')
font24 = ('Verdana', 24, 'bold')

menu_def = [
    ['File',
        ['Open', 'Save', 'Exit'  ]],
    ['Edit',
        ['Add a Patient','Add a Supplier']],
    ['Reports',
        ['List of patients',
         'List of suppliers',
         'Income.....',
            ['by category',
             'by procedure',
             'by patient'],
         'Expenses by category.....',
            ['by category',
             'by type',
             'by supplier'],
        ],
    ],
    ['Help', 'About...'],
]

sg.theme('DarkBlue3')

tab1=[[sg.T('Patient name:'), sg.In(size=(15,1), key='-PATIENT-')],]
tabgroup = [[sg.Tab('Receipts', tab1, key='-RECEIPTS-')]]
layout=[
    [sg.Menu(menu_def, )],
    [sg.Push(),
     sg.T('FootSmart Cash Book', font=font24,text_color='turquoise'),
     sg.Push()],
    [sg.Push(),
     sg.T('Enter transaction details in one of the TABS below', font=font18,
        text_color='turquoise'),
     sg.Push()],
    [sg.TabGroup(tabgroup, tab_location='topleft', title_color='Red',
        tab_background_color='Purple',selected_title_color='Green',
        selected_background_color='Gray', border_width=5)],
    [sg.T('Closing balance: '),
     sg.In(size=10, key='_CLOSBAL_'),
     sg.Push(),
     sg.Button('Close', button_color='red')],
]
window =sg.Window('Cash Book', layout, finalize=True)
window['-PATIENT-'].bind('<FocusOut>','FOCUS OUT')
new_name = None

while True:
    event, values = window.read()
    if event in (sg.WIN_CLOSED, 'Close'):
        break
    elif event=='Add Patient':
        new_name = add_patient_window('')
    elif event=='Add a Patient':
        new_name = add_patient_window('')
    elif event == '-PATIENT-FOCUS OUT':
        name=values['-PATIENT-'].title()
        if name not in ['Nicky Betts','Frank Aldridge','']:
            print('This is a new patient ' + name)
            reply=sg.PopupOKCancel('Warning!', 'This is a new patient. Add patient?')
            if reply=='OK':
                new_name = add_patient_window(name)
            elif reply=='Cancel':
                continue
    if new_name:
        window['-PATIENT-'].update(new_name)
        new_name = None

window.close()