2014-12-19 17 views
5

Tôi có giao diện tkinter nơi tôi cần hiển thị một số kết quả truy vấn và tôi cần người dùng có thể sửa đổi cột và gửi kết quả. Hiện nay để kéo các truy vấn tôi đang làm một cái gì đó như thế này:Kết quả truy vấn SQL bằng tkinter

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

Và đây là câu hỏi của tôi:

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

Các lĩnh vực mà người dùng cần phải sửa đổi là num_seconds (chỉ số). Câu hỏi của tôi là, làm cách nào để làm cho kết quả truy vấn hiển thị trong lưới và làm cách nào để tôi thực hiện một trong các trường có thể sửa đổi bằng nút để gửi thay đổi?

Thông tin bổ sung: Tôi đã thực hiện việc này theo cách rất lộn xộn bằng cách sử dụng exec() và tạo biến theo chương trình cho từng trường. Nó trở nên rất dài và khó hiểu và tôi thực sự nghĩ rằng phải có một cách tốt hơn và dễ dàng hơn để làm điều này.

Mọi trợ giúp đều được đánh giá cao. Cảm ơn!!

Cập nhật nhanh: vì đây được đặt ở trạng thái giữ, tôi sẽ thêm một hình ảnh của một cái gì đó tương tự như những gì tôi đang tìm kiếm:

enter image description here

Các giá trị trong nhãn nhập cảnh phải thay thế các giá trị trong cột ở bên phải khi tôi tải chúng trở lại DB.

Khi tôi nói rằng tôi đã làm điều này một cách lộn xộn, là bởi vì tôi đã làm (cách duy nhất tôi có thể nghĩ ra):

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) 

đâu results là danh sách có chứa kết quả truy vấn và upload_cor là chức năng sẽ tải lên các thay đổi cho DB. Vì tôi đã sử dụng exec, ngay cả khi người dùng sửa đổi hộp nhập, tôi không thể sử dụng .get() để nhận được những gì người dùng đã nhập. Khi tôi thử sử dụng .get(), tôi chỉ nhận được None ngay cả khi đã nhập nội dung nào đó vào hộp nhập.

Tôi chỉ cần một phương pháp khác để làm điều này, một lần nữa, mọi ý tưởng đều được hoan nghênh.

+0

num_seconds sẽ sử dụng Mục nhập (hoặc danh sách ID mục nhập) và phần còn lại sẽ là Nhãn. Bạn cũng sẽ phải liên kết số hàng với bản ghi và so sánh từng mục nhập với giá trị ban đầu để xem những hàng nào đã thay đổi, nhưng nếu "id" là duy nhất thì nó phải đơn giản.Nhập thông tin widget http://effbot.org/tkinterbook/entry.htm –

Trả lời

7

Bạn chắc chắn không muốn sử dụng lệnh exec, và bạn không cần sử dụng tùy chọn textvariable. Cả hai đều chỉ thêm vào sự nhầm lẫn. Chỉ cần lưu trữ các tiện ích của bạn dưới dạng từ điển, nhận dữ liệu trực tiếp từ tiện ích mục nhập và tất cả đều trở nên rất dễ quản lý.

Dưới đây là một ví dụ làm việc:

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() 

Tôi thực sự sẽ thực hiện điều này một chút khác nhau bằng cách tạo ra một lớp Table với một phương pháp add_row, nhưng tôi không muốn nhận được quá phức tạp. Ý tưởng cơ bản là như nhau cho dù bạn tạo ra một lớp học Table, làm tất cả trong một lớp học, hoặc làm điều đó procedurally - tạo ra một từ điển để đại diện cho dữ liệu của bạn. Bạn cũng có thể sử dụng danh sách lồng nhau, nhưng tôi thấy từ điển dễ sử dụng hơn nhiều. Chúng cũng tự ghi lại tài liệu, vì bạn tham chiếu mọi thứ theo tên tượng trưng thay vì chỉ biết rằng cột 4 là thời gian bắt đầu.

+0

Điều này thực sự là khá tuyệt vời, tôi nghĩ rằng điều này bây giờ từ một quan điểm khác nhau. Chỉ cần có thêm một câu hỏi, làm thế nào để tôi đặt một thanh cuộn trong trường hợp kết quả lớn hơn cửa sổ? điều đó có thể không? Cảm ơn!!!! – rodrigocf

+0

Và nếu chỉ nên lưu điều đó cho một câu hỏi khác, hãy cho tôi biết :) – rodrigocf

+0

@rodrigocf: đó là một câu hỏi riêng biệt đã được trả lời trước đó. Xem http://stackoverflow.com/a/3092341/7432 –

Các vấn đề liên quan