'I need to understand why my tkinter code is implicitly running my bluetooth code without tkinter widget event occuring

It is unclear to me why my tkinter code used to present a top-level tkinter sub-screen called "connect screen" changes in its cosmetic display since I added my bluetooth code to this GUI program. Moreover, when you click on the "connect screen" button in the "main menu" screen and it spawns the top-level screen, this program will implicitly start scanning for bluetooth devices without clicking on the "scan button".

I would love to know why this above functionality is occurring I have zero idea as to why. The only documentation I have found about the potentially issue of this underlying problems was found at this website: https://gordonlesti.com/use-tkinter-without-mainloop/

I am extra curious as to know the underlying issues of this code. Moreover, potential fixes.

My Bluetooth code is below

import bluetooth



class AFLBBluetooth:
    def __init__(self):
        self.names_of_near_by_devices = []
        self.address_of_near_by_devices = []
        self.num_of_devices = 0
        self.r_port = 1                      
        self.backlog = 1




    def isolate_device_data(self, devices):
        """

        :param devices:
        :return:
        """
        for data in devices:
            self.address_of_near_by_devices.append(str(data[0]))
            self.names_of_near_by_devices.append(str(bluetooth.lookup_name(data[1])))



    def look_for_devices(self):
        """

        :return:
        """
        nearby_devices = bluetooth.discover_devices(lookup_names=True)
        self.num_of_devices = len(nearby_devices)
        self.isolate_device_data(nearby_devices)



    def bind(self, socket, mac_address):

        trys = 3
        while trys > 0:
            try:
                socket.bind(mac_address, self.r_port)
                return 1

            except bluetooth.btcommon.BluetoothError:
                trys = trys - 1
                self.r_port = self.r_port + 1
                continue

        return 0

    def receive_messages(self, target_bluetooth_mac_address):

        client = ""  # this initialization has no affect on the code, just to satisfy the python interpreter.

        size = 1024
        s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
        if self.bind(s, target_bluetooth_mac_address) > 0:
            s.listen(self.backlog)
            try:
                client, clientInfo = s.accept()
                while 1:
                    data = client.recv(size)
                    if data:
                        print(data)        # test to see if data was received
                        client.send(data)  # Echo back to client
            except bluetooth.btcommon.BluetoothError:
                client.close()
                s.close()

My tkinter code is below

import tkinter as tk
import threading
import bot_blue


