display pdf in sepearate window with python tkinter - python

I have a function checking if a tkinter listbox element is a pdf file. If so, it should be shown via "ShowPdf" in a new window. I only want to view the one pdf I have chosen.
Using the function once works fine. But if I switch to another listbox element and run the function again, the pdf from the first run and the second run are arranged behind each other. So I see the pdf from the first run at first followed by the second pdf. If I run it a third time, then all three pdfs are arranged behind each other etc.
Could you please help me so that only the current pdf is shown?
import tkinter as tk
from tkPDFViewer import tkPDFViewer as pdf
def OnEntryLeft(event):
cur_file=listb.get(listb.curselection())
if (cur_file[-4:]==".pdf" or cur_file[-4:]==".PDF"):
newWindow = tk.Toplevel(root)
pdf.ShowPdf().pdf_view(newWindow,pdf_location=cur_file,width=75,height=100).pack()
else:
messagebox.showinfo("PDF-Check", "NO pdf")

If you look into the source code of tkPDFViwer, you will notice that ShowPdf uses a class variable img_object_li (type list) to store the loaded pages from PDF file. Therefore ShowPdf.img_object_li will hold all the pages from those instances of ShowPdf. I think it is a design bug.
You need to clear the list before loading PDF file:
pdf.ShowPdf.img_object_li.clear() # clear loaded pages
pdf.ShowPdf().pdf_view(newWindow,pdf_location=cur_file,width=75,height=100).pack()

Related

Error when trying to merge two slide slides

How do you merge two slide slides saved as a PDF? Specifically, I want to know how to add a second slide to a first slide. I tried copying the code in a Python Udemy course while changing the variables' names, I found one solution online that looked very, very not concise, and I glanced at a stack overflow thread that ended in there maybe not being a solution. I got an error four times when running Udemy code that one of my PDFs was corrupted and never got a slide added to another slide. The expected output is a pdf file with two slides, one from each pdf file. Here's a very rough excerpt of my code (attached). Note, the practice presentations I tried to merge I called ~sept-1.pdf and second-page.pdf + I changed the username in the file path to eliminate my nickname.
Goal: Add the one and only slide from pdf 2 and add it to the end of pdf 1.
Import modules
!pip install PyPDF4 then import PyPDF4
Change directory to desktop
import os
os.getcwd()
os.chdir('/Users/mac_username_name/Desktop')
os.getcwd()
Stuff after chaging the directory to the desktop
Adding to my desired PDF
f = open('sept-1.pdf','rb')
pdf_reader = PyPDF4.PdfFileReader(f)
first_page = pdf_reader.getPage(0)
pdf_writer = PyPDF4.PdfFileWriter()
pdf_writer.addPage(first_page)
pdf_output = open("newer.pdf","wb")
pdf_writer.write(pdf_output)
f.close()

How to save DataFrame in the same location where the program will be

Hi I write program that will take many csv filles make three new structure for them.
After that program concat the same csv files in one structure depends of its name.
All this i done alredy but i need to save this three new files. I did it by using tkinter and it works, code look like this:
list_of_df = [completeDR,completeDS,completeDD,completeKL]
for i in list_of_df:
if not i.empty:
root = Tk() # this is to close the dialogue box later
try:
# with block automatically closes file
with filedialog.asksaveasfile(mode='w', defaultextension=".csv") as file:
i.to_csv(file.name, index = False)
except AttributeError:
# if user cancels save, filedialog returns None rather than a file object, and the 'with' will raise an error
print("The user cancelled save")
root.destroy() # close the dialogue box
This solutions work rly good but I have one problem. When I save files I need to named it but i dont know which one i save in this moment. I need solution that let me save files exacly in the same place where application will be run. Second option is to change name of title in tkinter winodw. If title will say me what i save right now there will be no problem anymore. Anyone have some ideas ? Thanks for help.

How do you get filenames and save and display there names in labels. KivyMD Kivy Python

I am trying to display file names on Kivy Buttons but I want to add a feature so when there is not txt file the Buttons don't show up but the more txt files that you have the more labels you have.
I have a system where you save text to a file a give the file a title so I want the user to know if this file exists. I currently have no knowledge on how to do this. My idea is when you press the button with the file name for example "test" it will display the text of the txt file but I don't know how to display the names of the txt files on the buttons and there might not be any txt files so you would have to hide the buttons. I am using KivyMD so those buttons would be preferred.
Here is a screenshot of the page that the buttons would be displayed on:
I hope the experts of python could help me out here.
Update:
files_list = [os.path.abspath(x) for x in os.listdir()]
for k in files_list:
type = mimetypes.MimeTypes().guess_type(k)[0]
if type == "text\plain":
MainScreen.add_widget(Button(text=k))
Use two screens approach. First screen for list of buttons and second for editing text.
import mimetypes, os
files_list = [os.path.abspath(x) for x in os.listdir()]
for k in files_list:
type = mimetypes.MimeTypes().guess_type(k)[0])
if type == "text\plain":
mylayout.add_widget(Button(text=k))
Here mylayout is a kivy layout depends upon how you want to arrange your buttons.
For displaying text, second screen would contain a label. Just read the text file and assign it to text property of label.

How to erase text from PDF using Python

