2013-07-30 113 views
1

有沒有辦法讓Tkinter列表框的項目成爲條目窗口小部件?結果將是您可以動態修改Listbox條目中的文本。如果你的列表框的樣子:Tkinter列表框與條目

-------- 
| Apples | 
| Pears | 
| Oranges | 
--------- 

那麼你會希望能夠點擊蘋果和寫一些任意的文本 - 那麼你可以綁定Enter鍵,比方說,觸發基於新文本的功能。

回答

0

,你可以給用戶一些條目然後創建從輸入

一個列表框,但你不能只改變一個列表框的文字一樣,

也許嘗試不同的GUI庫像WX

編輯

這裏是你可以做的:

from Tkinter import * 


root = Tk() 
opt_list = ['opt1','opt2','opt3','opt4','opt5'] 
sel_list = [] 

def get_sel(): 
    sel_list.append(Lb1.curselection()) 
    root.destroy() 

def change_opt(): 
    entry = E.get() 
    change = entry.split(" ") 
    print change 
    Lb1.insert(int(change[0]),change[1]) 
    root.update() 


def cancel(): 
    root.destroy() 
E = Entry(root) 
A = Button(root, text ="Change", command = change_opt) 
B = Button(root, text ="Submit", command = get_sel) 
C = Button(root, text ="Cancel", command = cancel) 
Lb1 = Listbox(root, selectmode=MULTIPLE) 


for i,j in enumerate(opt_list): 
    Lb1.insert(i,j) 


Lb1.pack() 
B.pack() 
C.pack() 
E.pack() 
A.pack() 

root.mainloop() 

這將使一個列表框與opt_list選項然後當你鍵入比如5 hello的項目,然後按更改將選項hello添加到第五位

那唯一的辦法我能想到的

+0

這是我認爲,但我會癢,直到我明白爲什麼不 - 這是否說這個地方? –

+0

嗯,我不認爲這是真的寫在任何地方它的更多像Tk沒有先進的足夠做這樣的事情......虐待環顧 – Serial

+0

看我的編輯它可能是唯一的方法來做到這一點 – Serial

2

不,tkinter不支持就地編輯列表框中的項目。當然,如果你真的不需要一個列表框,你總是可以將標籤或輸入小部件堆疊在一起,以獲得相似的效果。

1

我知道這個問題已經有一段時間了,但我已經創建了一個名爲'ListboxEditable'的小部件,它可以充當列表框,並且當雙擊某個項目時,用戶可以在條目中鍵入任何內容。然後,當用戶單擊另一行時,信息將保存在相應的修改單元格中。請注意,用戶可以使用向上和向下鍵瀏覽整個給定列表(所選行具有不同的背景顏色)。

此代碼是根據Bryan Oakley的回答開發的。

我離開這裏最小的工作情況:

# Imports 
from tkinter import * 
from tkinter.ttk import * 
# Import for the listboxEditable 
from ListboxEditable import * 

# Colors 
colorActiveTab="#CCCCCC" # Color of the active tab 
colorNoActiveTab="#EBEBEB" # Color of the no active tab 
# Fonts 
fontLabels='Calibri' 
sizeLabels2=13 

# Main window 
root = Tk() 

# *** Design ***** 
frame_name=Frame(root,bg=colorActiveTab) # Column frame 
frame_name_label=Frame(frame_name,bg='blue') # Label frame 
label_name=Label(frame_name_label, text="Header", bg='blue', fg='white', font=(fontLabels, sizeLabels2, 'bold'), pady=2, padx=2, width=10) 
frame_name_listbox=Frame(frame_name,bg='blue') # Label frame 
list_name=['test1','test2','test3'] 
listBox_name=ListboxEditable(frame_name_listbox,list_name) 

# *** Packing **** 
frame_name.pack(side=LEFT,fill=Y) 
frame_name_label.pack(side=TOP, fill=X) 
label_name.pack(side=LEFT,fill=X) 
frame_name_listbox.pack(side=TOP, fill=X) 
listBox_name.placeListBoxEditable() 

# Infinite loop 
root.mainloop() 

的ListboxEditable類如下:

# Author: David Duran Perez 
# Date: May 26, 2017 

# Necessary imports 
from tkinter import * 
from tkinter import ttk 

