How to automate parse.unquote(), .clipboard_append() etc. in Python - tkinter - python

I'm trying to make a link slicer that automatically slice and copy the sliced output of the link right after I pasted it on txt = Entry(window,width=50) without clicking a button.
When I paste a link something like this: http://url.io/s/1234abcd/?s=https%3A%2F%2Fexample.com%2Fsome_contens%2F then it will become: example.com/some_contents/
Right now the code below is what I use, but I still have to click the "slice" button before "slicing" and "copying" happens.
from tkinter import *
from urllib import parse
from tkinter import Tk
window = Tk()
window.title("Link Slicer")
window.geometry('344x50')
lbl = Label(window, text="Link")
lbl.grid(column=0, row=1)
txt = Entry(window,width=50)
txt.grid(column=0, row=0)
def clicked():
sliced = txt.get()
sliced = parse.unquote(sliced)
lbl.configure(text= sliced[36:])
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(sliced[36:])
r.update()
btn = Button(window, text="Slice", command=clicked)
btn.grid(column=1, row=0)
window.mainloop()
I made this code below to try to automate "slicing" and "copying" right after I paste the link in the txt = Entry(window,width=50) without clicking a button (which doesn't work):
from tkinter import *
from urllib import parse
from tkinter import Tk
window = Tk()
window.title("Link Slicer")
window.geometry('344x50')
lbl = Label(window, text="Link")
lbl.grid(column=0, row=1)
txt = Entry(window,width=50)
txt.grid(column=0, row=0)
sliced = txt.get() // 1. automatically get what's in txt = Entry(window,width=50)
sliced = parse.unquote(sliced) // 2. auto-slice
r = Tk() }
r.withdraw() }
r.clipboard_clear() } // 3. auto-copy
r.clipboard_append(sliced[36:]). }
r.update() }
window.mainloop()

