2017-09-12 8 views
2

EnvironnementTk copies seulement si le presse-papiers "coller" est utilisé avant le programme sort

  • Python 3.6.2
  • de Windows 10

Le problème

I utilisez la méthode tk clipboard_append() pour copier une chaîne dans le presse-papiers.

Lorsque mon programme est exécuté à partir de l'interpréteur Python, les données sont copiées dans le Presse-papiers correctement.

Lors de l'exécution à l'aide de "C: \ Python36.exe myprogram.py", cependant, j'obtiens un comportement étrange.

  1. Si je coller les données alors que le programme est toujours en cours, il fonctionne comme prévu.
  2. Si je coller les données pendant que le programme est en cours d'exécution, puis fermez le programme, je peux continuer à coller les données.
  3. Si je ferme le programme après copie mais avant coller, le Presse-papiers est vide.

Question

Comment puis-je faire une copie tk au presse-papiers, peu importe ce qui se passe à la fenêtre contenant?

Mon code

from tkinter import * 
from tkinter import messagebox 

url = 'http://testServer/feature/' 

def copyToClipboard(): 
    top.clipboard_clear() 
    top.clipboard_append(fullURL.get()) 
    top.update() 
    top.destroy() 

def updateURL(event): 
    fullURL.set(url + featureNumber.get()) 

def submit(event): 
    copyToClipboard() 

top = Tk() 
top.geometry("400x75") 
top.title = "Get Test URL" 

topRow = Frame(top) 
topRow.pack(side = TOP) 

bottomRow = Frame(top) 
bottomRow.pack(side = BOTTOM) 

featureLabel = Label(topRow, text="Feature Number") 
featureLabel.pack(side = LEFT) 

featureNumber = Entry(topRow) 
featureNumber.pack(side = RIGHT) 

fullURL = StringVar() 
fullURL.set(url) 

fullLine = Label(bottomRow, textvariable=fullURL) 
fullLine.pack(side = TOP) 

copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard) 
copyButton.pack(side = TOP) 

featureNumber.focus_set() 
featureNumber.bind("<KeyRelease>", updateURL) 
featureNumber.bind("<Return>", submit) 

top.mainloop() 

Objet du Programme

Mon entreprise dispose d'un serveur de test que nous utilisons pour de nouvelles fonctionnalités. Chaque fois que nous créons une nouvelle fonctionnalité, nous devons publier une URL sur le serveur de test. Les URL sont identiques sauf pour le numéro de fonction, donc j'ai créé ce programme python pour générer l'url pour moi et le copier dans le presse-papier.

Je peux obtenir ce travail si je commente "top.destroy" et collez l'URL avant de fermer manuellement la fenêtre, mais je voudrais vraiment éviter cela. Dans un monde parfait, j'appuierais sur un raccourci, j'ouvrirais la fenêtre, entrerais mon numéro de fonction, puis j'appuierais simplement sur la touche Entrée pour fermer la fenêtre et coller la nouvelle adresse, le tout sans enlever mes mains du clavier.

+0

'' ipdateLink' dans featureNumber.bind ("", updateLink) 'ne figure pas dans votre code à l'origine que votre code soit pas testable. Veuillez fournir une version testable de votre code. Ce message devrait vous aider: [Exemple minimal, complet et vérifiable] (https://stackoverflow.com/help/mcve) –

+0

Cela semble être un doublon de https://stackoverflow.com/q/20866593/7432 –

+0

I suggère d'essayer la suggestion ici pour voir si elle résout votre problème: https://bugs.python.org/msg254055 –

Répondre

1

Votre problème de vide dans le presse-papiers si vous fermez l'application tk avant de coller le presse-papiers est dû à un problème dans tkinter lui-même. Cela a été signalé à quelques reprises et il doit en raison de la façon paresseuse tkinter gère le presse-papiers.

Si quelque chose est défini dans le presse-papiers de tkinter mais n'est pas collé, tkinter n'ajoutera pas le presse-papiers de Windows avant la fermeture de l'application. Donc, un moyen de contourner cela est de dire à tkinter d'ajouter au presse-papiers de Windows.

