I am trying to integrate a python code I found here on SO by a user @srccircumflex, his code is for tkinter
and I tried to modify it because I'm using customtkinter
His code was using class PassEntry(Entry):
so I replaced it with class PassEntry(ctk.CTkEntry):
also inside the class I replaced Entry
with ctk.CTkEntry
I am a beginner in python and below is what I have so far
import customtkinter as ctk
import tkinter as tk #using messagebox
from tkinter import filedialog
from tkinter import END, INSERT, SEL_FIRST, SEL_LAST
import PyPDF2
from PyPDF2 import PdfWriter
from sys import platform
from typing import Iterable
merger = PdfWriter()
def merge_pdfs():
#code to merge pdf files
file_password = entry_password.getpass()
...
#PASSENTRY # Copyright (c) 2022 Adrian F. Hoefflin [srccircumflex] ------------------------------
class PassEntry(ctk.CTkEntry):
def __init__(self,
master,
show: chr = "*",
delay: int = 800,
getpass_range: Iterable = None,
getpass_call: ... = None,
getpass_del: bool = False,
**tk_kwargs,
):
"""
Password entry with delayed hiding. Alternative to `Entry(master, show="*")'.
Supports all common character sets(1aA!), multy keys(^`˝) and under Linux also the alternative graphics(↑Ωł).
{Deletes the input from the widget and writes it casually into a variable. Markings and the position
of the cursor is respected.}
howto get the password:
- by protected member self._password
- by calling self.getpass (args `getpass_*' executed here)
- by calling self.get (args `getpass_*' executed here)
:param master: root tk
:param show: displayed char
:param delay: hiding delay
:param getpass_range: check password length
:param getpass_call: callable, gets `self._password' as argument
:param getpass_del: delete `self._password' and flush entry if True
:param tk_kwargs: Valid resource names: background, bd, bg, borderwidth, cursor, exportselection, fg, font, foreground, highlightbackground, highlightcolor, highlightthickness, insertbackground, insertborderwidth, insertofftime, insertontime, insertwidth, invalidcommand, invcmd, justify, relief, selectbackground, selectborderwidth, selectforeground, state, takefocus, textvariable, validate, validatecommand, vcmd, width, xscrollcommand
"""
self._password: str = ""
self.delay: int = delay
self.show: chr = show
self.getpass_range: Iterable = getpass_range
self.getpass_call: ... = getpass_call
self.getpass_del: bool = getpass_del
ctk.CTkEntry.__init__(self, master, **tk_kwargs)
self.bind("<Key>", self._run)
self.bind("<Button>", self._run)
self._external: bool = False
self.get = self.getpass
if platform == "linux":
# (
# MultyKeys, ^ ` ọ ˇ
# NoModifier, a b c d
# Shift+Key, A B C D
# AltGr+Key(AT-Layout), @ ł | ~
# AltGr+Shift+Key(AT-Layout) Ω Ł ÷ ⅜
# )
self._states = (0, 16, 17, 144, 145)
elif platform == "win32":
# (
# AltGr+Key(AT-Layout), @ \ | }
# NoModifier, a b c d
# Shift+Key, A B C D
# )
self._states = (0, 8, 9)
def _char(self, event) -> str:
def del_mkey():
i = self.index(INSERT)
self._delete(i - 1, i)
if event.keysym in ('Delete', 'BackSpace'):
return ""
elif event.keysym == "Multi_key" and len(event.char) == 2: # windows stuff
if event.char[0] == event.char[1]:
self.after(10, del_mkey)
return event.char[0]
return event.char
elif event.char != '\\' and '\\' in f"{event.char=}":
return ""
elif event.num in (1, 2, 3):
return ""
elif event.state in self._states:
return event.char
return ""
def _get(self):
return self.tk.call(self._w, 'get')
def _delete(self, first, last=None):
self.tk.call(self._w, 'delete', first, last)
def _insert(self, index, string: str) -> None:
self.tk.call(self._w, 'insert', index, string)
def _run(self, event):
if self._external and self._char(event):
self._external = False
self.clear()
def hide(index: int, lchar: int):
i = self.index(INSERT)
for j in range(lchar):
self._delete(index + j, index + 1 + j)
self._insert(index + j, self.show)
self.icursor(i)
if event.keysym == 'Delete':
if self.select_present():
start = self.index(SEL_FIRST)
end = self.index(SEL_LAST)
else:
start = self.index(INSERT)
end = start + 1
self._password = self._password[:start] + self._password[end:]
elif event.keysym == 'BackSpace':
if self.select_present():
start = self.index(SEL_FIRST)
end = self.index(SEL_LAST)
else:
if not (start := self.index(INSERT)):
return
end = start
start -= 1
self._password = self._password[:start] + self._password[end:]
elif char := self._char(event):
if self.select_present():
start = self.index(SEL_FIRST)
end = self.index(SEL_LAST)
else:
start = self.index(INSERT)
end = start
self._password = self._password[:start] + char + self._password[end:]
self.after(self.delay, hide, start, len(char))
def insert(self, index, string: str) -> None:
self._external = True
self.tk.call(self._w, 'insert', index, string)
def delete(self, first, last=None) -> None:
self._external = True
self.tk.call(self._w, 'delete', first, last)
def clear(self):
del self._password
self._password = ""
self._delete(0, END)
def getpass(self):
password = self._password
if self.getpass_range:
assert len(self._password) in self.getpass_range, f'## Password not in {self.getpass_range}'
if self.getpass_call:
password = self.getpass_call.__call__(self._password)
if self.getpass_del:
del self._password
self._password = ""
self._delete(0, END)
return password
#PASSENTRY----------------------------------------------------------------------------------
if __name__ == "__main__":
#main window
root = ctk.CTk()
root.title("Merge PDF")
#Create user input entry for filename
...
#Create user input entry for optional password
entry_password = PassEntry(
master=root,
width=200,
height=40,
border_width=1,
fg_color="white",
placeholder_text="OPTIONAL: Enter password...",
text_color="black",
font=('Arial Rounded MT Bold', 14))
entry_password.grid(row=2, column=0, padx=20, pady=(10,20))
# Create a button to merge the selected PDF files
...
root.mainloop()
ctk.CTkEntry.__init__(self, master, tk_kwargs)
should bectk.CTkEntry.__init__(self, master, **tk_kwargs)
instead. – MolliemollifyCTkEntry
does not inherit fromEntry
directly, so something works forEntry
may not work. – Molliemollify