Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

Python Family Tree-Add a new member window

saradis1

Coder
Hello. I would like to choose from the root1 the member and take it's ID of the member and put it in root window in the field "relation_with". I can't find how to go on or what to change to work.

Python:
from tkinter import *

from tkinter import messagebox

import tkinter as tk

import sqlite3



# Connection with my database

conn = sqlite3.connect('genealogy.db')



# Δημιουργία cursor για τα ερωτήματα

c = conn.cursor()



# Table creation

c.execute('''CREATE TABLE IF NOT EXISTS members

             (id INTEGER PRIMARY KEY,

             first_name TEXT NOT NULL,

             last_name TEXT NOT NULL,

             date_of_birth TEXT NOT NULL,

             relation TEXT NOT NULL,

             relation_with INTEGER)''')

# Sending Data

conn.commit()

# function for member input

def insert_member():

    # Get from the form

    first_name = entry_first.get()

    last_name = entry_last.get()

    date_of_birth = entry_dob.get()

    relation = relation_var.get()

    relation_with = entry_relation_with.get()

    # member's input in the database

    c.execute(

        'INSERT INTO members (first_name, last_name, date_of_birth, relation, relation_with) VALUES (?, ?, ?, ?, ?)',

        (first_name, last_name, date_of_birth, relation, relation_with))

    # Changes->sending

    conn.commit()

    # Clear my form after the input

    clear_form()



    # Succesful add

    messagebox.showinfo(title="Επιτυχής", message="Η καταχώρησή σας ήταν επιτυχής")

    root.destroy() #κλείσιμο του παραθύρου



# function Clear form

def clear_form():

    entry_first.delete(0, 'end')

    entry_last.delete(0, 'end')

    entry_dob.delete(0, 'end')



    entry_relation_with.delete(0, 'end')





# GUI

root = tk.Tk()

root.title("Γενεαλογικό Δέντρο-Εισαγωγή Μέλους")



#GUI Second Window for connection with "relationship_with"

root1= tk.Tk()

root1.title("Members to connect with relationship_with")

# root1.geometry("300x300") We can change it later...



#show all members in root1

# Create the listbox

listbox = tk.Listbox(root1)

listbox.pack()



# Retrieve all members from the database

c.execute("SELECT * FROM members")

members = c.fetchall()



# Loop through the members and add them to the listbox

for member in members:

    listbox.insert(tk.END, member)



def update_entry_relation_with(member_id):

    entry_relation_with.delete(0, tk.END)  # Clear any existing value in the entry

    entry_relation_with.insert(0, member_id)  # Insert the selected member's ID in the entry



def select_member():

    global member_id

    selected_member = listbox.get(tk.ACTIVE)  # Get the selected member

    member_id = selected_member[0]  # the first column contains the member's ID





# Δημιουργία Labels και entries (root)

lbl_id = tk.Label(root, text="ID:")

lbl_id.grid(row=0, column=0, padx=10, pady=5)

entry_id = tk.Entry(root, state='disabled')

entry_id.grid(row=0, column=1, padx=10, pady=5)

lbl_first = tk.Label(root, text="Name:")

lbl_first.grid(row=1, column=0, padx=10, pady=5)

entry_first = tk.Entry(root)

entry_first.grid(row=1, column=1, padx=10, pady=5)

lbl_last = tk.Label(root, text="Last name:")

lbl_last.grid(row=2, column=0, padx=10, pady=5)

entry_last = tk.Entry(root)

entry_last.grid(row=2, column=1, padx=10, pady=5)

lbl_dob = tk.Label(root, text="Date of birthday:")

lbl_dob.grid(row=3, column=0, padx=10, pady=5)

entry_dob = tk.Entry(root)

entry_dob.grid(row=3, column=1, padx=10, pady=5)



lbl_relation = tk.Label(root, text="Σχέση:")

lbl_relation.grid(row=4, column=0, padx=10, pady=5)

relation_var = StringVar(root)

relation_var.set("Relatioship:")

entry_relation = OptionMenu(root, relation_var, "Father", "Mother", "Child", "Grandpa")

entry_relation.grid(row=4, column=1, padx=10, pady=5)



lbl_relation_with = tk.Label(root, text="Relationship with the ID:")

lbl_relation_with.grid(row=5, column=0, padx=10, pady=5)

entry_relation_with = tk.Entry(root)

entry_relation_with.grid(row=5, column=1, padx=10, pady=5)



#buttons root

btn_submit = tk.Button(root, text="Καταχώρηση", command=insert_member)

btn_submit.grid(row=6, column=0, padx=10, pady=5)

