Python tkinter - удаление выбранного элемента списка - PullRequest
0 голосов
/ 01 ноября 2018

Мне нужно иметь возможность выделить один или несколько элементов в указанном списке и удалить их. Я смотрел на вопросы других людей здесь, но по какой-то причине, когда я пытаюсь удалить элементы, ничего не происходит вообще.

Ниже мой код, который я использую. Может кто-нибудь взглянуть и помочь мне, пожалуйста?

import tkinter

class Remove_Button_Widget():

    def __init__(self):
        self.Remove_Button = tkinter.Button(master, text= "Remove", height = 2, width = 6, command =lambda :remove_button().remove_functionality(Robot_Files_Found_Widgets().ROBOT_FILE_LIST))
        self.Remove_Button.place(x=362,y=350)

class Robot_Files_Found_Widgets():


    def __init__(self):
        self.Robot_Files_Ran_Frame = tkinter.Frame(master)
        self.Robot_Files_Ran_Frame.place(bordermode=tkinter.INSIDE, height=30, width=200, y=250, x=35)

        self.Display_Robot_Files_Frame = tkinter.Frame(master, borderwidth=1, highlightthickness=1,
                                              highlightbackground="black", highlightcolor="black")
        self.Display_Robot_Files_Frame.place(bordermode=tkinter.INSIDE, height=200, width=300, y=285, x=50)
        self.ROBOT_FILE_LIST = tkinter.Listbox(self.Display_Robot_Files_Frame,selectmode=tkinter.MULTIPLE)
        self.ROBOT_FILE_LIST.place(bordermode=tkinter.INSIDE, height=196, width=296)

        self.Scroll_Bar_x = tkinter.Scrollbar(self.ROBOT_FILE_LIST, orient=tkinter.HORIZONTAL)
        self.Scroll_Bar_x.config(command=self.ROBOT_FILE_LIST.xview)
        self.Scroll_Bar_x.pack(fill=tkinter.X, side=tkinter.BOTTOM)
        self.ROBOT_FILE_LIST.config(xscrollcommand=self.Scroll_Bar_x.set)
        self.Scroll_Bar_y = tkinter.Scrollbar(self.ROBOT_FILE_LIST, orient=tkinter.VERTICAL)
        self.Scroll_Bar_y.config(command=self.ROBOT_FILE_LIST.yview)
        self.Scroll_Bar_y.pack(fill=tkinter.Y, side=tkinter.RIGHT)
        self.ROBOT_FILE_LIST.config(yscrollcommand=self.Scroll_Bar_y.set)
        list = []
        for x in range(0,15):
            list.append(x)
        for y in list:
            self.ROBOT_FILE_LIST.insert(0,y)

class remove_button():

    def remove_functionality(self, ROBOT_FILE_LIST):
        sel = ROBOT_FILE_LIST.curselection()
        # iterate over sel, deleting each item
        for index in sel:
            ROBOT_FILE_LIST.delete(index)

if __name__ == "__main__":


    master = tkinter.Tk()
    master.title("Test Runner")
    master.geometry("750x500")
    master.resizable(width=False, height=False)
    Robot_Files_Found_Widgets()
    Remove_Button_Widget()
    master.mainloop()

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Основная причина, по которой ваша кнопка не работает, связана с тем, как вы построили свою лямбду. Поскольку вы вызываете класс каждый раз, когда нажимаете кнопку, вы на самом деле не редактируете первый экземпляр этого класса, используемый для создания вашего графического интерфейса. Вам нужно сохранить ссылку на экземпляр класса, чтобы заставить это работать. Еще одна проблема, которую я вижу, которую вам следует избегать, - это назвать свой список list. Не называйте переменные так же, как встроенные методы. Это сломает вещи в вашем коде.

Я не думаю, что вы должны строить так много классов. Вся ваша функциональность здесь может быть встроена в один класс. Тем не менее, вам также нужно reversed() при удалении выбранных вами индексов, чтобы вы не пропускали индекс.

import tkinter as tk