class UnlockWindow:
    def __init__(self, master):
        self.m = master
        self.win = tk.Toplevel(self.m)
        self.setup_unlock_screen()



    def setup_unlock_screen(self):
        """

        :return:
        """
        self.win.title("Unlock Screen")
        self.win.geometry("480x320")  # Size of the window
        self.win.resizable(False, False)
        self.win.maxsize(480, 320)
        self.win.minsize(480, 320)
        self.create_buttons_for_screen()


    def create_buttons_for_screen(self):
        """
        This function creates the functionality for each button in the main menu screen. It specifies the size,
        padding, name, and function for each button in the container of the main menu widget screen.
        """

        # setting up frames
        text_frame = tk.Frame(self.win)
        num_frame = tk.Frame(self.win)
        action_frame = tk.Frame(self.win)


        # packing each frame into the parent widget 'unlock_root[0]'
        text_frame.pack(side=tk.TOP,  expand=tk.YES)
        num_frame.pack(side=tk.LEFT, expand=tk.YES)
        action_frame.pack(side=tk.RIGHT, expand=tk.YES)
        #
        # text entry for displaying button presses in unlock screen
        e = tk.Entry(text_frame, width=30, font=('arial', 18, 'bold'), fg="white", bg='#567', bd=5, )
        bdin = 2
        num_w = 10
        act_w = 10
        num_h = 3
        act_h = 4
        # num frame buttons
        # The first row will comprise of the buttons '7', '8' , '9'
        b7 = tk.Button(num_frame, text="7", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(7, e))
        b8 = tk.Button(num_frame, text="8", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(8, e))
        b9 = tk.Button(num_frame, text="9", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(9, e))

        # The third row will comprise of the buttons '4', '5', '6'
        b4 = tk.Button(num_frame, text="4", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(4, e))
        b5 = tk.Button(num_frame, text="5", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(5, e))
        b6 = tk.Button(num_frame, text="6", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(6, e))

        # The third row will comprise of the buttons '1', '2', '3'
        b1 = tk.Button(num_frame, text="1", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(1, e))
        b2 = tk.Button(num_frame, text="2", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(2, e))
        b3 = tk.Button(num_frame, text="3", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(3, e))

        # the forth row will comprise of the buttons  '0', 'backspace', 'clear'
        b0 = tk.Button(num_frame, text="0", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.do_num_button(0, e))
        bback = tk.Button(num_frame, text="<-", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.back_space(e))
        bclear = tk.Button(num_frame, text="C", fg="white",  bg='#567', width=num_w, height=num_h, bd=bdin, command=lambda: self.clear_button(e))

        # action frame buttons
        bUn = tk.Button(action_frame, fg="white", bg='#567', text="Unlock\nLid", width=act_w, height=act_h, command="")
        bMain = tk.Button(action_frame,  fg="white", bg='#567', text="Main Menu",width=act_w, height=act_h, command=self.return_to_main_menu)

        # setting the geometry of each row
        # row 1
        e.grid(row=0, column=0, columnspan=3)

        # row 2
        b7.grid(row=0, column=0)
        b8.grid(row=0, column=1)
        b9.grid(row=0, column=2)

        # row 3
        b4.grid(row=1, column=0)
        b5.grid(row=1, column=1)
        b6.grid(row=1, column=2)

        # row 4
        b1.grid(row=2, column=0)
        b2.grid(row=2, column=1)
        b3.grid(row=2, column=2)

        # row 5
        bclear.grid(row=3, column=0)
        b0.grid(row=3, column=1)
        bback.grid(row=3, column=2)

        # action buttons in action frame grid placement
        bUn.grid(row=0, column=0)
        bMain.grid(row=1, column=0)


    def return_to_main_menu(self):
        """

        :return:
        """
        self.win.destroy()


    def unlock_button(self, container):
        """

        :return:
        """
        current = container.get()
        if len(current) < 4:
            return



    def clear_button(self, container):
        """

        :param container:
        :return:
        """
        container.delete(0, tk.END)

    def back_space(self, container):
        """

        :param container:
        :return:
        """
        current = container.get()
        new_length = len(current) - 1
        container.delete(new_length, tk.END)

    def do_num_button(self, button_function, container):
        """ Function is the action taken by a number button in the Unlock Screen GUI """
        current = container.get()
        if len(current) >= 10:
            return
        self.clear_button(container)
        container.insert(0, str(current) + str(button_function))