btn_clear = tk.Button(root, text="Καθαρισμός φόρμας", command=clear_form)

btn_clear.grid(row=6, column=1, padx=10, pady=5)



#button root1

button_select_member = tk.Button(root1, text="Select member", command=select_member)

button_select_member.pack()





#Show The ID

c.execute('SELECT MAX(id) FROM members')

max_id = c.fetchone()[0]

if max_id is None:

    max_id = 0

entry_id.config(state='normal')

entry_id.delete(0, 'end')

entry_id.insert(0, str(max_id+1))

entry_id.config(state='disabled')



#Start root

root.mainloop()



#Start root1

root1.mainloop()





#Close connection

conn.close()
 
Last edited by a moderator:
I finally managed to do it.
I had forgotten that i should had used the method StringVar.
Python:
relation_with_var = tk.StringVar()
lbl_relation_with = tk.Label(root, text="Σχέση με ID:")
lbl_relation_with.grid(row=5, column=0, padx=10, pady=5)
entry_relation_with = tk.Entry(root, textvariable=relation_with_var)
entry_relation_with.grid(row=5, column=1, padx=10, pady=5)

I also made a fuction that shows all the members of the database and one that isolates the id in a variable.
Python:
    def connect_with():

        selected = listbox.curselection()


        selected_member = members[selected[0]] #απομόνωση του ID
        entry_relation_with.delete(0, 'end')
        entry_relation_with.insert(0, str(selected_member[0]))

    btn_connect = tk.Button(root1, text="Σύνδεση με το ID του επιλεγμένου μέλους", command=connect_with)
    btn_connect.pack()

    # pack listbox and button
    listbox.pack()
 
That's great. I've started the approach I would take. I will finished when I get home from work tomorrow. I'm using classes with the mvc approach.
What I have so far. I do not know what the button labels are in your form as I can't read the language.

Python:
import sqlite3
import tkinter as tk
from tkinter import messagebox

class Model:
    def __init__(self):
        self.db = 'genealogy.db'

    def create_db(self):
        conn = sqlite3.connect(self.db)
        conn.execute('''
            create table if not exists members (
            id integer primary key autoincrement,
            fname varchar(120) not null,
            lname varchar(120) not null,
            birth varchar(120) not null,
            relation varchar(120) not null,
            relation_id integer
            )
        ''')

    def insert(self, *data):
        conn = sqlite3.connect(self.db)

        conn.execute('''
            insert into members (fname, lname, birth, relation, relation_id) values (?,?,?,?,?)
        ''', data)

        conn.commit()

    def _get(self):
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()
        cursor.execute('select * from members')
        result = cursor.fetchall()
        return result

class View:
    def __init__(self, parent):
        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)

        container = tk.Frame(parent)
        container.grid(column=0, row=0, sticky='news', padx=5, pady=5)
        container.grid_columnconfigure(0, weight=3, uniform='split')
        container.grid_columnconfigure(1, weight=3, uniform='split')
        container.grid_rowconfigure(0, weight=3)

        self.listbox = tk.Listbox(container)
        self.listbox.grid(column=0, row=0, sticky='news')

        form_container = tk.Frame(container, padx=5, pady=5)
        form_container['borderwidth'] = 1
        form_container['highlightbackground'] = 'gray'
        form_container['highlightcolor'] = 'gray'
        form_container['highlightthickness'] = 1
        form_container.grid(column=1, row=0, sticky='news')
        form_container.grid_columnconfigure(1, weight=3)

        id_label = tk.Label(form_container, text='ID', anchor='w')
        id_label.grid(column=0, row=0, sticky='new', pady=2)
        self.id = tk.Entry(form_container, text='')
        self.id.grid(column=1, row=0, sticky='new', pady=2)
        self.id['state'] = 'readonly'

        fname_label = tk.Label(form_container, text='First Name', anchor='w')
        fname_label.grid(column=0, row=1, sticky='new', pady=2)
        self.fname_entry = tk.Entry(form_container)
        self.fname_entry.grid(column=1, row=1, sticky='new', pady=2)

        lname_label = tk.Label(form_container, text='Last Name', anchor='w')
        lname_label.grid(column=0, row=2, sticky='new', pady=2)
        self.lname_entry = tk.Entry(form_container)
        self.lname_entry.grid(column=1, row=2, sticky='new', pady=2)

        birth_label = tk.Label(form_container, text='Date of Birth', anchor='w')
        birth_label.grid(column=0, row=3, sticky='new', pady=2)
        self.birth_entry = tk.Entry(form_container)
        self.birth_entry.grid(column=1, row=3, sticky='new', pady=2)

        relation_label = tk.Label(form_container, text='Relations', anchor='w')
        relation_label.grid(column=0, row=4, sticky='new', pady=2)
        relation = tk.StringVar(value='Father')
        kin = ('Father', 'Mother', 'Child', 'Grandpa', 'Grandma')
        self.relation = tk.OptionMenu(form_container, relation, *kin)
        self.relation.grid(column=1, row=4, sticky='new', pady=2)

        rid = tk.Label(form_container, text='Relations ID', anchor='w')
        rid.grid(column=0, row=5, sticky='new', pady=2)
        self.rid = tk.Entry(form_container)
        self.rid.grid(column=1, row=5, sticky='new', pady=2)






