Selecting values simultaneously from different Tki

2019-08-12 02:08发布

问题:

I want my program to work in a way that:

  • when I click an element from either of the 3 listboxes to select the adjacent values (example: if i select 0 in the first listbox, it should select the value "hello" in the second listbox and "world" in the third listbox

Thanks to This question/answer I managed to make them move simultaneously

the code is the following:

from tkinter import *

class fase3(Frame):

    def __init__(self, master):


        Frame.__init__(self,master)
        self.master=master
        self.frame=Frame(self.master)

        self.txtm=Label(self, text="example")
        self.txtm.grid(row=1, columnspan=5)

        self.txt1=Label(self, text="1")
        self.txt1.grid(row=2, column=1)

        self.txt2=Label(self, text="2")
        self.txt2.grid(row=2,column=2)

        self.txt3=Label(self, text="3")
        self.txt3.grid(row=2,column=3)
        self.scrlb=Scrollbar(self,orient="vertical")

        self.lista1=Listbox(self,yscrollcommand=self.yscroll1,exportselection=0)
        self.lista1.grid(row=3,column=1)

        self.lista2=Listbox(self, yscrollcommand=self.yscroll2,exportselection=0)
        self.lista2.grid(row=3, column=2)

        self.lista3=Listbox(self, yscrollcommand=self.yscroll3,exportselection=0)
        self.lista3.grid(row=3, column=3)

        #self.scrlb.config(command=self.yview)
        #self.scrlb.grid(row=3, column=4,rowspan=1)
#i chose not to place the scrollbar because it involved frames and it makes the code longer


        for i in range(3):
            self.lista1.insert("end",i)

        self.lista2.insert("end","hello")
        self.lista2.insert("end","pls")
        self.lista2.insert("end","thanks")
        self.lista3.insert("end","world")
        self.lista3.insert("end","help")
        self.lista3.insert("end","alot")

    def yscroll1(self, *args):
        if  self.lista2.yview()!=self.lista1.yview()!=self.lista3.yview():
            self.lista2.yview_moveto(args[0])
            self.lista3.yview_moveto(args[0])
        self.scrlb.set(*args)

    def yscroll2(self, *args):
        if  self.lista1.yview()!=self.lista2.yview()!=self.lista1.yview():
            self.lista1.yview_moveto(args[0])
            self.lista3.yview_moveto(args[0])
        self.scrlb.set(*args)

    def yscroll3(self, *args):
        if self.lista2.yview()!=self.lista3.yview()!=self.lista1.yview():
            self.lista1.yview_moveto(args[0])
            self.lista2.yview_moveto(args[0])
        self.scrlb.set(*args)

    def yview(self, *args):
        self.lista1.yview(*args)
        self.lista2.yview(*args)
        self.lista3.yview(*args)



    self.pack()

root = Tk()

marco= Frame(root, padx=100, pady=50)

marco.pack()

lf = fase3(marco)

root.mainloop()

part of the problem is, I already have a function bound to every Listbox, when I add exportselection=0, it selects a single value, so, for example the user can select ("0","hello","alot"), which for my purposes would make no sense at all (insertion to a database)

I haven't made any process in this, but if its possible for them to move simultaneously, it should somehow be possible for them to select adjacent values.

you should be able to copy paste this and run it on Python without a problem, I made it in python 3.

回答1:

The first thing you want to do is bind to the <<ListboxSelect>> event to detect when an option is selected in one of your list-boxes:

def __init__(self, master):

    # ...

    self.lista1=Listbox(self,yscrollcommand=self.yscroll1,exportselection=0)
    self.lista1.bind('<<ListboxSelect>>', self.on_select1)
    self.lista1.grid(row=3,column=1)

    self.lista2=Listbox(self, yscrollcommand=self.yscroll2,exportselection=0)
    self.lista2.bind('<<ListboxSelect>>', self.on_select2)
    self.lista2.grid(row=3, column=2)

    self.lista3=Listbox(self, yscrollcommand=self.yscroll3,exportselection=0)
    self.lista3.bind('<<ListboxSelect>>', self.on_select3)
    self.lista3.grid(row=3, column=3)

     # ...

When an option is selected, you want to select the corresponding option in the other list-boxes:

def on_select1(self, event):
    # Get index of selected option.
    index = self.lista1.curselection()[0]
    # Select corresponding options in other list-boxes.
    self.select_others(index, self.lista2, self.lista3)

def on_select2(self, event):
    # Get index of selected option.
    index = self.lista2.curselection()[0]
    # Select corresponding options in other list-boxes.
    self.select_others(index, self.lista1, self.lista3)

def on_select3(self, event):
    # Get index of selected option.
    index = self.lista3.curselection()[0]
    # Select corresponding options in other list-boxes.
    self.select_others(index, self.lista1, self.lista2)

def select_others(self, index, *others):
    for listbox in others:
        # The list-box's selection must be cleared to prevent the previous selection from remaining.
        listbox.selection_clear(0, listbox.size() - 1)
        listbox.selection_set(index)

Finally, the self.pack() at the end of the face3 class is misplaced.

class face3(Frame):

    # ...

    self.pack()

You should pack lf instead:

root = Tk()

marco = Frame(root, padx=100, pady=50)
marco.pack()

lf = fase3(marco)
lf.pack()

root.mainloop()