Since you always want to operate on the clipboard contents there's no need to even paste the clip into the Entry. You can just grab the clip, transform it, and put it back into the clipboard. I've included an Entry to display the result, but that's not really necessary.
import tkinter as tk
from urllib import parse
root = tk.Tk()
root.title("Link Slicer")
root.geometry('344x50')
root.attributes("-topmost", True)
def clicked():
clip = root.clipboard_get()
clip = parse.unquote(clip)[36:]
root.clipboard_clear()
root.clipboard_append(clip)
entry_text.set(clip)
entry_text = tk.StringVar()
txt = tk.Entry(root, textvariable=entry_text, width=50)
txt.pack()
btn = tk.Button(root, text="Slice", command=clicked)
btn.pack()
root.mainloop()
When I copy the sample URL from your question and click the Slice button I get this result displayed in the Entry and copied to the clipboard. Note that I did not paste the URL into the Entry, I just clicked the button.
example.com/some_contens/
I've included root.attributes("-topmost", True) to force the window to stay above other windows, because I think that's convenient for a tool like this.
As I mentioned in the comments, you should not call Tk() more than once because each call starts a new instance of the Tcl interpreter, which can lead to confusing behaviour (and it's a waste of resources).

Related

Set width of entry object in an optimal way the string is fully visible

I have following code:
from tkinter import *
from tkinter import simpledialog
def resize(lbl):
USER_INP = simpledialog.askstring(title="User input",
prompt="Please enter your message here:")
lbl['state'] = 'normal'
lbl.insert(0, f"Text was \'{USER_INP}\'.")
lbl['state'] = 'readonly'
lbl['width'] = 50
top = Tk()
lbl_entry = Entry(top, state="readonly", justify='center', width=10)
lbl_entry.grid(column=0, row=1)
bt_adjust = Button(top, text = "Resize Entry", command=lambda:resize(lbl_entry))
bt_adjust.grid(column=0, row=0)
top.mainloop()
After pressing the button bt_adjust the width of the Entry object is adjusting automatically. Is their a way to set the width dynamically in that way the text is fully displayed on the Entry element but if the width would be a little smaller the text wouldn't be fully displayed anymore?
Does this help? By using len() to adjusting automatically resizing.
After pressing the button bt_adjust the width of the Entry object is
adjusting automatically.
code in line 10:
lbl['width'] = f'{len(USER_INP)}
Screenshot before resizing:
AScreenshot after resizing:

Tkinter: Skip through PDFs in GUI

I am very new to python and want to build a gui that lets you skip through different pdfs. I managed to display the first pdf. My problem now is that I could not manage to display the second pdf and all following. If I only repeat the command to display the pdf, the new pdf gets displayed next to the old one, instead of replacing it. I have been through several hours of extensive googling and could not find out how to solve this. Can someone maybe help?
Here's my code:
from tkinter import *
import tkinter as tk
import glob
from tkPDFViewer import tkPDFViewer as pdf
from tkdocviewer import *
parent_path = 'somepath\\'
doc_list = glob.glob((parent_path + "*//*.pdf"))
doc_counter = 0
root = tk.Tk()
root.title('Training Data Creator')
root.geometry("1000x1000")
frame_r = Frame(root, relief=RAISED, borderwidth=1)
frame_r.pack(fill=BOTH, expand=True, side=tk.LEFT)
# creating object of ShowPdf from tkPDFViewer.
pdf_show = pdf.ShowPdf()
# Adding pdf location and width and height.
V_pdf = pdf_show.pdf_view(master=frame_r,
pdf_location=(doc_list[doc_counter]),
width=90, height=100)
V_pdf.pack(side=tk.LEFT)
#button skip
def skip_callback():
global doc_counter
doc_counter = doc_counter +1
# Here I want to display the next PDF!!
V_pdf = pdf_show.pdf_view(master=frame_r,
pdf_location=(doc_list[doc_counter]),
width=90, height=100)
V_pdf.pack()
print(doc_counter)
button_skip = Button(root, text='skip', command= skip_callback)
button_skip.pack(fill=tk.X, pady=0)
root.mainloop()
When I hit the 'skip' button, the next pdf from the 'parent_path' is supposed to appear where the initial one was displayed.
Thanks for your help!
Flo
I have looked into tkPDFViewer's code and the ShowPdf class has not been designed to load a new document after the initial one.
The reason why the second file is displayed next to the first one is that pdf_show.pdf_view() creates a new Frame which is then packed on the right of the previous one. So you need to destroy the old one first with
pdf_show.frame.destroy()
Then, I have noticed that instead of displaying the second document when clicking on the skip button, what is displayed is a concatenation of both documents. This can be solved by clearing the image list of pdf_show
pdf_show.img_object_li.clear()
Here is the full code:
import tkinter as tk
import glob
from tkPDFViewer import tkPDFViewer as pdf
parent_path = '/home/juliette/Documents'
doc_list = glob.glob((parent_path + "*//*.pdf"))
doc_counter = 0
root = tk.Tk()
root.title('Training Data Creator')
root.geometry("1000x1000")
frame_r = tk.Frame(root, relief=tk.RAISED, borderwidth=1)
frame_r.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
# creating object of ShowPdf from tkPDFViewer.
pdf_show = pdf.ShowPdf()
# Adding pdf location and width and height.
V_pdf = pdf_show.pdf_view(master=frame_r,
pdf_location=(doc_list[doc_counter]),
width=90, height=100)
V_pdf.pack(side=tk.LEFT)
#button skip
def skip_callback():
global doc_counter
doc_counter = doc_counter +1
# Reset view:
pdf_show.frame.destroy()
pdf_show.img_object_li.clear()
# Display new pdf
V_pdf = pdf_show.pdf_view(master=frame_r,
pdf_location=(doc_list[doc_counter]),
width=90, height=100)
V_pdf.pack(side=tk.LEFT)
print(doc_counter)
button_skip = tk.Button(root, text='skip', command= skip_callback)
button_skip.pack(fill=tk.X, pady=0)
root.mainloop()
By the way, you are importing tkinter twice:
from tkinter import *
import tkinter as tk
so I advise you to choose one of the ways to import it and stick with it, rather than mixing both. Furthermore, I suggest you to use import tkinter as tk, this way you will not crowd the namespace with a large amount of unknown names that can lead to naming conflicts (e.g. if you import Image from PIL and then do from tkinter import *, Image will be the tkinter class, not the PIL one).

Tkinter how to lock Text widget by checking checkbox?

I am new to programming and Tkinter. I want to DISABLED textbox when checkbox is pressed and open it NORMAL when box is not ticked. Here is my code:
from tkinter import *
root = Tk()
def lock_fields():
if check == True:
data.configure(state=DISABLED)
if check == False:
data.configure(state=NORMAL)
check = BooleanVar()
open_for_edit = Checkbutton(root, text="check the box for editing", variable=check,
onvalue=True, offvalue=False, command=lambda: lock_fields())
open_for_edit.pack()
check = check.get()
data = Text(root)
data.insert(END, "I would like to be able to edit this text only when checkbox is checked.")
data.pack()
root.mainloop()
It seems that for some reason the check-variable is always False when it enters to lock_fields function. I tried passing check argument to the method.
You're pretty close, only thing is that the check.get() line must be in the function. Also you don't need the lambda. Try this:
from tkinter import *
root = Tk()
def lock_fields():
if check.get():
data.configure(state=DISABLED)
else:
data.configure(state=NORMAL)
check = BooleanVar()
open_for_edit = Checkbutton(root, text="check the box for editing", variable=check, onvalue=True, offvalue=False, command=lock_fields)
open_for_edit.pack()
data = Text(root)
data.insert(END, "I would like to be able to edit this text only when checkbox is checked.")
data.pack()
root.mainloop()

How to get the entry text and display in another entry?

I just want that when I type my name inside the entry box then appears in another entry with some add text. The idea is type in the entry below and after that it showed in the big entry.I was looking for this solution, but just found place in Label. I don't want in Label. The window is more big, must drag to show the entry. There's is a picture that i use in this script:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
cat = Entry(root)
cat.place(x=48, y=25, width= 350, height=140)
user = Entry(root)
user.place(x=75, y=550)
btn = Button(root, text='START')
btn.place(x=220, y=410)
root.mainloop()
#
Ok, It works the way you told me,thank you!
But now i'm facing another problem.
The problem is when i insert the function of the game in the second window. I tested in one window and it works, but when i place the function in the second window gives an error when i press the "Start" button:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
When i press reset button gives another error:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
So i know that is missing definition, but i don't know how to make a reference for this command that it's in the second window. Like i said running with just one window the program works.
Maybe i should make using class, i don't know, but i wish to make this way that i started. However if there's no other way to do as i'm doing, let's go.
I just simplify the script here, actualy the main script is more bigger, so my idea is when open the program, there is a window and the user read the instructions about the game and proceed open the second window. The window have pictures and some hidden buttons in the next picture, so there will be an interactivity with the environment.
The guess number is just the beggining. After that there will be new challeges.
I'm very excited doing this, but i'm stuck in this point. The part one i finished, the pictures, the hidden buttons it's exacly the way i want, but the challenge stops here in this problem.
from tkinter import *
from PIL import Image, ImageTk, ImageSequence
import random
from tkinter import messagebox
pc = random.randint(1,10)
def reset():
global pc
pc = random.randint(1,10)
cat['text'] = 'Ok! Lets Try Again!'
def openwin2():
win1.withdraw()
win2 = Toplevel()
win2.geometry('350x300+180+100')
win2.title('second window')
txt = Entry(win2)
txt.place(x=10,y=10)
cat = Label(win2,wraplength=300)
cat.place(x=10,y=50)
cat.config(text='Hi! I Am thinking a number between 1 and 10.')
btn = Button(win2,text='start',command=check)
btn.place(x=30, y=150)
btn2 = Button(win2, text='reset', command=reset)
btn2.place(x=110,y=150)
win2.mainloop()
def check():
user_try = int(txt.get())
if user_try < pc:
msg = 'Hmmmm... the number, which I thought of, is greater than this.'
elif user_try > pc:
msg = 'How about trying a smaller number ?!'
elif user_try == pc:
msg = 'Well Done! You guessed! It was %s the number!' % user_try
else:
msg = 'Something Went Wrong...'
cat['text'] = msg
win1 = Tk()
win1.title('First Window')
win1.geometry('350x300')
user = Label(win1,text='first window')
user.place(x=10,y=10)
btn1 = Button(win1,text='Open Window 2', command=openwin2)
btn1.place(x=10,y=50)
win1.mainloop()
There are multiple ways to do this in tkinter, here's a rework of your code using StringVar objects set to the textvariable properties of your Entry objects:
import tkinter as tk
def doit():
out_string.set("Hello " + in_string.get())
root = tk.Tk()
in_string = tk.StringVar()
out_string = tk.StringVar()
cat = tk.Entry(root, textvariable=in_string)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root, textvariable=out_string)
user.place(x=20, y=75)
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
Per #Mike-SMT, here's a different approach using Entry.get() and Entry.insert(). It augments the text when the user clicks the button:
import tkinter as tk
def doit():
user.insert(tk.END, cat.get())
root = tk.Tk()
cat = tk.Entry(root)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root)
user.place(x=20, y=75)
user.insert(0, "Hello ")
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
However, you'll see that subsequent button clicks keep appending the text. When working with Entry.insert(), you need to work with Entry.delete() and/or other Entry methods to properly manipulate the text.