class Controller:
    def __init__(self, model, view):
        self.model = model
        self.view = view

        self.populate()

    def populate(self):
        people = self.model._get()
        for index, person in enumerate(people):
            self.view.listbox.insert(index, person)


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('800x600+300+300')
    controller = Controller(Model(), View(root))
    root.mainloop()
 
Last edited:
I redone the code as your original code was using two windows. This has a main window, when highlighting an entry and clicking the button or double left click and entry, a new window will open with the form. when the submit button on the form is clicked, the window will be destroyed and you will return to the main window. There is no error checking of any kind in the script. The script assumes that there is already at least one entry in the database.

Python:
import sqlite3
import tkinter as tk
from tkinter import messagebox

class Model:
    '''
    The model class will handle all of the database queries
    '''
    def __init__(self):
        self.db = 'genealogy.db'

    def create_db(self):
        conn = sqlite3.connect(self.db)
        conn.execute('''
            create table if not exists members (
            id integer primary key autoincrement,
            fname varchar(120) not null,
            lname varchar(120) not null,
            birth varchar(120) not null,
            relation varchar(120) not null,
            relation_id integer
            )
        ''')

    def insert(self, *data):
        '''
        insert method will insert data from the form
        '''
        conn = sqlite3.connect(self.db)

        conn.execute('''
            insert into members (fname, lname, birth, relation, relation_id) values (?,?,?,?,?)
        ''', data)

        conn.commit()

    def _get(self):
        '''
        _get pulls all entries from database for the listbox
        '''
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()
        cursor.execute('select * from members')
        result = cursor.fetchall()
        return result
   
    def get_count(self):
        '''
        get_count gets total number of entries in database
        '''
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()
        cursor.execute('select max(id) from members')
        result = cursor.fetchone()[0]
        return result

   
class View(tk.Listbox):
    '''
    View class is the display window with the listbox
    Can highlight an entry and double left click or use
    the button to bring up toplevel window
    '''
    def __init__(self, parent, *args, **kwargs):
        self.parent = parent
        super().__init__(*args, **kwargs)
       
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        self.listbox = tk.Listbox(parent)
        self.listbox['font'] = (None, 12, 'normal')
        self.listbox['selectmode'] = 'single'
        self.listbox.grid(column=0, row=0, sticky='news')

        self.button = tk.Button(parent, text='Submit')
        self.button['font'] = (None, 12, 'bold')
        self.button.grid(column=0, row=1, sticky='nw', pady=10)