I'm creating a python script to edit text from PDFs.
I have this Python code which allows me to add text into specific positions of a PDF file.
import PyPDF2
import io
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
import sys
packet = io.BytesIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
# Insert code into specific position
can.drawString(300, 115, "Hello world")
can.save()
#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PyPDF2.PdfFileReader(packet)
# read your existing PDF
existing_pdf = PyPDF2.PdfFileReader(open("original.pdf", "rb"))
num_pages = existing_pdf.numPages
output = PyPDF2.PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
page = existing_pdf.getPage(num_pages-1) # get the last page of the original pdf
page.mergePage(new_pdf.getPage(0)) # merges my created text with my PDF.
x = existing_pdf.getNumPages()
#add all pages from original pdf into output pdf
for n in range(x):
output.addPage(existing_pdf.getPage(n))
# finally, write "output" to a real file
outputStream = open("output.pdf", "wb")
output.write(outputStream)
outputStream.close()
My problem: I want to replace the text in a specific position of my original PDF with my custom text. A way of writing blank characters would do the trick but I couldn't find anything that does this.
PS.: It must be Python code because I will need to deploy this as a .exe file later and I only know how to do that using Python code.
A general purpose algorithm for replacing text in a PDF is a difficult problem. I'm not saying it can't ever be done, because I've demonstrated doing so with the Adobe PDF Library albeit with a very simple input file with no complications, but I'm not sure that pyPDF2 has the facilities required to do so. In part, just finding the text can be a challenge.
You (or more realistically your PDF library) has to parse the page contents and keep track of the changes to the graphic state, specifically changes to the current transformation matrix in case the text is in a Form XObject, and the text transformation matrix, and changes to the font; you have to use the font resource to get character widths to figure out where the text cursor may be positioned after inserting a string. You may need to handle standard-14 fonts which don't contain that information in their font resources (the application -your program- is expected to know their metrics)
After all that, removing the text is easy if you don't need to break up a Tj or TJ (show text) instruction into different parts. Preventing the text after from shifting, if that's what's desired, may require inserting a new Tm instruction to reposition the text after to where it would have been.
Inserting new text can be challenging. If you want to stay consistent with the font being used and it is embedded and subset, it may not necessarily contain the glyphs you need for your text insertion. And after insertion, you then have to decide whether you need to reflow the text that comes after the text you inserted.
And lastly, you will need your PDF library to save all the changes. Quite frankly, using Adobe Acrobat's Redaction features would likely be cheaper and more cost-effective way of doing this than trying to program this from scratch.
If you want to do a poor man's redaction with ReportLab and PyPDF2,
you would create your replacement content with ReportLab.
Given a Canvas, a rectangle indicating an area, a text string and a point where the text string would be inserted you would then:
#set a fill color to white:
c.setFillColorRGB(1,1,1)
# draw a rectangle
c.rect([your rectangle], fill=1)
# change color
c.setFillColorRGB(0,0,0)
c.drawString([text insert position], [text string])
save this PDF document you've created to a temporary file.
Open this PDF document and the document you want to modify using the PyPDF2's PdfFileReader. create a pdfFileWriter object, call it ModifiedDoc. Get page 0 of temporary PDF, call it updatePage. Get page n of the other document, call it toModifyPage.
toModifyPage.mergePage(updatePage)
after you are done updating pages:
modifiedDoc.cloneDocumentFromReader(srcDoc)
modifiedDoc.write(outStream)
Again, if you go this route, a user might still see the original text before it gets covered up with the new content, and text extraction would likely pull out both the original and new text for that area, and possibly intermingle it to something unintelligible.

Implement a dynamic dropdown menu based on on the number of lines of text file

I am trying to achieve a dropdown which changes dynamically based on the number of lines of text file.
I can find the number of lines using:
with open('Cipher 3.5 Output.txt') as f:
Line_Count = (sum(1 for _ in f))
What I am then trying to do is make the dropdown have an option for each line in the file, for example if the file has three lines the dropdown will have the options 1, 2 and 3.
I am trying to achieve this so that in my encryption program the user can choose which line of their encrypted text file to read and decrypt.
Currently my interface looks like this:
I am planning to add a label between Key2 and Output which reads 'Choose line' or something to that effect, and then a dropdown box between the two Entry boxes. Finally I will add a button between the Random Key and Clear buttons which will set the line number to 'all' and read the whole file.
So, how can I implement the dynamically changing dropdown? Your help is appreciated.
I very much doubt you'll need it but see Here for the rest of my code.
You can use a ttk.Combobox to let the user choose a line and you can associate a command with the click of the Button Encrypt. In this command (function) you will put the code that calculates the lines and you will update there the values of the ttk.Combobox. If you are using Python 3 (I hope), you can import the ttk.Combobox in the following way:
from tkinter.ttk import Combobox
Comboboxes are part of the tkinter extension ttk, you have explicitly to say you want to import from that module.
If you are using Python 2, you can simply import from ttk:
from ttk import Combobox
Now, suppose the following is the code for the Button Encrypt:
encrypt = Button(master, text='Encrypt')
Then you can associate a command with the click of a Button in the following way:
encrypt = Button(master, text='Encrypt', command=on_click) # without ( )
Now, you can define the function on_click:
def on_click():
# calculate the lines
# update the values of the Combobox

Categories

Resources