2017-10-08 4 views
1

Lorsque je copie du texte et le collez (crtl + v) dans une entrée tkinter, s'il y a du texte sélectionné, il ne le supprimera pas de l'entrée. Je suis sur Linux (Mint) 64 bits.
tkinter copier-coller dans Entrée ne supprime pas le texte sélectionné

Ici je copie "d" avec (ctrl + c): enter image description here

Puis je sélectionne "b": enter image description here

Maintenant, je coller "d" (ctrl + v) sur celui-ci mais le résultat est le suivant: enter image description here

Première: Je veux savoir si cela est un bug spécifique à Linux ou cela est la façon dont il était censé être?

Deuxième: Je pensais à une solution pour cela avec validatecommand mais je suis un autre problème:

Si je dois supprimer le texte sélectionné dans une commande, je dois connaître l'indice de sélection l'entrée. Sinon, s'il y a plusieurs instances du texte sélectionné directement après et avant le curseur, je ne saurais pas lequel supprimer et remplacer par le nouveau texte. Parce que le curseur pourrait être de chaque côté de la sélection (selon que la personne a fait glisser la souris de droite à gauche ou de gauche à droite sur le texte).

Maintenant, est-il un moyen d'obtenir le index de sélection dans l'entrée? ou une autre façon de contourner ce problème?

est ici un code avec un exemple du problème:

import tkinter as tk 

root = tk.Tk() 

def validation(after_text, before_text, validation_text, cursor_index): 
    cursor_index = int(cursor_index) 
    print('cursor index:', cursor_index) 
    print('text after change:', after_text) 
    print('text before change:', before_text) 
    print('text in need of validation:', validation_text) 

    try: 
     selection = root.selection_get() 
    except: 
     selection = '' 
    print('selection:', selection) 

    # EXAMPLE: 

    # validation_text = 'd' 
    # before text = "bb" 

    # now if someone dragged from right to left on the 2nd b: 
    # cursor position will be 1 (imagine | as the cursor): 'b|b' 
    # cursor_index = 1 
    # after_text = 'bdb' --> but should be 'bd' 

    # now if someone dragged from left to right on the 2nd b: 
    # cursor position will be 2 (imagine | as the cursor): 'bb|' 
    # cursor_index = 2 
    # after_text = 'bbd' --> but should be 'bd' 

    # so there is no way for me to know which of these b's I have 
    # to replace with d based on cursor position alone. I have to 
    # know the index of selection itself in before_text to be 
    # able to replace the text properly. 

    # I don't know how to get that. 

    return True 

txtvar = tk.StringVar(value = 'a-b-c-d-e') 
entry = tk.Entry(root, textvariable = txtvar) 
font = tk.font.Font(family = entry.cget('font'), size = -50) 

entry.config(validate = 'all', 
    vcmd = (root.register(validation),'%P', '%s', '%S', '%i'), 
    font = font) 
entry.pack() 

root.mainloop() 
+0

Dans Windows 7/python3, le collage fonctionne comme prévu. – Lafexlos

+0

À propos de chose de sélection, vous pouvez consulter [cette question] (https://stackoverflow.com/questions/4073468/how-do-i-get-a-selected-string-in-from-a-tkinter-text- boîte). Les deux réponses (et ses commentaires) sont très instructifs. – Lafexlos

+0

@Lafexlos J'ai obtenu le texte de sélection ... regarde dans mon essai/sauf. problème que je l'ai expliqué, n'est pas incapable d'obtenir le texte, il ne sait pas exactement d'où vient l'entrée de ce texte (l'index de ce texte de sélection dans le texte entier de l'entrée). – ROAR

Répondre

1

Ce n'est pas un bug. Si c'était un bug, quelqu'un l'aurait remarqué et l'aurait corrigé il y a une dizaine d'années. Tkinter existe depuis longtemps et des choses fondamentales comme celle-ci ne passent pas inaperçues.

La mise en œuvre du collage sur les systèmes X11 ne supprimera pas le texte sélectionné avant le collage. Ce qui suit est le code Tcl réel sous-jacent au moment où j'écris ceci:

bind Entry <<Paste>> { 
    global tcl_platform 
    catch { 
     if {[tk windowingsystem] ne "x11"} { 
      catch { 
       %W delete sel.first sel.last 
      } 
     } 
     %W insert insert [::tk::GetSelection %W CLIPBOARD] 
     tk::EntrySeeInsert %W 
    } 
} 

Utilisation de la fonction de validation est certainement la mauvaise façon de résoudre ce problème. La validation est spécifiquement pour ce que le nom implique: validation. La bonne solution consiste à créer votre propre liaison à l'événement <<Paste>>.

Maintenant, existe-t-il un moyen d'obtenir l'index de sélection dans l'entrée? ou une autre façon de contourner ce problème?

Oui, le widget d'entrée a l'indice spécial sel.first qui représente le premier caractère de la sélection et sel.last représente le caractère juste après la sélection.

Une traduction assez littérale du code ci-dessus en python (moins le chèque de x11) ressemblerait à quelque chose comme ceci:

def custom_paste(event): 
    try: 
     event.widget.delete("sel.first", "sel.last") 
    except: 
     pass 
    event.widget.insert("insert", event.widget.clipboard_get()) 
    return "break" 

d'avoir cette application à un widget spécifique, se lient à l'événement <<Paste>> pour que widget:

entry = tk.Entry(...) 
entry.bind("<<Paste>>", custom_paste) 

Si vous voulez faire une seule liaison qui applique pour tous les widgets Entry, utilisez bind_class:

root = tk.Tk() 
... 
root.bind_class("Entry", "<<Paste>>", custom_paste) 
+0

Merci beaucoup, cela résout. Impossible de l'obtenir n'importe où! J'ai juste supposé que tkinter n'a pas l'attention qu'il mérite sous Linux par opposition à Windows. C'est pourquoi j'ai pensé que c'était un bug. J'ai aussi posé une autre question concernant les doubles points dans les extensions de fichiers sur Linux et n'ai pas eu de réponse (autre que cela fonctionne sur Windows ... donc j'ai juste supposé ...) – ROAR

+0

@ROAR: croyez-le ou non, tk (le La boîte à outils sous-jacente utilisée par tkinter) a été développée à l'origine pour les systèmes Unix avant même l'existence de Linux. Il a fallu quelques années avant qu'il y ait un port windows et macintosh. –

+0

Donc, ce que je reçois de ceci est ... Je ne pouvais pas avoir plus tort. : D Vous en savez beaucoup sur tkinter ... Je vois vos réponses dans beaucoup de questions sur tkinter. peut-être que vous connaissez la réponse à [mon autre question concernant les extensions de fichiers] (https://stackoverflow.com/questions/46512663/tkinter-asksaveasfilename-doesnt-work-with-more-than-1-dot-in-file-extension). – ROAR