class Window(tk.Toplevel):
    '''
    Window class is a toplevel window with the form
    '''
    def __init__(self, id, parent, population, *args, **kwargs):
        '''
        self.model is used for getting a count of entries
        self.pop is for refreshing the listbox on returning to the window
        '''
        self.model = Model()
        self.population = population
        super().__init__(*args, *kwargs)
        self.parent = parent
        self.geometry('400x200+250+250')
        self.resizable(False, False)
        self.title('My Window')
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        frame = tk.Frame(self, padx=5, pady=5)
        frame.grid(column=0, row=0, sticky='news')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_columnconfigure(1, weight=3)

        # id is for the entry count + one
        id = self.model.get_count() + 1

        # Created a dict for the labels/headers of the form
        label = {
            'ID': None, 'First Name': None, 'Last Name': None, 'Birth': None,
            'Relations': None, 'Relations ID':None
        }

        # i for counting to place widget rows
        i = 0
        for key in label.keys():
            heading = tk.Label(frame, text=key, anchor='w')
            heading['font'] = (None, 10, 'bold')
            heading.grid(column=0, row=i, sticky='new', padx=2, pady=2)

            # Setup the entry fields and variables
            entry = tk.Entry(frame)
            value = tk.StringVar()
            entry['textvariable'] = value
            label[key] = value

            # If the key is our ID  label disable
            if key == 'ID':
                entry.delete(0, tk.END)
                entry.insert(0, id)
                entry['state'] = 'readonly'
            entry.grid(column=1, row=i, sticky='new', padx=2, pady=2)
            i += 1
       
        self.button = tk.Button(frame, text='Submit')
        self.button['font'] = (None, 10, 'bold')
        self.button['bg'] = 'gray90'
        self.button.grid(columnspan=2, column=0, row=len(label), sticky='ew', pady=5)

        # Bind button to functions for highlighting on hover and to button command
        self.button.bind('<Enter>', self.on_enter)
        self.button.bind('<Leave>', self.on_exit)
        self.button['command'] = lambda :self._add(label)

        # This for when using the window x button to close
        # Will deiconify the main window
        self.protocol('WM_DELETE_WINDOW', self.close)

    # Method for destroying form window and deiconify main window
    def close(self):
        self.destroy()
        self.parent.deiconify()

    # Change color of button on hover
    def on_enter(self, event):
        self.button['fg'] = 'blue'
        self.button['bg'] = 'gray85'

    # Return button color on exiting button
    def on_exit(self, event):
        self.button['fg'] = 'black'
        self.button['bg'] = 'gray90'

    # Get all form data, pop the first entry off as it will be added when data
    # is inserted to database. Destroy form window and deiconify main window
    # self.pop will refrest listbox on main window
    def _add(self, *args):
        alist = []
        for value in args[0].values():
            alist.append(value.get())
        alist.pop(0)
        self.model.insert(*alist)
        self.destroy()
        self.parent.deiconify()
        self.population()


class Controller:
    '''
    Controller class handles communications between our classes and methods
    '''
    def __init__(self, model, view):
        '''
        Set instant variables, button commands, and populate the listbox
        '''
        self.model = model
        self.view = view

        self.view.button['command'] = self._window
        self.view.listbox.bind('<Double-1>', self._window)

        self.populate()

    # Function for populating the listbox
    def populate(self):
        self.view.listbox.delete(0, tk.END)
        people = self.model._get()
        for index, person in enumerate(people):
            self.view.listbox.insert(index, person)
        self.view.listbox.selection_set(0)

    # Function opens our form window
    def _window(self, event=None):
        for i in self.view.listbox.curselection():
            id = self.view.listbox.get(i)[0]
        self.view.parent.iconify()
        Window(id, self.view.parent, self.populate)



if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('800x600+350+350')
    root['padx'] = 5
    root['pady'] = 5
    controller = Controller(Model(), View(root))
    controller.model.create_db()
    root.mainloop()
 
Last edited:
I redone the code as your original code was using two windows. This has a main window, when highlighting an entry and clicking the button or double left click and entry, a new window will open with the form. when the submit button on the form is clicked, the window will be destroyed and you will return to the main window. There is no error checking of any kind in the script. The script assumes that there is already at least one entry in the database.

Python:
import sqlite3
import tkinter as tk
from tkinter import messagebox

class Model:
    '''
    The model class will handle all of the database queries
    '''
    def __init__(self):
        self.db = 'genealogy.db'

    def create_db(self):
        conn = sqlite3.connect(self.db)
        conn.execute('''
            create table if not exists members (
            id integer primary key autoincrement,
            fname varchar(120) not null,
            lname varchar(120) not null,
            birth varchar(120) not null,
            relation varchar(120) not null,
            relation_id integer
            )
        ''')

    def insert(self, *data):
        '''
        insert method will insert data from the form
        '''
        conn = sqlite3.connect(self.db)

        conn.execute('''
            insert into members (fname, lname, birth, relation, relation_id) values (?,?,?,?,?)
        ''', data)

        conn.commit()

    def _get(self):
        '''
        _get pulls all entries from database for the listbox
        '''
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()
        cursor.execute('select * from members')
        result = cursor.fetchall()
        return result
 
    def get_count(self):
        '''
        get_count gets total number of entries in database
        '''
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()
        cursor.execute('select max(id) from members')
        result = cursor.fetchone()[0]
        return result

 
class View(tk.Listbox):
    '''
    View class is the display window with the listbox
    Can highlight an entry and double left click or use
    the button to bring up toplevel window
    '''
    def __init__(self, parent, *args, **kwargs):
        self.parent = parent
        super().__init__(*args, **kwargs)
   
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        self.listbox = tk.Listbox(parent)
        self.listbox['font'] = (None, 12, 'normal')
        self.listbox['selectmode'] = 'single'
        self.listbox.grid(column=0, row=0, sticky='news')

        self.button = tk.Button(parent, text='Submit')
        self.button['font'] = (None, 12, 'bold')
        self.button.grid(column=0, row=1, sticky='nw', pady=10)


