2013-07-30 2 views
1

Есть ли способ, чтобы элементы списка Tkinter были видными виджетами? В результате вы могли бы динамически изменять текст в записи списка. Если ваш Listbox выглядит следующим образом:Tkinter Listbox with Entry

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

, то вы хотели бы быть в состоянии нажать на яблоки и написать какой-нибудь произвольный текст - можно затем привязать клавишу Enter, скажем, чтобы вызвать функцию, основанную на новом тексте.

ответ

0

вы могли бы дать пользователю некоторые записи затем создать ListBox из этого входа

, но вы не можете просто изменить текст ListBoxes как этот

может быть, попробовать другой GUI библиотеки как WX

EDIT

здесь является то, что вы можете сделать:

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

С наилучшими пожеланиями,

Дэвид