Как перемещать элементы вверх или вниз по списку в Tkinter, не теряя их выбора?

1

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

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

Я попытался настроить exportselection = False при настройке списка, но это не сработало.

import tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.wm_title("Animals")
        self._frame = None

class AnimalPage(tk.Frame):
    def __init__(self, master, controller):
        tk.Frame.__init__(self, master)
        self.master = master
        self.controller = controller
        self.config(relief='sunken', borderwidth=2)
        self.pack(fill = "both", expand = False)
        tk.Label(self, text="This is the Animal Configuration Page").pack()

        self.animalList = ['Cat', 'Dog', 'Bear', 'Dolphin', 'Kangaroo']
        self.animalString = tk.StringVar(value=self.animalList)
        self.animalBox = tk.Listbox(self, listvariable=self.animalString,
                                height=25, width=50, borderwidth=2)
        self.animalBox.pack()

        moveUpButton = tk.Button(self, text="Move Up", command=lambda: self.moveup())
        moveUpButton.pack()
        moveDownButton = tk.Button(self, text="Move Down", command=lambda: self.movedown())
        moveDownButton.pack()

    def moveup(self, *args):
        try:
            self.idxs = self.animalBox.curselection()
            if not self.idxs:
                return
            for pos in self.idxs:
                if pos==0:
                    continue
                text=self.animalBox.get(pos)
                self.animalBox.delete(pos)
                self.animalBox.insert(pos-1, text)
                self.animalList.pop(pos)
                self.animalList.insert(pos-1, text)
        except:
            pass

    def movedown(self, *args):
        try:
            self.idxs = self.animalBox.curselection()
            if not self.idxs:
                return
            for pos in self.idxs:
                if pos==0:
                    continue
                text=self.animalBox.get(pos)
                self.animalBox.delete(pos)
                self.animalBox.insert(pos+1, text)
                self.animalList.pop(pos)
                self.animalList.insert(pos+1, text)
        except:
            pass

if __name__ == "__main__":
    app = SampleApp()
    newFrame = AnimalPage(app, app)
    app.geometry("1200x700")
    app.mainloop()
Теги:
tkinter

3 ответа

5
Лучший ответ

Просто используйте selection_set для сохранения выбранного элемента, например:

 def moveup(self, *args):
    try:
        self.idxs = self.animalBox.curselection()
        if not self.idxs:
            return
        for pos in self.idxs:
            if pos==0:
                continue
            text=self.animalBox.get(pos)
            self.animalBox.delete(pos)
            self.animalBox.insert(pos-1, text)
            self.animalList.pop(pos)
            self.animalList.insert(pos-1, text)
            self.animalBox.selection_set(pos-1)
    except:
        pass

И аналогичным образом для movown.

  • 0
    PS. Я не мог не заметить, что функции moveup и Moveown закодированы, чтобы справиться с множественными выборами, но Listbox создается с режимом выбора по умолчанию (BROWSE), который позволяет выбирать только один элемент.
  • 0
    Привет, Мкам, большое спасибо за ответ. Это работает очень хорошо (и ответ Бристолы тоже сработал). Я не знал, что есть разные режимы выбора - я посмотрю, в каком из них возможен множественный выбор. Последнее, что я заметил, это использование вашего ответа, если я перейду на бывшего. Кенгуру наверх, я больше не могу сдвинуть его вниз. Только если я переместлю Кошку на 1 позицию вверх, я смогу снова начать движение Кенгуру.
Показать ещё 1 комментарий
3

Чтобы выбор был выбран, вы должны фактически выбрать правильный индекс в коде, так как он находится в новом месте. К счастью, box select_set (i) делает это. вы сделали бы это следующим образом:

def moveup(self, *args):
    try:
        self.idxs = self.animalBox.curselection()
        if not self.idxs:
            return
        for pos in self.idxs:
            if pos==0:
                continue
            text=self.animalBox.get(pos)
            self.animalBox.delete(pos)
            self.animalBox.insert(pos-1, text)
            self.animalList.pop(pos)
            self.animalList.insert(pos-1, text)
        self.animalBox.select_set(pos-1)
    except:
        pass
1

Исправленный код для motionown:

def movedown(self, *args):
    try:
        self.idxs = self.animalBox.curselection()
        if not self.idxs:
            return
        for pos in self.idxs:
            # Are we at the bottom of the list?
            if pos == len(self.animalList)-1: 
                continue
            text=self.animalBox.get(pos)
            self.animalBox.delete(pos)
            self.animalBox.insert(pos+1, text)
            self.animalList.pop(pos)
            self.animalList.insert(pos+1, text)
            self.animalBox.selection_set(pos + 1)
    except:
        pass
  • 0
    Ты такой классный. Спасибо, Мкам!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню