How to disable selction of the free part of Tkinter Listbox widget as an item?

Viewed 225

I'm creating a Tkinter-based app. It has a Listbox widget, and I want to get selected item on the double-click. Everything works fine if I double-click on an item, but if I double-click on the free part of the Listbox, the last item is getting selected and curselection returns a tuple with it (instead of an empty tuple).

Here is the code:

from tkinter import *


root = Tk()
listbox = Listbox(root)
for item in ("foo", "bar"):
    listbox.insert(END, item)
listbox.bind("<Double-1>", lambda event: print(listbox.curselection()))
listbox.pack()
root.mainloop()

I also tried using listbox.get(ACTIVE) and listbox.nearest(event.y) as @stovfl suggested but, unfortunately, it didn't help either. In the first case it returned the last string that was shown in the Listbox instead of the tuple with the last index. And in the second case it just returned the last index instead of the tuple with it.

illustration to my problem

PS: I have been here. But I don't bind the event to the root window, I bind it to the Listbox, but it doesn't work as I need either.

1 Answers

I think there are two ways to achieve that:

  1. When user click the empty place,deselect the active element.(I don't know how to do that)
  2. Or judge the position of the mouse.

For the second solution(You could use a function Listbox.bbox()):

import tkinter as tk


class Custom(tk.Frame):
    def __init__(self, master):
        super(Custom, self).__init__()

        self.master = master
        self.listbox = tk.Listbox(master=self)
        self.pos_list = []
        for item in ("foo", "bar"):
            self.listbox.insert(tk.END, item)
        self.listbox.bind("<Double-1>", self.double_click)

        self.listbox.pack()

    def double_click(self, event): # judge the event.y and the position of the first offsetY and the last offsetY
        if (event.y < self.listbox.bbox(0)[1]) or (event.y > self.listbox.bbox(tk.END)[1]+self.listbox.bbox(tk.END)[3]): # if not between it
            print(None)
        else:
            print(self.listbox.nearest(event.y))


root = tk.Tk()
customFrame = Custom(root)
customFrame.pack()
root.mainloop()

Refer: Listbox.bbox

Related