Can this be done more than once?

from tkinter import *
from tkinter import ttk
import webbrowser
import urllib
root = Tk()
w = Label(root, text="Where can I take you?")
w.pack()
url = 'http://sampdm.net/member.php?action=profile&uid=1'
def Openurl(url):
webbrowser.open_new(url)
button = Button(root, text = "Open Owners Profile #1", command = lambda:
Openurl(url))
button.pack()
root.mainloop()
Is there any way to make another button with another link like it?
I know there will be but I can't seem to figure out
From reading the comments it looks like you are not sure how to create multiple buttons inside your Tkinter window.
Its really easy and all you need to do is repeat the process that you used to create your first button.
I will provide 2 examples.
Here is how you can create each button manually for each website you wish to provide a button for.
from tkinter import *
import webbrowser
root = Tk()
url = 'http://sampdm.net/member.php?action=profile&uid=1'
url2 = 'www.google.com' # assign any variable name you want.
some_other_url = 'https://www.yahoo.com/'
def Openurl(url):
webbrowser.open_new(url)
w = Label(root, text="Where can I take you?")
w.pack()
# Here you can keep creating buttons using the same method as the first button.
# Just make sure you assign the correct url variable to the command.
button = Button(root, text = "Open Owners Profile #1", command = lambda: Openurl(url)).pack()
button2 = Button(root, text = "Open Google", command = lambda: Openurl(url2)).pack()
some_other_button = Button(root, text = "Open something else", command = lambda: Openurl(some_other_url)).pack()
root.mainloop()
Here is an example where your buttons are created from a list. This is a simple example but it should be enough to illustrate how it can be done.
from tkinter import *
import webbrowser
root = Tk()
# Here we create a list to use in button creation.
url_list = ['www.google.com', 'www.yahoo.com']
w = Label(root, text="Where can I take you?")
w.pack()
def Openurl(url):
webbrowser.open_new(url)
def create_buttons():
for url in url_list: # for each string in our url list
# creating buttons from our for loop values that will pack
# in the order they are created.
Button(root, text = url, command = lambda u = url: Openurl(u)).pack()
create_buttons()
root.mainloop()

Categories

Resources