-1

I have the code below :

def update_contact_from_crm_to_import_in_365():

sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
search_result = my_cursor.execute(sql)
search_result = my_cursor.fetchall()
sql_result.clear()
sql_result.append(search_result)

Filter(sql_result[0])

# Get id of sql result to pass them
list_get_selected_id.clear()
for res in (sql_result):
    for id in (res):
        list_get_selected_id.append(id[0])


time.sleep(5)

validate1 = messagebox.askquestion("Update ?", "Launch update ?")
if validate1 == 'yes':
    open_dynamics_365_full_contact_list()

My problem is that the Filter(sql_result[0]) seems to start at the very end of the update_contact_from_crm_to_import_in_365 function (after the messagebox)

So far, when i call update_contact_from_crm_to_import_in_365() it display the messagebox and once it has been answered then it call Filter().

But i would like to call Filter, wait 5 secondes for Filter to proceed and end, and then display the messagebox.

How do i do that please ?

I read about Threading but i'm just a beginner in Python so it's a bit complicated for me to get it yet.

Thanks in advance

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
Nico44044
  • 125
  • 8
  • 1
    what does Filter do? Can you post its code in the OP? – tstoev Jun 10 '21 at 12:44
  • if it is `tkinter` then you could use `root.after(5000, function_name)` to run function after 5000ms (5s). And `function_name` means function's name without `()` (so called `callback`) – furas Jun 10 '21 at 14:54
  • you have wrong indentations so we can't say how this code works. Edit question, put code again, select code and use `Ctrl+K` to correctly format code. – furas Jun 10 '21 at 14:54
  • @tstoev : Filter() is actually taking the result of the SQL query to feed a widget (tk.treeview). So far everything works fine but the treeview only refresh after the messagebox has been answered. It's as if the messagebox is stoping the code from runing in background. But since the Filter() call is before the messagebox i don't get why ... – Nico44044 Jun 10 '21 at 15:02
  • @furas: Thanks for your reply but i'm trying to do the opposite, i dont want to delay the Filter() calling, was trying to give it some time to proceed but the pop up messagebox windows appears almost instantly when i call update_contact_from_crm_to_import_in_365. – Nico44044 Jun 10 '21 at 15:05
  • use `after` to run message after 5 second. OR you should show correct code because `tkinter` first runs function and later update widgets in window - so your filter may run correctly but message blocks `mainloop` to update window in correct moment. OR use `root. update()` after filter to force `mainloop` to update widgets in window. – furas Jun 10 '21 at 15:10

1 Answers1

0

I can't run it but problem can be that mainloop first runs function update_contact_from_crm_to_import_in_365 and it waits for it end and later it updates widgets in widow. This way it can update all widgets in one moment so window less flicker.

In your situation you can have two solutions

  1. You can use root.after(5000, function_with_message) instead of sleep() and then update_contact_from_crm_to_import_in_365 will finish work and it will go back to mainloop which will update widgets - and after 5000ms it will run function_with_message.

    def show_message():
        validate1 = messagebox.askquestion("Update ?", "Launch update ?")
        if validate1 == 'yes':
            open_dynamics_365_full_contact_list()
    
    def update_contact_from_crm_to_import_in_365():
    
        sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
        search_result = my_cursor.execute(sql)
        search_result = my_cursor.fetchall()
        sql_result.clear()
        sql_result.append(search_result)
    
        Filter(sql_result[0])
    
        # Get id of sql result to pass them
        list_get_selected_id.clear()
        for res in (sql_result):
            for id in (res):
                list_get_selected_id.append(id[0])
    
        root.after(5000, show_message)
        #root.after(1, show_message) # it will no need to wait so long.
    
  2. You can use root.update() after Filter() to force mainloop to update widgets before end of function.

    def update_contact_from_crm_to_import_in_365():
    
        sql = "SELECT * FROM CRM_PRIMARY WHERE copy_to_365 = 'To update' ORDER BY CRM_PRIMARY.id DESC"
        search_result = my_cursor.execute(sql)
        search_result = my_cursor.fetchall()
        sql_result.clear()
        sql_result.append(search_result)
    
        Filter(sql_result[0])
    
        # Get id of sql result to pass them
        list_get_selected_id.clear()
        for res in (sql_result):
            for id in (res):
                list_get_selected_id.append(id[0])
    
        root.update()  # force tkinter to update widgets in window
        #time.sleep(5)
    
        validate1 = messagebox.askquestion("Update ?", "Launch update ?")
        if validate1 == 'yes':
            open_dynamics_365_full_contact_list()
    

In both situations you can use smaller values because it will run it after updating widgets so it doesn't need time for this.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
furas
  • 134,197
  • 12
  • 106
  • 148