Tkinter GUI:按下按钮时使用.grid()添加新的输入框

时间:2017-03-28 07:40:07

标签: python python-2.7 user-interface layout tkinter

我试图在"添加条目"时创建新的输入框。用于我的程序。我确实意识到'包代码'当我单独运行它时工作,但是当我与grid()中的现有程序结合时,我运行程序时窗口没有显示。

我也明白,当我在同一个程序中使用.pack()进行其他操作时,我们不应同时使用.grid()。因此,我的问题是,如何在网格中创建新的输入框。

我试过在其他地方寻找,但他们都建议打包。例如:我看过here here等等,仅举几例;但是找不到类似我的东西。我想在第3行的当前输入框下面添加输入框。

我是Python的新手; (我在这个程序中使用Python 2.7和tkinter模块。非常感谢你的帮助! 我的简化错误代码如下:

from Tkinter import *
import tkFileDialog
import tkMessageBox
import Tkinter
import os

class Window:

 def __init__(self, master):

    self.filename3=""
    csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
    bar=Entry(master).grid(row=3, column=3)
    self.entryText3 = StringVar()
    self.bar = Entry(root, textvariable=self.entryText3).grid(row=3, column=3)

    #BUTTONS
    self.cbutton= Button(root, text="OK", command=self.process_csv)
    self.cbutton.grid(row=15, column=6, sticky = W + E)

####PROBLEM FROM HERE#####
    all_entries = []
    addboxButton = Button(root, text='ADD', fg="BLUE", command=self.addBox)
    addboxButton.pack()

#I have also tried replacing the last 2 lines with the following 2 lines instead but to no avail:     
#self.addboxButton = Button(root, text='ADD THA-ID', fg="BLUE", command=self.addBox)
#self.addboxButton.grid(row=3, column=6)

    frame_for_boxes = Frame(root)
    frame_for_boxes.pack()

 def addBox(self):
    print "ADD"
    next_row = len(all_entries)
    lab = Label(frame_for_boxes, text=str(next_row+1))
    lab.grid(row=next_row, column=0)
    ent = Entry(frame_for_boxes)
    ent.grid(row=next_row, column=0)
    all_entries.append( ent )

 def process_csv(self):
    #own program here
    print "program"
root = Tk()
window=Window(root)
root.mainloop()

2 个答案:

答案 0 :(得分:1)

除了您所声明的程序之外,您的程序几乎没有问题:

  1. 在初始值设定项(__init__())中,您将小部件附加到root,而Window类的范围内未定义这些小部件。解决此问题的合理方法是在root类中使用Tk(),id master id Window的实例,将其设为实例变量。这意味着您必须在inititializer中做的第一件事是:self.master = master。您必须在root

  2. 中替换__init__()内的所有self.master次出现结果
  3. 要修复的第二个问题是您在问题标题中指定的问题:您不能将grid()pack()布局管理器混合到同一个窗口小部件容器中。你必须决定哪一个。由于您使用grid()放置了大部分小部件,因此我建议您删除pack()。这意味着:

      例如,
    • addboxButton.pack()变为addboxButton.grid(row=0, column=1)
    • 例如,
    • frame_for_boxes.pack()变为frame_for_boxes.grid(row=0, column=0)
  4. 上一个列表项可以解决问题,但它会让您发现程序中与其相关的其他问题:

    • NameError: global name 'all_entries' is not defined
    • NameError: global name 'frame_for_boxes' is not defined

    这是因为在addBox()函数范围内无法访问这些窗口小部件变量。要解决此问题,您必须将这两个元素作为实例变量。这意味着:

    • all_entries = []变为self.all_entries = []
    • frame_for_boxes = Frame(root)变为self.frame_for_boxes = Frame(self.master)(请记住,我们已在{strong> 1 <{strong>}中将root替换为self.master

    此错误修复的后果是您必须在程序中使用全部内容:

    • self.all_entries代替all_entries
    • self.frame_for_boxes代替frame_for_boxes
  5. 出于可伸缩性的原因,我认为你至少要将其余的小部件作为实例变量(i.d.用self关键字作为前缀)

  6. 由于您的真实项目比您在此MCVE中显示的更复杂,我建议您在创建和放置窗口小部件元素时采用SaYa idiom。这意味着您需要替换:

      csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
    

    通过

      self.csvfile = Label(self.master, text="NUMBERS")
      self.csvfile.grid(row=3, column=0)
    

    为了避免程序中的意外错误,您必须对在inititialzer中声明的其余小部件执行相同的操作。

  7. 还有其他一些我想提及的内容,但其中大部分都可以在PEP8上找到

答案 1 :(得分:0)

您需要做什么来创建一个命令,该命令创建条目并将新条目存储在变量中。 在我的例子中,我使用Entry_i并存储在条目中,但您可以使用self.Entries来简化通信。 (python 3.5)

def Make_Entry(self, root, Entries, x, y):

    Entry_i = Entry(root, bd = 5)
    Entry_i.grid(row = x, column = y, sticky = W+E+N+S)
    Entries.append(Entry_i)
    return(Entries, x+1, y+1)