class ConnectScreen:
    def __init__(self, master):
        self.m = master
        self.win = tk.Toplevel(self.m)
        self.setup_connect_screen()



    def setup_connect_screen(self):
        """
        This function is called to initial all attributes for establishing the connect screen of the
        Auto Follow Locker Bot.
        """
        self.win.title("Connect Screen")
        self.win.geometry("480x320")  # Size of the window
        self.win.resizable(False, False)
        self.win.maxsize(480, 320)
        self.win.minsize(480, 320)
        self.put_buttons_on_screen()


    def return_to_main_menu(self):
        """

        :return:
        """
        self.win.destroy()



    def do_scan(self, list_box_container):
        """

        :param list_box_container:
        :return:
        """
        addrs, names = self.scan_for_devices()
        if not addrs:
            list_box_container.insert(0, "No Bluetooth Devices Found")
        else:
            for i in range(len(names)):
                list_box_container.insert(i, names[i] + " " + addrs[i])



    def scan_for_devices(self):
        """
        :return:
        """
        b = bot_blue.AFLBBluetooth()
        b.look_for_devices()
        if b.num_of_devices:
            return b.address_of_near_by_devices, b.names_of_near_by_devices
        return None, None


    def item_selected(self, listbox):
        """

        :return:
        """
        selected_bluetooth_device = listbox.curselection()
        if selected_bluetooth_device:
            return selected_bluetooth_device[1]
        return None




    def do_discovery(self):
        pass
        # b = bot_blue.AFLBBluetooth()
        # b.bluetooth_setup()


    def put_buttons_on_screen(self):
        """

        :return:
        """
        # creating appropriate frames for organization purposes of the connect screen GUI
        entry_frame = tk.Frame(self.win)
        button_frame = tk.Frame(self.win)
        xtra = tk.Frame(self.win)

        # positioning frames in a compositional way  as desired by the creator
        entry_frame.pack(side=tk.RIGHT,  expand=tk.YES)
        button_frame.pack(side=tk.LEFT, expand=tk.YES)
        xtra.pack(side=tk.TOP, expand=tk.YES)

        # creating a list box for displaying all bluetooth connection, device, metadata to connect screen
        connections = tk.Listbox(entry_frame, width=20, height=7, font=('arial', 18, 'bold'), fg="white", bg='#567', bd=5, selectmode='single')
        con_sbv = tk.Scrollbar(entry_frame, width=30, highlightcolor="white", bg='#567', bd=5, orient=tk.VERTICAL)
        con_sbh = tk.Scrollbar(entry_frame, width=30, highlightcolor="white", bg='#567', bd=5, orient=tk.HORIZONTAL)
        connections.bind('<<ListboxSelect>>', self.item_selected(connections))
        # configuring both horizontal and vertical scroll bars of the list box, so the user can scroll and see all
        # bluetooth devices in the area and their corresponding metadata
        connections.configure(yscrollcommand=con_sbv.set)
        connections.configure(xscrollcommand=con_sbh.set)
        con_sbv.config(command=connections.yview)
        con_sbh.config(command=connections.xview)


        # creating button widgets for functionality of the 'connect screen'  of the micro controller
        scan = tk.Button(button_frame, text="scan", fg="white",  bg='#567', width=8, height=5, bd=4,
                               command=threading.Thread(target=self.do_scan, args=[connections]).start())
        discover = tk.Button(button_frame, text="Make Discoverable", fg="white",  bg='#567', width=13, height=4, bd=4,
                             command=threading.Thread(target=self.do_discovery).start())
        main_m = tk.Button(button_frame, text="Main Menu", fg="white",  bg='#567', width=5, height=5, bd=4,
                           command=self.return_to_main_menu)

        # positioning 'list text widget' in the 'entry_frame'
        connections.grid(row=0, column=0)

        # positioning 'scroll bars' in the 'entry_frame'
        con_sbv.grid(row=0, column=1)
        con_sbh.grid(row=1, column=0)

        # positioning buttons 'disconnect', 'discover', 'back to main menu' in the button_frame
        discover.grid(row=0, column=0)
        scan.grid(row=1, column=0)
        main_m.grid(row=2, column=0)



class MainMenu:
    def __init__(self, master):
        self.master = master
        self.button_h = 3
        self.button_w = 10
        self.bdin = 4

    def setup_main_menu(self):
        """

        :return:
        """
        self.master.geometry("480x320")
        self.master.title("Auto Follow Locker Bot")
        self.master.resizable(False, False)
        self.master.maxsize(480, 320)
        self.master.minsize(480, 320)
        self.do_main_menu_screen()


    def do_main_menu_screen(self):
        """

        :return:
        """
        main_menu_label_frame = tk.Frame()
        buttons_frame = tk.Frame()
        xtra_buttons_frame = tk.Frame()

        main_menu_label_frame.pack(side=tk.TOP,  expand=tk.YES)
        buttons_frame.pack(side=tk.LEFT, expand=tk.YES)
        xtra_buttons_frame.pack(side=tk.RIGHT, expand=tk.YES)

        label1 = tk.Label(main_menu_label_frame, text="Main Menu", font=('arial', 16, 'bold'))
        label1.pack()

        un = tk.Button(buttons_frame, text="Unlock Screen", fg="white",  bg='#567', width=self.button_w,
                        height=self.button_h, bd=self.bdin, command=self.do_unlock_window)
        con = tk.Button(buttons_frame, text="Connect Screen", fg="white",  bg='#567', width=self.button_w,
                        height=self.button_h, bd=self.bdin, command=self.do_connect_window)
        ex = tk.Button(buttons_frame, text="Exit", fg="white",  bg='#567', width=self.button_w,
                        height=self.button_h, bd=self.bdin, command=exit)

        un.grid(row=0, column=0)
        con.grid(row=1, column=0)
        ex.grid(row=2, column=0)

    def do_unlock_window(self):
        doun = UnlockWindow(self.master)
        doun.win.mainloop()



    def do_connect_window(self):
        docon = ConnectScreen(self.master)
        docon.win.mainloop()





root = tk.Tk()
main = MainMenu(root)
main.setup_main_menu()
root.mainloop()


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source