# Colors 
colorActiveTab="#CCCCCC" # Color of the active tab 
colorNoActiveTab="#EBEBEB" # Color of the no active tab 
# Fonts 
fontLabels='Calibri' 
sizeLabels2=13 

class ListboxEditable(object): 
    """A class that emulates a listbox, but you can also edit a field""" 
    # Constructor 
    def __init__(self,frameMaster,list): 
     # *** Assign the first variables *** 
     # The frame that contains the ListboxEditable 
     self.frameMaster=frameMaster 
     # List of the initial items 
     self.list=list 
     # Number of initial rows at the moment 
     self.numberRows=len(self.list) 

     # *** Create the necessary labels *** 
     ind=1 
     for row in self.list: 
      # Get the name of the label 
      labelName='label'+str(ind) 
      # Create the variable 
      setattr(self, labelName, Label(self.frameMaster, text=self.list[ind-1], bg=colorActiveTab, fg='black', font=(fontLabels, sizeLabels2), pady=2, padx=2, width=10)) 

      # ** Bind actions 
      # 1 left click - Change background 
      getattr(self, labelName).bind('<Button-1>',lambda event, a=labelName: self.changeBackground(a)) 
      # Double click - Convert to entry 
      getattr(self, labelName).bind('<Double-1>',lambda event, a=ind: self.changeToEntry(a)) 
      # Move up and down 
      getattr(self, labelName).bind("<Up>",lambda event, a=ind: self.up(a)) 
      getattr(self, labelName).bind("<Down>",lambda event, a=ind: self.down(a)) 

      # Increase the iterator 
      ind=ind+1 

    # Place 
    def placeListBoxEditable(self): 
     # Go row by row placing it 
     ind=1 
     for row in self.list: 
      # Get the name of the label 
      labelName='label'+str(ind) 
      # Place the variable 
      getattr(self, labelName).grid(row=ind-1,column=0) 

      # Increase the iterator 
      ind=ind+1 


    # Action to do when one click 
    def changeBackground(self,labelNameSelected): 
     # Ensure that all the remaining labels are deselected 
     ind=1 
     for row in self.list: 
      # Get the name of the label 
      labelName='label'+str(ind) 
      # Place the variable 
      getattr(self, labelName).configure(bg=colorActiveTab) 

      # Increase the iterator 
      ind=ind+1 

     # Change the background of the corresponding label 
     getattr(self, labelNameSelected).configure(bg=colorNoActiveTab) 
     # Set the focus for future bindings (moves) 
     getattr(self, labelNameSelected).focus_set() 


    # Function to do when up button pressed 
    def up(self, ind): 
     if ind==1: # Go to the last 
      # Get the name of the label 
      labelName='label'+str(self.numberRows) 
     else: # Normal 
      # Get the name of the label 
      labelName='label'+str(ind-1) 

     # Call the select 
     self.changeBackground(labelName) 


    # Function to do when down button pressed 
    def down(self, ind): 
     if ind==self.numberRows: # Go to the last 
      # Get the name of the label 
      labelName='label1' 
     else: # Normal 
      # Get the name of the label 
      labelName='label'+str(ind+1) 

     # Call the select 
     self.changeBackground(labelName) 


    # Action to do when double-click 
    def changeToEntry(self,ind): 
     # Variable of the current entry 
     self.entryVar=StringVar() 
     # Create the entry 
     #entryName='entry'+str(ind) # Name 
     self.entryActive=ttk.Entry(self.frameMaster, font=(fontLabels, sizeLabels2), textvariable=self.entryVar, width=10) 
     # Place it on the correct grid position 
     self.entryActive.grid(row=ind-1,column=0) 
     # Focus to the entry 
     self.entryActive.focus_set() 

     # Bind the action of focusOut 
     self.entryActive.bind("<FocusOut>",lambda event, a=ind: self.saveEntryValue(a)) 


    # Action to do when focus out from the entry 
    def saveEntryValue(self,ind): 
     # Find the label to recover 
     labelName='label'+str(ind) 
     # Remove the entry from the screen 
     self.entryActive.grid_forget() 
     # Place it again 
     getattr(self, labelName).grid(row=ind-1,column=0) 
     # Change the name to the value of the entry 
     getattr(self, labelName).configure(text=self.entryVar.get()) 

最好的問候,

大衛