मेरे पास एक मॉड्यूल है जो निम्न फॉर्म (पायथन टिंकर का उपयोग करके) उत्पन्न करता है:

enter image description here

enter image description here

enter image description here

जैसा कि आप देख सकते हैं कि फॉर्म में तीन राज्य हो सकते हैं:

  • संपादन योग्य नहीं - प्रवेश बॉक्स अक्षम हैं - रद्द करें और संपादित करें बटन सक्रिय
  • बिना किसी बदलाव के संपादन योग्य - प्रविष्टि बॉक्स सक्रिय हैं, रद्द करें बटन और संपादन बटन अक्षम हो जाता है सहेजें बटन और
  • परिवर्तनों के साथ संपादन योग्य - प्रविष्टि बॉक्स सक्रिय हैं, रद्द करें बटन एक पूर्ववत बटन बन जाता है और सहेजें बटन सक्रिय हो जाता है

इसे प्राप्त करने के लिए मेरा कोड इस प्रकार है:

def display_selected_user(event, user_frame, editable):

    def fill_entry_boxes():
        # Clear entry boxes
        f_name.entry.delete(0, 'end')
        l_name.entry.delete(0, 'end')
        email.entry.delete(0, 'end')

        # Populate with original data
        f_name.entry.insert(0, user_dict[user_id]['f_name'])
        l_name.entry.insert(0, user_dict[user_id]['l_name'])
        email.entry.insert(0, user_dict[user_id]['email'])

        cancel_btn.config(text="Cancel")

    def cancel_revert_process():
        if not changes_made():
            user_detail_frame.grid_forget()
            close_btn.grid(row=2, column=2, padx=10, pady=10, sticky='E')
        else:
            MsgBox = messagebox.askquestion('Revert Changes',
                                            f'Changes have been made - are you sure you want to revert?',
                                            icon='question')
            if MsgBox == 'yes':
                fill_entry_boxes()
                edit_save_btn.config(state='disabled', bg='gray80')

    def save_or_edit(event, _editable):
        if _editable:
            save_process(_editable)
        else:
            make_editable_process(_editable)

    def save_process(_editable):
        # Notify user of process commencement
        user_frame_messenger = MessageBox(user_frame, "")
        user_frame_messenger.grid(row=3, column=0, columnspan=3, sticky='nsew')
        user_frame_messenger.update_content(user_frame, "Saving user changes to database - one moment")
        # Save Process
        changes = record_changes()
        client = MongoClient('mongodb+srv://xxxxxx.zzyri.mongodb.net/test?')
        db = client['football_data']
        collection = db['users']
        for key in changes[1]:
            collection.update_one({"_id": ObjectId(changes[0])},
                                  {"$set": {key: changes[1][key]}}
                                  )
        # Notify user of process completion
        user_frame_messenger.destroy()
        messagebox.showinfo("User detail updated",
                            "The changes to the user details have been saved")
        user_frame.grid_forget()
        cancel_revert_process()
        _editable = False

    def make_editable_process(_editable):

        f_name.entry.config(state='normal')
        l_name.entry.config(state='normal')
        email.entry.config(state='normal')
        _editable = True
        edit_save_btn.config(text="Save", state='disabled', bg='gray80')

    def key_pressed(event):
        if changes_made():
            cancel_btn.config(text="Revert")
            edit_save_btn.config(state='normal', bg="#43E082")
        else:
            cancel_btn.config(text="Cancel")
            edit_save_btn.config(state='disabled', bg='gray80')

    # Record data of selected user
    user = user_lst.tree.focus()
    user_data = user_lst.tree.item(user)
    user_id = user_data['values'][0]

    # Create objects
    f_name = LabelEntryCombo(user_frame, "First name:")
    l_name = LabelEntryCombo(user_frame, "Last name:")
    email = LabelEntryCombo(user_frame, "Email:")
    cancel_btn = ColourSchemedButton(user_frame, "PaleGreen", "Cancel")
    edit_save_btn = ColourSchemedButton(user_frame, "GreenBlue", "Edit", state='normal')

    # Fill entry boxes
    fill_entry_boxes()

    # Bind objects
    f_name.entry.bind('<KeyRelease>', lambda e: key_pressed(e))
    l_name.entry.bind('<KeyRelease>', lambda e: key_pressed(e))
    email.entry.bind('<KeyRelease>', lambda e: key_pressed(e))
    cancel_btn.config(command=cancel_revert_process)
    edit_save_btn.config(command=lambda e=event, d=editable: save_or_edit(e, d))

    # Place and removal of objects
    close_btn.grid_forget()
    user_detail_frame.grid(row=2, columnspan=3, padx=10, pady=10, sticky='NW')
    f_name.frame.grid(row=0, columnspan=3, pady=10, padx=10)
    l_name.frame.grid(row=1, columnspan=3, pady=10, padx=10)
    email.frame.grid(row=2, columnspan=3, pady=10, padx=10)
    cancel_btn.grid(row=3, column=1, pady=10, padx=10)
    edit_save_btn.grid(row=3, column=2, pady=10, padx=10)

    # Configure grid
    user_detail_frame.grid_columnconfigure(0, weight=1)
    user_detail_frame.grid_columnconfigure(1, weight=0)
    user_detail_frame.grid_columnconfigure(2, weight=0)

    # Set state of  objects
    f_name.entry.config(state='disabled')
    l_name.entry.config(state='disabled')
    email.entry.config(state='disabled')

