如何在Tkinter的列表框中上移或下移项目而不丢失选择?

时间:2018-10-11 15:07:13

标签: python tkinter

我有以下代码,该代码创建了一个简单的列表框,并允许用户选择项目并将其在列表中上移或下移,从而重新排列列表。

我现在遇到的问题是每次我按“上移”或“下移”时,操作均正确执行,但是光标不再保持选中状态。我必须重新选择该项目才能再次执行该功能。

在设置列表框时,我尝试配置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()

3 个答案:

答案 0 :(得分: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

并且对于 movedown 也是如此。

答案 1 :(得分:3)

要使选择保持选中状态,实际上必须在代码中选择正确的索引,因为它位于新位置。幸运的是,盒子的 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

答案 2 :(得分:1)

movedown 的更正代码为:

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