class Window(tk.Toplevel):
    '''
    Window class is a toplevel window with the form
    '''
    def __init__(self, id, parent, population, *args, **kwargs):
        '''
        self.model is used for getting a count of entries
        self.pop is for refreshing the listbox on returning to the window
        '''
        self.model = Model()
        self.population = population
        super().__init__(*args, *kwargs)
        self.parent = parent
        self.geometry('400x200+250+250')
        self.resizable(False, False)
        self.title('My Window')
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        frame = tk.Frame(self, padx=5, pady=5)
        frame.grid(column=0, row=0, sticky='news')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_columnconfigure(1, weight=3)

        # id is for the entry count + one
        id = self.model.get_count() + 1

        # Created a dict for the labels/headers of the form
        label = {
            'ID': None, 'First Name': None, 'Last Name': None, 'Birth': None,
            'Relations': None, 'Relations ID':None
        }

        # i for counting to place widget rows
        i = 0
        for key in label.keys():
            heading = tk.Label(frame, text=key, anchor='w')
            heading['font'] = (None, 10, 'bold')
            heading.grid(column=0, row=i, sticky='new', padx=2, pady=2)

            # Setup the entry fields and variables
            entry = tk.Entry(frame)
            value = tk.StringVar()
            entry['textvariable'] = value
            label[key] = value

            # If the key is our ID  label disable
            if key == 'ID':
                entry.delete(0, tk.END)
                entry.insert(0, id)
                entry['state'] = 'readonly'
            entry.grid(column=1, row=i, sticky='new', padx=2, pady=2)
            i += 1
   
        self.button = tk.Button(frame, text='Submit')
        self.button['font'] = (None, 10, 'bold')
        self.button['bg'] = 'gray90'
        self.button.grid(columnspan=2, column=0, row=len(label), sticky='ew', pady=5)

        # Bind button to functions for highlighting on hover and to button command
        self.button.bind('<Enter>', self.on_enter)
        self.button.bind('<Leave>', self.on_exit)
        self.button['command'] = lambda :self._add(label)

        # This for when using the window x button to close
        # Will deiconify the main window
        self.protocol('WM_DELETE_WINDOW', self.close)

    # Method for destroying form window and deiconify main window
    def close(self):
        self.destroy()
        self.parent.deiconify()

    # Change color of button on hover
    def on_enter(self, event):
        self.button['fg'] = 'blue'
        self.button['bg'] = 'gray85'

    # Return button color on exiting button
    def on_exit(self, event):
        self.button['fg'] = 'black'
        self.button['bg'] = 'gray90'

    # Get all form data, pop the first entry off as it will be added when data
    # is inserted to database. Destroy form window and deiconify main window
    # self.pop will refrest listbox on main window
    def _add(self, *args):
        alist = []
        for value in args[0].values():
            alist.append(value.get())
        alist.pop(0)
        self.model.insert(*alist)
        self.destroy()
        self.parent.deiconify()
        self.population()


class Controller:
    '''
    Controller class handles communications between our classes and methods
    '''
    def __init__(self, model, view):
        '''
        Set instant variables, button commands, and populate the listbox
        '''
        self.model = model
        self.view = view

        self.view.button['command'] = self._window
        self.view.listbox.bind('<Double-1>', self._window)

        self.populate()

    # Function for populating the listbox
    def populate(self):
        self.view.listbox.delete(0, tk.END)
        people = self.model._get()
        for index, person in enumerate(people):
            self.view.listbox.insert(index, person)
        self.view.listbox.selection_set(0)

    # Function opens our form window
    def _window(self, event=None):
        for i in self.view.listbox.curselection():
            id = self.view.listbox.get(i)[0]
        self.view.parent.iconify()
        Window(id, self.view.parent, self.populate)



if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('800x600+350+350')
    root['padx'] = 5
    root['pady'] = 5
    controller = Controller(Model(), View(root))
    controller.model.create_db()
    root.mainloop()

thanks a lot for your help.
While running, it appears a window to choose the member. However, it shows empty fields to be completed but it doens't transfer the ID of the selected member.
I am pasting my code. It works fine. Let me know what you think.

Python:
from tkinter import *
from tkinter import messagebox
import tkinter as tk
import sqlite3

# Συνδεση με τη βάση δεδομένων (ή με την υπάρχουσα)
conn = sqlite3.connect('genealogy.db')

# Δημιουργία cursor για τα ερωτήματα
c = conn.cursor()

