SQL Query result in tkinter

I have a tkinter interface where I need to display some query results, and I need the user to be able to change the column and send the results. Currently, to do queries, I am doing something like this:

conn = connection_info_goes_here cur = conn.cursor() cur.execute(query_goes_here) 

And this is my request:

 SELECT id, reviewer, task, num_seconds, start_time, end_time FROM hours WHERE DATE(start_time) = '2014-12-18' AND reviewer = 'john' 

The field that the user needs to change is num_seconds (digits only). My question is: how can I show the results of a query in the grid and how to make one of the fields changeable using the button to send the changes?

Additional information: I already did this very dirty, using exec() and programmatically creating variables for each field. It has become very long and confusing, and I really think that there should be a better and easier way to do this.

Any help is appreciated. Thanks!!

Quick update: since it was paused, I will add an image of something similar to what I'm looking for:

enter image description here

The values ​​in the record label should replace the values ​​in the column on the right when I load them back into the database.

When I say that I did it in a dirty way, it is because I did (the only way I could think of):

 def cor_window(): corrections = Tk() corrections.title("Corrections") corrections_frame = ttk.Frame(corrections) cor_values = [] count=0 cor_count=0 for x in results: count2=0 for y in results[count]: if count2 == 3: exec('int' + str(cor_count) + '=tkinter.StringVar') exec('int' + str(cor_count) + '_entry = ttk.Entry(corrections, width=20, textvariable=int' + str(cor_count) + ')') exec('int' + str(cor_count) + '_entry.grid(column=count2, row=count+2)') cor_count = cor_count+1 cor_values.append('int' + str(cor_count) + '_entry') ttk.Label(corrections, width=20, anchor=CENTER, relief=SUNKEN, borderwidth=1, text= results[count][count2]).grid(column=count2+1, row=count+2) elif count2 > 3: ttk.Label(corrections, width=20, anchor=CENTER, relief=SUNKEN, borderwidth=1, text= results[count][count2]).grid(column=count2+1, row=count+2) else: ttk.Label(corrections, width=20, anchor=CENTER, relief=SUNKEN, borderwidth=1, text= results[count][count2]).grid(column=count2, row=count+2) count2=count2+1 count=count+1 ttk.Button(corrections, text="Done!", command=upload_cor).grid(column=0, row=1) 

Where results is a list containing query results, and upload_cor is a function that will upload changes to the database. Since I used exec , even if the user modifies the input window, I cannot use .get() to get what the user typed. When I try to use .get() , I get only None , even if something has been entered in the input field.

I just need another way to do this, again, any ideas are welcome.

+5
source share
1 answer

You definitely don't want to use exec, and you don't need to use the textvariable parameter. Both of them just add to the confusion. Just save your widgets as a dictionary, get the data directly from the input widget, and everything becomes very easy to manage.

Here is a working example:

 import tkinter as tk class Example(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) b = tk.Button(self, text="Done!", command=self.upload_cor) b.pack() table = tk.Frame(self) table.pack(side="top", fill="both", expand=True) data = ( (45417, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45418, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45419, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45420, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45421, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45422, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), (45423, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"), ) self.widgets = {} row = 0 for rowid, reviewer, task, num_seconds, start_time, end_time in (data): row += 1 self.widgets[rowid] = { "rowid": tk.Label(table, text=rowid), "reviewer": tk.Label(table, text=reviewer), "task": tk.Label(table, text=task), "num_seconds_correction": tk.Entry(table), "num_seconds": tk.Label(table, text=num_seconds), "start_time": tk.Label(table, text=start_time), "end_time": tk.Label(table, text=start_time) } self.widgets[rowid]["rowid"].grid(row=row, column=0, sticky="nsew") self.widgets[rowid]["reviewer"].grid(row=row, column=1, sticky="nsew") self.widgets[rowid]["task"].grid(row=row, column=2, sticky="nsew") self.widgets[rowid]["num_seconds_correction"].grid(row=row, column=3, sticky="nsew") self.widgets[rowid]["num_seconds"].grid(row=row, column=4, sticky="nsew") self.widgets[rowid]["start_time"].grid(row=row, column=5, sticky="nsew") self.widgets[rowid]["end_time"].grid(row=row, column=6, sticky="nsew") table.grid_columnconfigure(1, weight=1) table.grid_columnconfigure(2, weight=1) # invisible row after last row gets all extra space table.grid_rowconfigure(row+1, weight=1) def upload_cor(self): for rowid in sorted(self.widgets.keys()): entry_widget = self.widgets[rowid]["num_seconds_correction"] new_value = entry_widget.get() print("%s: %s" % (rowid, new_value)) if __name__ == "__main__": root = tk.Tk() Example(root).pack(fill="both", expand=True) root.mainloop() 

I would actually implement this a little differently by creating a Table class using the add_row method, but I did not want to get too complicated. The basic idea is the same, regardless of whether you create the Table class, do it all in one class or do it procedurally - create a dictionary to represent your data. You can also use nested lists, but I believe dictionaries will be much easier to use. They are also self-documenting since you are referencing things by a symbolic name, and not just that column 4 is the start time.

+7
source

Source: https://habr.com/ru/post/1209505/


All Articles