J'ai testé une méthode pour cela, mais cela cause un certain retard dans le processus d'application, donc ce n'est probablement pas la meilleure solution mais c'est un début. Jetez un oeil à cette version modifiée de votre code en utilisant l'importation os avec la méthode system.

from tkinter import * 
from tkinter import messagebox 
import os 

top = Tk() 
top.geometry("400x75") 
top.title = "Get Test URL" 

url = 'http://testServer/feature/' 
fullURL = StringVar() 
fullURL.set(url) 

def copyToClipboard(): 
    top.clipboard_clear() 
    top.clipboard_append(fullURL.get()) 
    os.system('echo {}| clip'.format(fullURL.get())) 
    top.update() 
    top.destroy() 

def updateURL(event): 
    fullURL.set(url + featureNumber.get()) 

def submit(event): 
    copyToClipboard() 

topRow = Frame(top) 
topRow.pack(side = TOP) 
bottomRow = Frame(top) 
bottomRow.pack(side = BOTTOM) 
featureLabel = Label(topRow, text="Feature Number") 
featureLabel.pack(side = LEFT) 
featureNumber = Entry(topRow) 
featureNumber.pack(side = RIGHT) 
fullLine = Label(bottomRow, textvariable=fullURL) 
fullLine.pack(side = TOP) 
copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard) 
copyButton.pack(side = TOP) 
featureNumber.focus_set() 
featureNumber.bind("<Return>", submit) 

top.mainloop() 

Lorsque vous exécutez le code, vous verrez que le code gèle l'application mais une fois que son traitement de finition au bout de quelques secondes, il aura fermé l'application et vous pouvez encore coller le contenu de planchettes. Ce serveur montre que si nous pouvons écrire dans le presse-papiers de Windows avant que l'application tkinter soit fermée, cela fonctionnera comme prévu. Je chercherai une meilleure méthode mais cela devrait être un point de départ pour vous.

Voici quelques liens du même problème qui ont été signalés à tkinter.

issue23760

1844034fffffffffffff

732662ffffffffffffff

822002ffffffffffffff

MISE À JOUR:

Voici une solution propre qui utilise la bibliothèque pyperclip

Ceci est également multi-plateforme :)

from tkinter import * 
from tkinter import messagebox 
import pyperclip 

top = Tk() 
top.geometry("400x75") 
top.title = "Get Test URL" 

url = 'http://testServer/feature/' 
fullURL = StringVar() 
fullURL.set(url) 

def copyToClipboard(): 
    top.clipboard_clear() 
    pyperclip.copy(fullURL.get()) 
    pyperclip.paste() 
    top.update() 
    top.destroy() 

def updateURL(event): 
    fullURL.set(url + featureNumber.get()) 

def submit(event): 
    copyToClipboard() 

topRow = Frame(top) 
topRow.pack(side = TOP) 
bottomRow = Frame(top) 
bottomRow.pack(side = BOTTOM) 
featureLabel = Label(topRow, text="Feature Number") 
featureLabel.pack(side = LEFT) 
featureNumber = Entry(topRow) 
featureNumber.pack(side = RIGHT) 
fullLine = Label(bottomRow, textvariable=fullURL) 
fullLine.pack(side = TOP) 
copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard) 
copyButton.pack(side = TOP) 
featureNumber.focus_set() 
featureNumber.bind("<Return>", submit) 

top.mainloop() 
+0

Fonctionne parfaitement. Comme vous l'avez dit, il y a un peu de retard, mais je n'ai besoin de le faire qu'une ou deux fois par jour, donc ce n'est pas un problème. Merci! – TripleD

+0

Je suis content que cela fonctionne pour vous. Je chercherais toujours une meilleure méthode car le retard ne devrait pas se produire. –

+0

Le lien fourni par Bryan Oakly a également pointé vers une solution utilisant 'après' pour exécuter 'détruire' après un petit délai et revenir au circuit principal. Cela fonctionne, et n'a pas de retard, mais je ne suis pas un fan personnel de «retarder et espérer pour les meilleures» solutions. – TripleD