# Δημιουργία του πίνακα δεδομένων (ακόμα και αν δεν υπάρχει ήδη)
c.execute('''CREATE TABLE IF NOT EXISTS members
             (id INTEGER PRIMARY KEY,
             first_name TEXT NOT NULL,
             last_name TEXT NOT NULL,
             date_of_birth TEXT NOT NULL,
             relation TEXT NOT NULL,
             relation_with INTEGER)''')
# Αποστολή δεδομένων
conn.commit()
# function για την εισαγωγή μελών
def insert_member():
    # Get τιμών απο τη φόρμα
    first_name = entry_first.get()
    last_name = entry_last.get()
    date_of_birth = entry_dob.get()
    relation = relation_var.get()
    relation_with = entry_relation_with.get()
    # Εισαγωγή του μέλους στη βάση δεδομένων
    c.execute(
        'INSERT INTO members (first_name, last_name, date_of_birth, relation, relation_with) VALUES (?, ?, ?, ?, ?)',
        (first_name, last_name, date_of_birth, relation, relation_with))
    # Αποστολή αλλαγών
    conn.commit()
    # Εκκαθάριση φόρμας μετά την εισαγωγή
    clear_form()

    # μήνυμα επιτυχούς καταχώρησης
    messagebox.showinfo(title="Επιτυχής", message="Η καταχώρησή σας ήταν επιτυχής")
    root.destroy() #κλείσιμο του παραθύρου





# function καθαρισμού φόρμας
def clear_form():
    entry_first.delete(0, 'end')
    entry_last.delete(0, 'end')
    entry_dob.delete(0, 'end')
    entry_relation_with.delete(0, 'end')


# GUI - Κύριο
root = tk.Tk()
root.title("Γενεαλογικό Δέντρο-Εισαγωγή Μέλους")



# Δημιουργία Labels και entries (root)
lbl_id = tk.Label(root, text="ID:")
lbl_id.grid(row=0, column=0, padx=10, pady=5)
entry_id = tk.Entry(root, state='disabled')
entry_id.grid(row=0, column=1, padx=10, pady=5)
lbl_first = tk.Label(root, text="Όνομα:")
lbl_first.grid(row=1, column=0, padx=10, pady=5)
entry_first = tk.Entry(root)
entry_first.grid(row=1, column=1, padx=10, pady=5)
lbl_last = tk.Label(root, text="Επώνυμο:")
lbl_last.grid(row=2, column=0, padx=10, pady=5)
entry_last = tk.Entry(root)
entry_last.grid(row=2, column=1, padx=10, pady=5)
lbl_dob = tk.Label(root, text="Ημερομηνία Γέννησης:")
lbl_dob.grid(row=3, column=0, padx=10, pady=5)
entry_dob = tk.Entry(root)
entry_dob.grid(row=3, column=1, padx=10, pady=5)


lbl_relation = tk.Label(root, text="Σχέση:")
lbl_relation.grid(row=4, column=0, padx=10, pady=5)
relation_var = StringVar(root)
relation_var.set("Σχέση:")
entry_relation = OptionMenu(root, relation_var, "Πατέρας", "Μητέρα", "Παιδί", "Εγγονός")
entry_relation.grid(row=4, column=1, padx=10, pady=5)

relation_with_var = tk.StringVar()
lbl_relation_with = tk.Label(root, text="Σχέση με ID:")
lbl_relation_with.grid(row=5, column=0, padx=10, pady=5)
entry_relation_with = tk.Entry(root, textvariable=relation_with_var)
entry_relation_with.grid(row=5, column=1, padx=10, pady=5)

#Κουμπιά
btn_submit = tk.Button(root, text="Καταχώρηση", command=insert_member)
btn_submit.grid(row=6, column=0, padx=10, pady=5)
btn_clear = tk.Button(root, text="Καθαρισμός φόρμας", command=clear_form)
btn_clear.grid(row=6, column=1, padx=10, pady=5)



#Εμφάνιση ID στην εισαγωγή μέλους
c.execute('SELECT MAX(id) FROM members')
max_id = c.fetchone()[0]
if max_id is None:
    max_id = 0
entry_id.config(state='normal')
entry_id.delete(0, 'end')
entry_id.insert(0, str(max_id+1))
entry_id.config(state='disabled')