class Example(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Test Runner")
        self.geometry("750x500")
        self.resizable(width=False, height=False)
        self.robot_files_ran_frame = tk.Frame(self)
        self.robot_files_ran_frame.place(bordermode=tk.INSIDE, height=30, width=200, y=250, x=35)

        self.display_robot_files_frame = tk.Frame(self, borderwidth=1, highlightthickness=1,
                                              highlightbackground="black", highlightcolor="black")
        self.display_robot_files_frame.place(bordermode=tk.INSIDE, height=200, width=300, y=285, x=50)
        self.robot_file_list = tk.Listbox(self.display_robot_files_frame,selectmode=tk.MULTIPLE)
        self.robot_file_list.place(bordermode=tk.INSIDE, height=196, width=296)

        self.scroll_bar_x = tk.Scrollbar(self.robot_file_list, orient=tk.HORIZONTAL)
        self.scroll_bar_x.config(command=self.robot_file_list.xview)
        self.scroll_bar_x.pack(fill=tk.X, side=tk.BOTTOM)
        self.robot_file_list.config(xscrollcommand=self.scroll_bar_x.set)
        self.scroll_bar_y = tk.Scrollbar(self.robot_file_list, orient=tk.VERTICAL)
        self.scroll_bar_y.config(command=self.robot_file_list.yview)
        self.scroll_bar_y.pack(fill=tk.Y, side=tk.RIGHT)
        self.robot_file_list.config(yscrollcommand=self.scroll_bar_y.set)
        some_list = []

        for x in range(0,15):
            some_list.append(x)

        for y in some_list:
            self.robot_file_list.insert(0, y)

        self.remove_button = tk.Button(self, text= "Remove", height=2, width=6, command=self.remove_functionality)
        self.remove_button.place(x=362, y=350)

    def remove_functionality(self):
        sel = self.robot_file_list.curselection()
        # added reversed here so index deletion work for multiple selections.
        for index in reversed(sel):
            self.robot_file_list.delete(index)

if __name__ == "__main__":
    Example().mainloop()

Просто для того, чтобы исправить исходную проблему, не перерабатывая весь код, вам нужно сохранить ссылку на ваш список и передать ее на кнопку для переменной.

Вот пример использования вашего кода с сохраненной переменной для передачи между классами.

import tkinter


class Remove_Button_Widget():
    def __init__(self, var1):
        variable_to_pass = var1
        self.Remove_Button = tkinter.Button(master, text="Remove", height=2, width=6, command=lambda :remove_button().remove_functionality(variable_to_pass))
        self.Remove_Button.place(x=362,y=350)


class Robot_Files_Found_Widgets():
    def __init__(self):
        self.Robot_Files_Ran_Frame = tkinter.Frame(master)
        self.Robot_Files_Ran_Frame.place(bordermode = tkinter.INSIDE, height=30, width=200, y=250, x=35)
        self.Display_Robot_Files_Frame = tkinter.Frame(master, borderwidth=1, highlightthickness=1,
                                              highlightbackground="black", highlightcolor="black")
        self.Display_Robot_Files_Frame.place(bordermode = tkinter.INSIDE, height=200, width=300, y=285, x=50)
        self.ROBOT_FILE_LIST = tkinter.Listbox(self.Display_Robot_Files_Frame,selectmode = tkinter.MULTIPLE)
        self.ROBOT_FILE_LIST.place(bordermode = tkinter.INSIDE, height=196, width=296)

        self.Scroll_Bar_x = tkinter.Scrollbar(self.ROBOT_FILE_LIST, orient = tkinter.HORIZONTAL)
        self.Scroll_Bar_x.config(command=self.ROBOT_FILE_LIST.xview)
        self.Scroll_Bar_x.pack(fill = tkinter.X, side = tkinter.BOTTOM)
        self.ROBOT_FILE_LIST.config(xscrollcommand=self.Scroll_Bar_x.set)
        self.Scroll_Bar_y = tkinter.Scrollbar(self.ROBOT_FILE_LIST, orient = tkinter.VERTICAL)
        self.Scroll_Bar_y.config(command=self.ROBOT_FILE_LIST.yview)
        self.Scroll_Bar_y.pack(fill = tkinter.Y, side = tkinter.RIGHT)
        self.ROBOT_FILE_LIST.config(yscrollcommand=self.Scroll_Bar_y.set)
        some_list = []
        for x in range(0,15):
            some_list.append(x)
        for y in some_list:
            self.ROBOT_FILE_LIST.insert(0, y)
        Remove_Button_Widget(self.ROBOT_FILE_LIST)


class remove_button():
    def remove_functionality(self, ROBOT_FILE_LIST):
        sel = ROBOT_FILE_LIST.curselection()
        # iterate over sel, deleting each item
        for index in reversed(sel):
            ROBOT_FILE_LIST.delete(index)


if __name__ =="__main__":
    master = tkinter.Tk()
    master.title("Test Runner")
    master.geometry("750x500")
    master.resizable(width=False, height=False)
    Robot_Files_Found_Widgets()
    master.mainloop()
0 голосов
/ 01 ноября 2018

Метод .curselection() возвращает набор индексов выбранных элементов. Метод .delete() берет данные, указанные в ошибке в верхней части вашего вопроса, он не будет принимать кортеж.

У вас есть режим выбора для вашего Listbox, установленный как MULTIPLE, поэтому вам нужно перебрать кортеж, возвращаемый curselection(), и удалить каждый индекс один за другим.

def remove_functionality(self,ROBOT_FILE_LIST):
    sel = ROBOT_FILE_LIST.curselection()
    # iterate over sel, deleting each item
    for index in sel[::-1]:
        ROBOT_FILE_LIST.delete(index)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...