classification
Title: tkinter ListboxSelect
Type: behavior Stage: resolved
Components: Tkinter Versions: Python 3.7, Python 3.6, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Frank Pae, louielu, serhiy.storchaka, terry.reedy
Priority: normal Keywords:

Created on 2017-04-28 15:42 by Frank Pae, last changed 2017-05-01 08:42 by Frank Pae. This issue is now closed.

Files
File name Uploaded Description Edit
tk_ListboxSelect.py Frank Pae, 2017-04-29 06:23
py2.7.13.gif Frank Pae, 2017-04-29 08:21
py3.5.3.gif Frank Pae, 2017-04-29 08:21
py3.6.1.gif Frank Pae, 2017-04-29 08:21
Messages (15)
msg292535 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-28 15:42
prerequisite:
you have more than one tkinter listbox

behavior in py 2.7.13 and py 3.5.3:
if you leave a listbox and goes to another, then the abandoned listbox create not a  ListboxSelect Event

behavior in py 3.6.0 and 3.6.1:
if you leave a listbox and goes to another, then the abandoned listbox create a  ListboxSelect Event and this gives a error-message


I dont know if my program is false, but it works in 2.7 and 3.5 good, however not with 3.6

Thank you
msg292565 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2017-04-29 05:32
Bug examples should be the bare minimum of code needed to reproduce the problem, not a dump of (failing) application code.  See, for instance, https://stackoverflow.com/help/mcve.

http://www.tcl.tk/man/tcl8.6/TkCmd/listbox.htm says "Any time the set of selected item(s) in the listbox is updated by the user through the keyboard or mouse, the virtual event <<ListboxSelect>> will be generated."  It was the same for 8.5.

What precise actions are *needed* to produce what you consider buggy behavior?  Please copy the complete traceback for the exception.  What system (OS) are you using.  If *nix, are you using the same tcl/tk for 3.6 as for 3.5?
msg292566 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-29 06:40
thank you for your answer

sorry for the "Long" code, but sometime is an longer example better than many words (and the most code is for layout, please fold with PyCharm)

i use "original" Python with tcl/tk as it is in the installer
in my gif-pictures you can see my sytem and the pyton versions

please run my example in 3.5.3 and in 3.6.1
call Font-Menue
choose size 11 and than choose style Standard

you will see what i mean


Thank you
msg292567 - (view) Author: Louie Lu (louielu) * Date: 2017-04-29 06:44
I can reproduce the problem at 2.7.13 on Linux.


Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1542, in __call__
    return self.func(*args)
  File "tests.py", line 174, in get_style
    lb_sty_get =  listbox_style.get(lb_sty_cur)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 2629, in get
    return self.tk.call(self._w, 'get', first)
TclError: bad listbox index "": must be active, anchor, end, @x,y, or a number
msg292568 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-29 06:52
i have added my picture for 2.7.13 

i mean there is no problem
msg292569 - (view) Author: Louie Lu (louielu) * Date: 2017-04-29 06:56
The problem cause by listbox.curselection(). When crossing from a listbox to another listbox, it will trigger twice event.

The first time get a valid select tuple from curselection() (which will return (index, label)), and the second time will generate empty tuple.

You should check curselection()'s tuple before passing into listbox.get(). The easiest is to add a if stmt for lb_*_cur, for example:


def get_style(event):
        # self.style.set(listbox_style.get(listbox_style.curselection()))
        # ____TEST____ >
        lb_sty_cur = listbox_style.curselection()
        if lb_sty_cur:
            lb_sty_get = listbox_style.get(lb_sty_cur)
            self.style.set(lb_sty_get)
        return
msg292570 - (view) Author: Louie Lu (louielu) * Date: 2017-04-29 07:06
But I'm not sure if this is a behavior error or something else, I'm still trying to find the root cause.
msg292571 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-29 07:30
it works in py 2.7 and 3.5 normal

there must be a change in 3.6, intended or unintentional

this is my Workaround:

def get_size(event):
    # self.size.set(listbox_size.get(listbox_size.curselection()))
    # ____TEST____ >
    ok=True
    try:
        lb_siz_cur = listbox_size.curselection()
        lb_siz_get =  listbox_size.get(lb_siz_cur)
    except:
        ok=False
    if ok:
        self.size.set(lb_siz_get)

        print('<<ListboxSelect>>',
              'def get_size:  listbox_size.curselection()= ',
              lb_siz_cur,'listbox_size.get()= ',lb_siz_get)
    return


you need the workaround also for get_style and get_font
msg292572 - (view) Author: Louie Lu (louielu) * Date: 2017-04-29 07:33
I think this is only a normal behavior now.


Generate two events make sense, they are generate by different widget:

.!editor.!font_dialog.!frame.!frame.!listbox (0,)   # Select Font
.!editor.!font_dialog.!frame2.!frame.!listbox (0,)  # Select Style
.!editor.!font_dialog.!frame.!frame.!listbox ()     # Deselect Font

When you select one list and trying to select another listbox,
you will trigger two event, first is the select, and second the de-select.

So you will need to handle the de-select part.
msg292573 - (view) Author: Louie Lu (louielu) * Date: 2017-04-29 07:43
This behavior is as same as on my Linux Python 2.7.13:


(<Tkinter.Listbox instance at 0x7f4b2b0c08c0>, (2,)) # Select Font
(<Tkinter.Listbox instance at 0x7f4b29caf248>, (3,)) # Select Style
(<Tkinter.Listbox instance at 0x7f4b2b0c08c0>, ())   # Deselect Font


And also, you don't need a try expect to handle this situation. You can see that when de-select the listbox, curselection() will return an empty tuple, you only need an if statement to handle this:

    def get_style(event):
        lb_sty_cur = event.widget.curselection()
        if lb_sty_cur:
            lb_sty_get = listbox_style.get(lb_sty_cur)
            self.style.set(lb_sty_get)
        return
msg292574 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-29 07:50
Thanks for the answers

Can you please explain why python 3.6 requires another treatment?

In 2.7 und 3.5 I do not need that

Thank you
msg292640 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2017-04-30 18:59
Frank, bigger is not better for demonstrating a problem.  The only thing needed for this issue is a tk window with two list boxes.  Having to click twice to get a window with more than just the two Listboxes is just noise.  

Anyway, I downloaded the file as tem.py into a directory on the path and ran "py -x.y -m tem" with the 3 x,y pairs.  For 3.6 I see the traceback Louie Lu posted -- **for 2.7**.

Since clicking in box 2 after clicking in box 1 changes the selection set in *both* boxes, on all 3 versions, there should a <<ListboxSelect>> event for both, on all 3 versions, as specified in the tcl/tk doc that I quoted. I believe it was a bug when the deselect event did not happen.

On Windows, 2.7.13 uses tk 8.5.15, 3.5.z uses tk 8.6.4, and 3.6.z uses tk 8.6.6.  My hypothesis is that the bug of not raising an event for the deselect, at least on Windows, was fixed in tk in 8.6.5/6.  If so, this should be closed as 'not a bug'.

Louie, what tk x.y.z do you have on your linux?

Serhiy, did you change anything in tkinter for 8.6 that could have affected <<ListboxSelect>> events?
msg292643 - (view) Author: Frank Pae (Frank Pae) Date: 2017-04-30 22:01
I am not a profi, just a normal user, i do what i can so good i can

I would like to thank all python developers

(AND: I think your last question ist the right question)
msg292646 - (view) Author: Louie Lu (louielu) * Date: 2017-05-01 01:01
ah, I think Terry point out the problem behind why my 2.7 and Frank's 2.7 have different behavior.

I'm using tk 8.6.6-1 on Linux, and it may be the problem from tk version.
msg292653 - (view) Author: Frank Pae (Frank Pae) Date: 2017-05-01 08:42
Here some detailed information about Tcl / Tk versions:

platform   Windows-10-10.0.14393   AMD64

python     3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
tkinter    Tcl/Tk  8.6.6 / 8.6.6

python     3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)]
tkinter    Tcl/Tk  8.6.4 / 8.6.4

python     2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)]
tkinter    Tcl/Tk  8.5.15 / 8.5.15
History
Date User Action Args
2017-05-01 08:42:46Frank Paesetmessages: + msg292653
2017-05-01 01:01:27louielusetmessages: + msg292646
2017-04-30 22:01:40Frank Paesetstatus: open -> closed
resolution: not a bug
messages: + msg292643

stage: test needed -> resolved
2017-04-30 18:59:04terry.reedysetmessages: + msg292640
2017-04-29 08:21:19Frank Paesetfiles: + py3.6.1.gif
2017-04-29 08:21:09Frank Paesetfiles: + py3.5.3.gif
2017-04-29 08:21:00Frank Paesetfiles: + py2.7.13.gif
2017-04-29 08:20:51Frank Paesetfiles: - py2.7.13.gif
2017-04-29 08:20:42Frank Paesetfiles: - py3.6.1.gif
2017-04-29 08:20:32Frank Paesetfiles: - py3.5.3.gif
2017-04-29 07:50:12Frank Paesetmessages: + msg292574
2017-04-29 07:43:56louielusetmessages: + msg292573
2017-04-29 07:33:02louielusetmessages: + msg292572
2017-04-29 07:30:03Frank Paesetmessages: + msg292571
2017-04-29 07:06:31louielusetmessages: + msg292570
2017-04-29 06:56:15louielusetmessages: + msg292569
2017-04-29 06:52:26Frank Paesetfiles: + py2.7.13.gif

messages: + msg292568
2017-04-29 06:44:02louielusetnosy: + louielu

messages: + msg292567
versions: + Python 2.7
2017-04-29 06:40:13Frank Paesetmessages: + msg292566
2017-04-29 06:24:45Frank Paesetfiles: + py3.6.1.gif
2017-04-29 06:24:27Frank Paesetfiles: + py3.5.3.gif
2017-04-29 06:23:16Frank Paesetfiles: + tk_ListboxSelect.py
2017-04-29 06:21:13Frank Paesetfiles: - tk_ListboxSelect.py
2017-04-29 05:32:59terry.reedysetversions: + Python 3.7
nosy: + terry.reedy, serhiy.storchaka

messages: + msg292565

stage: test needed
2017-04-28 15:42:07Frank Paecreate