# function to show the members in root1
def show_members():
    # get all members from the database
    c.execute('SELECT id, first_name,last_name FROM members')
    members = c.fetchall()

    # create listbox and add members to it
    listbox = tk.Listbox(root1,height=40,width=60)
    for member in members:
        listbox.insert(tk.END, f"{member[0]} - {member[1]}- {member[2]}")


    # add "connect with" button that sets the selected member's ID to the "relation_with" entry
    def connect_with():

        selected = listbox.curselection()


        selected_member = members[selected[0]] #απομόνωση του ID
        entry_relation_with.delete(0, 'end')
        entry_relation_with.insert(0, str(selected_member[0]))

    btn_connect = tk.Button(root1, text="Σύνδεση με το ID του επιλεγμένου μέλους", command=connect_with)
    btn_connect.pack()

    # pack listbox and button
    listbox.pack()


# create root1 window
root1 = tk.Toplevel()
root1.title("Όλα τα μέλη")


# show members in root1
show_members()

# start the mainloop for both windows
root.mainloop()
root1.mainloop()


#Κλείσιμο σύνδεσης
conn.close()
 
Last edited:
If your happy with it that's good. Still it's bad practice to have more than one mainloop.
Here is my final version of the code (uncommented)

Python:
import tkinter as tk
from tkinter import messagebox
import sqlite3

class Model:
    def __init__(self):
        self.database = 'genealogy.db'

    def connect(self):
        return sqlite3.connect(self.database)
       
    def create(self):
        connection = self.connect()
        connection.execute(
            '''
                create table if not exists members (
                id integer primary key autoincrement,
                fname text not null,
                lname text not null,
                birth text not null,
                relation text not null,
                relation_id integer not null
                )
            '''
        )

    def insert(self, data):
        connection = self.connect()
        connection.execute(
            '''
                insert into members (fname, lname, birth, relation, relation_id) values (?,?,?,?,?)
            ''', data)
        connection.commit()
        connection.close()

    def getall(self):
        connection = self.connect()
        cursor = connection.cursor()
        cursor.execute(''' select * from members ''')
        return cursor.fetchall()


    def count(self):
        connection = self.connect()
        cursor = connection.cursor()
        cursor.execute(''' select count(id) from members ''')
        return cursor.fetchone()[0]