जैसा कि आप उठा सकते हैं - मैं एक लैम्ब्डा फ़ंक्शन का उपयोग करके निम्नलिखित कॉन्फ़िगरेशन के साथ save_edit_btn को बांधता हूं जो एक स्टेट हैंडलर edit_save_btn.config(command=lambda e=event, d=editable: save_or_edit(e, d)) के रूप में उपयोग किए जाने वाले editable वेरिएबल को पास करता है।

वह editable वेरिएबल इस फ़ंक्शन के बाहर गलत के रूप में इनिशियलाइज़ किया गया है और सबसे ऊपर फ़ंक्शन display_selected_user() (मुख्य प्रोग्राम से कॉलबैक फ़ंक्शन यदि आप करेंगे) को पास किया गया है। इसलिए जब save_edit_btn दबाया जाता है तो फ़ंक्शन प्रविष्टियों को सक्रिय बनाता है और अन्य विजेट्स को तदनुसार बदलता है (फ़ंक्शन make_editable_process() के अनुसार) और editable वेरिएबल को ट्रू में बदल देता है (यहां तक ​​कि मुख्य प्रोग्राम में भी जहां इसे शुरू किया गया था)

समस्या यह है कि उसके बाद प्रक्रिया लैम्ब्डा लाइन पर वापस जाती है और editable वेरिएबल को वापस गलत पर रीसेट करती है - मुझे समझ में नहीं आता क्यों - और परिणामस्वरूप save_process() को कभी भी इनिशियलाइज़ नहीं किया जा सकता है।

ऐसा क्यों है इस पर किसी भी विचार की सराहना की जाएगी - कृपया मुझे बताएं कि क्या आपको किसी और कोड या विवरण की आवश्यकता है।

0
Ruben Ferreira 21 अप्रैल 2021, 15:46

2 जवाब

सबसे बढ़िया उत्तर

True/False, संख्याओं, स्ट्रिंग्स जैसे मानों के लिए पायथन अपना मान फ़ंक्शन (या अन्य चर) को भेजता है - चर के संदर्भ में नहीं।

उदाहरण के लिए:

 a = False 
 _editable = a 
 _editable = True
 print(a) 

और a अभी भी False है, True नहीं।

इसके लिए आप tkinter में tkinter.BooleanVar() का प्रयोग करेंगे।

 import tkinter as tk

 a = tk.BooleanVar(value=False)
 # a.set(False)
 _editable = a 
 _editable.set(True)
 print(a.get())

और अब a जब आप _editable बदलते हैं तो मान बदल जाता है

मान प्राप्त करने के लिए .get() और मान सेट करने के लिए = के बजाय .set() का उपयोग करना याद रखें।


संपादित करें:

अन्य स्थितियों में आपको return का उपयोग करना होगा और परिणाम को वापस चर पर असाइन करना होगा

def function(_editable):
    # ... code ...

    _editable = True

    return _editable

a = False
a = function(a)  # assign returned value to `a`
print(a)

लेकिन जब फ़ंक्शन को बटन (या bind(), या after()) में असाइन किया जाता है, तो इसे लौटाया गया मान और असाइन नहीं किया जा सकता है वेरिएबल पर वापस - और फिर आमतौर पर हम वैश्विक का उपयोग सीधे बाहरी वेरिएबल के मान को परखने के लिए करते हैं

def function(_editable):
    global a

    # ... code ...

    _editable = True
    a = _editable


a = False
function(a)  # without assignig returned value 
print(a)
0
furas 21 अप्रैल 2021, 18:05

कोई भी परिवर्तन जो आप स्थानीय चर में करते हैं, जैसे कि make_editable_process में _editable, केवल उस फ़ंक्शन के अंदर दिखाई देता है, इसलिए उस परिवर्तन को बाहर देखें, आपको या तो इसे वापस करने की आवश्यकता है, दिए गए फ़ंक्शन के लिए कुछ बाहरी में सहेजें परिवर्तनशील वस्तु (जैसे वे विभिन्न बटन चीज़ ), या इसे global या के रूप में घोषित करें nonlocal

आपके मामले के लिए मुझे लगता है कि गैर-स्थानीय पर्याप्त होगा।

उदाहरण

आप जो प्रयोग कर रहे हैं वह यह है

>>> def fun():
        a=5
        def f():
            a=42
        print(a)
        f()
        print(a)


>>> fun()
5
5
>>>

a में f f के लिए एक स्थानीय चर है, इसमें कोई भी परिवर्तन केवल अंदर दिखाई देता है, इसे बाहर बदलने के लिए पहले बताए गए तरीकों में से कोई भी करें, उदाहरण के लिए गैर-स्थानीय के साथ:

>>> def fun2():
        a=5
        def f():
            nonlocal a
            a=42
        print(a)
        f()
        print(a)


>>> fun2()
5
42
>>> 
1
Copperfield 21 अप्रैल 2021, 16:41