class Form(tk.Toplevel):
    def __init__(self, parent, insert, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.insert = insert
        self.title('Top Window')
        self.geometry('800x235+300+300')
        self.resizable(False, False)
        self.parent = parent
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self['pady'] = 5
        self['padx'] = 5

        frame = tk.Frame(self, padx=5, pady=5)
        frame['borderwidth'] = 1
        frame['highlightthickness'] = 1
        frame['highlightcolor'] = 'gray'
        frame['highlightbackground'] = 'gray'
        frame.grid(column=0, row=0, sticky='news')
        frame.grid_columnconfigure(1, weight=3)

        self.protocol('WM_DELETE_WINDOW', self.close)

        label = {
            'ID': None, 'First Name': None, 'Last Name': None, 'Birth': None,
            'Relations': None, 'Relations ID':None
        }

        for index, key in enumerate(label.keys()):
            header = tk.Label(frame, text=key, anchor='w')
            header['font'] = (None, 12, 'bold')
            header.grid(column=0, row=index, sticky='new', padx=2, pady=2)

            value = tk.StringVar()
            if key == 'Relations':
                entry = tk.OptionMenu(frame, value, 'Father', 'Mother', 'Child', 'Grandpa')
                value.set('Father')
            else:
                entry = tk.Entry(frame)
            entry['font'] = (None, 12, 'normal')
            entry['textvariable'] = value
            label[key] = value
            entry.grid(column=1, row=index, sticky='new', padx=2, pady=2)
            if key == 'ID':
                id = Model().count()
                entry.delete(0, tk.END)
                entry.insert(0, id+1)
                entry['state'] = 'readonly'
            if key == 'Relations ID':
                entry.delete(0, tk.END)
                entry.insert(tk.END, id)
                entry['state'] = 'readonly'

        btn_frame = tk.Frame(frame)
        btn_frame.grid(columnspan=2, column=0, row=len(label)+1, sticky='new', pady=5)
        btn_frame.grid_columnconfigure(0, weight=3, uniform='btns')
        btn_frame.grid_columnconfigure(1, weight=3, uniform='btns')

        self.submit_btn = tk.Button(btn_frame, text='Submit', bg='gray86', font=(None, 10, 'bold'))
        self.submit_btn.grid(column=0, row=len(label)+1, padx=(0,2), sticky='news')
        self.submit_btn.bind('<Enter>', self.on_enter)
        self.submit_btn.bind('<Leave>', self.on_exit)
        self.submit_btn['command'] = lambda: self.add(label)

        self.exit_button = tk.Button(btn_frame, text='Exit', bg='tomato', font=(None, 10, 'bold'), command=self.close)
        self.exit_button.grid(column=1, row=len(label)+1, padx=(2,0), sticky='news')
        self.exit_button.bind('<Enter>', self.exit_enter)
        self.exit_button.bind('<Leave>', self.exit_out)

    def add(self, data):
        self.insert(data)
        self.destroy()
        self.parent.deiconify()

    def on_enter(self, event):
        self.submit_btn['bg'] = 'lightblue'
        self.submit_btn['fg'] = 'blue'
        self.submit_btn['cursor'] = 'hand2'

    def on_exit(self, event):
        self.submit_btn['bg'] = 'gray86'
        self.submit_btn['fg'] = 'black'

    def exit_enter(self, event):
        self.exit_button['fg'] = 'white'
        self.exit_button['bg'] = 'red'
        self.exit_button['cursor'] = 'hand2'

    def exit_out(self, event):
        self.exit_button['fg'] = 'black'
        self.exit_button['bg'] = 'tomato'

    def close(self):
        self.destroy()
        self.parent.deiconify()


class View:
    def __init__(self, parent, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.parent = parent
        self.parent.rowconfigure(0, weight=1)
        self.parent.columnconfigure(0, weight=1)
       
        self.listbox = tk.Listbox(self.parent)
        self.listbox['font'] = (None, 12, 'normal')
        self.listbox['selectmode'] = 'single'
        self.listbox.grid(column=0, row=0, sticky='news', padx=5, pady=5)

        btn_frame = tk.Frame(self.parent)
        btn_frame.grid(column=0, row=1, sticky='new')
        btn_frame.grid_columnconfigure(0, weight=3, uniform='buttons')
        btn_frame.grid_columnconfigure(1, weight=3, uniform='buttons')

        self.button = tk.Button(btn_frame, text='Add Member', bg='gray86')
        self.button['font'] = (None, 12, 'normal')
        self.button.grid(column=0, row=0, sticky='new', padx=5, pady=5)
        self.button.bind('<Enter>', self.on_btn_enter)
        self.button.bind('<Leave>', self.on_btn_leave)

        self.exit_btn = tk.Button(btn_frame, text='Exit', bg='tomato')
        self.exit_btn['font'] = (None, 12, 'normal')
        self.exit_btn.grid(column=1, row=0, sticky='new', padx=5, pady=5)
        self.exit_btn.bind('<Enter>', self.on_quit_enter)
        self.exit_btn.bind('<Leave>', self.on_quit_leave)

    def on_btn_enter(self, event):
        self.button['bg'] = 'lightblue'
        self.button['fg'] = 'blue'
        self.button['cursor'] = 'hand2'

    def on_btn_leave(self, event):
        self.button['bg'] = 'gray86'
        self.button['fg'] = 'black'

    def on_quit_enter(self, event):
        self.exit_btn['bg'] = 'red'
        self.exit_btn['fg'] = 'white'
        self.exit_btn['cursor'] = 'hand2'

    def on_quit_leave(self, event):
        self.exit_btn['bg'] = 'tomato'
        self.exit_btn['fg'] = 'black'


class Controller:
    def __init__(self, model, view, form):
        self.model = model
        self.model.create()
        self.view = view
        self.form = form

        if self.model.count() < 1:
            self.view.parent.withdraw()
            check = messagebox.askokcancel('No Entries', 'There are no entries in the database. Go to form to add one.')
            print(check)
            if check:
                self.showform()
            else:
                self.view.parent.destroy()

        self.populate()

        self.view.listbox.bind('<Double-1>', self.showform)
        self.view.button['command'] = self.showform
        self.view.exit_btn['command'] = self.view.parent.destroy
 
    def showform(self, event=None):
        self.view.parent.iconify()
        self.form(self.view.parent, self.insert)

    def populate(self):
        self.view.listbox.delete(0, tk.END)
        people = self.model.getall()

        for index, person in enumerate(people):
            self.view.listbox.insert(index, person)
        if self.model.count() > 0:
            self.view.listbox.selection_set(0)
       
    def insert(self, *label):
        alist = []
        for k, v in label[0].items():
            if k != 'ID':
                alist.append(v.get())
        self.model.insert(alist)
        self.populate()

if __name__ == '__main__':
    root = tk.Tk()
    root.title('Genealogy')
    root.geometry('800x600+350+350')
    root.resizable(False, False)
    controller = Controller(Model(), View(root), Form)
    root.mainloop()

To view this content we will need your consent to set third party cookies.
For more detailed information, see our cookies page.
 
Last edited:

New Threads

Latest posts

Buy us a coffee!

Back
Top Bottom