Using .split with tkinter - python

Quite a beginner here. I have a command line script that works fine for what I do and I'm looking to move it into a GUI.
os.chdir(ImageDirST)
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
print(f, "-->", n_name)
I would like this to display in the same fashion within a message window in tkinter.
With some help from here, I managed to print the filenames in the directory when a button is pushed with:
filenames = sorted(os.listdir(ImageDirBT))
text = "\n".join(filenames)
print_filename_test.set(text)
I have tried to use my split code to setup a list of what the new filenames would look like, prior to setting the variable, with the following, where print_filenames() is the function triggered by the press of a button.
def print_filenames():
filenames = sorted(os.listdir(ImageDirBT))
for filenames in sorted(os.listdir(ImageDirBT)):
f_name,f_ext = (os.path.splitext(filenames))
f_sku = (f_name.split('_')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
newlist = "\n".join(n_name)
print_filename_test.set(newlist)
I don't get any errors with this code for print_filenames(), however what is displayed in the message panel is the last filename in the list, vertically, one character wide:
eg:
F
I
L
E
_
1
1
.
e
x
t
I would like to display the output as:
oldfilename_01.ext --> newfilename_csvdata_01.ext
oldfilename_02.ext --> newfilename_csvdata_02.ext
oldfilename_03.ext --> newfilename_csvdata_03.ext
oldfilename_04.ext --> newfilename_csvdata_04.ext
The command line program I have written uses numbers to chose menu options for what needs to be done, confirming before any renaming is done, hence printing the file name comparisons. My struggle is manipulating the strings in the list to be able to do the same thing.

Using messagebox:
import os
import tkinter as tk
from tkinter import messagebox
ImageDirST = r"your_path"
os.chdir(ImageDirST)
root = tk.Tk()
names = []
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
names.append(f"{f} --> {n_name}\n")
messagebox.showinfo(title="Something", message="".join(names))
root.mainloop()
Or using Text widget with scrollbar:
import os
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
ImageDirST = r"your_path"
os.chdir(ImageDirST)
root = tk.Tk()
txt = ScrolledText(root, font="Arial 8")
txt.pack()
for f in sorted(os.listdir(ImageDirST)):
f_name,f_ext = (os.path.splitext(f))
f_sku = (f_name.split(' ')[0])
f_num = (f_name[-2:])
n_name = ('{}_{}{}'.format(f_sku,f_num,f_ext))
txt.insert("end",f"{f} --> {n_name}\n")
root.mainloop()

Related

Python - tkinter askopenfilename function somehow stays active while selecting the file "directly" doesn't

I'm not a programmer so admittingly my title might be a bit off.
I have a program where I select an IFC-file (used in the construction industry, which contains data about the geometry and data connected to the objects in the 3D drawing) and then a dialog opens where I can add a GUID (an identifier) and search for all the information related to that object in the IFC-file, which I then print in the command prompt.
A minor issue which annoys me a bit is that the when is select the file in a more flexible way, using askopenfilename, the function seems to stay active or in a loop after I close the later opening dialog, so that I have to end the process using CTRL+C.
I post the entire code as I don't know if there is something else which causes it:
#imports to search for files
import os
# imports tkinter for selection purposes, so that one can select the files instead of reading in them automaticall from a directory
import tkinter as tk
from tkinter.filedialog import askopenfilename
#importing the counter to counte the occurences in a list
from collections import Counter
#importing regex functionality to check values
import re
#this is the numbering, for example #433, #4781 etc, that we either want to look for or change - now it looks for up to a number of length 7
regexIFCnumbers = '#\d{1,7}'
tk.Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
file1 = askopenfilename(initialdir=os.getcwd()) # show an "Open" dialog box and return the path to the selected file - this in the current directory where we'll start looking
file1Name = (os.path.basename(file1)) #only the file's name
#read files
def readFile(file):
x = []
f = open(file, 'r')
x = f.readlines()
f.close()
return(x)
x1 = readFile(file1)
#checks the GUIDs
def checkGUID(GUID, IFC):
A = []
for row in IFC:
if GUID in row:
#print(re.findall(regexIFCnumbers, row))
A.extend(re.findall(regexIFCnumbers, row))
return(A)
#the numbering is not perfectly ordered and varies in some places, so need to index it all to find the correct lines
def indexIFC(IFC):
A = []
for index, row in enumerate(IFC):
if re.findall('^#', row): #starts with a hash #
B = re.findall(r'\#\w+', row)[0]
A.append([B, index])
return(A)
def recurseThrough(inputList, IFC, checkedList, fullList, indexednumbersList):
for item in inputList:
for hashvalueList in indexednumbersList:
if item == hashvalueList[0]:
positionInIFC = hashvalueList[1]
if re.search('^'+item, IFC[positionInIFC]) and item not in checkedList: #if the row begins with the number item in the list
checkedList.append(item)
fullList.append(IFC[positionInIFC])
recurseThrough(re.findall(regexIFCnumbers, IFC[positionInIFC])[1:], IFC, checkedList, fullList, indexednumbersList) #recurses through the next list
return(fullList)
from os import system, name
def clear():
if name == 'nt':
_ = system('cls')
def runTheGUIDCheck(setValue):
inputValue = str(setValue)
print(inputValue)
clear()
try:
B1 = checkGUID(inputValue, x1) #This returns a list with for example [#122, #5, #7889]
checkedList = [] #the list of already checked items
fullList = []
indexedIFClist1 = indexIFC(x1)
#run the function with the initial input, sending in empty array as well as they should be empty/none at the start
outList1 = recurseThrough(B1, x1, [], [], indexedIFClist1)
for index, item in enumerate(outList1):
print(index, item.strip())
return None
except:
print("inserted GUID not found or didn't work")
#dialog
dialog = tk.Tk()
dialog.geometry('500x200')
t1 = tk.Label(dialog, text = 'Check GUID')
t1.grid(row = 0, column = 0, sticky = 'w')
testGUIDAttributes = tk.Entry(dialog, width = 40)
testGUIDAttributes.grid(row = 0, column = 1, columnspan = 50)
button = tk.Button(dialog, text='Run GUID', command = lambda: runTheGUIDCheck(testGUIDAttributes.get()))
button.grid(row = 5, column = 0, sticky = 'w')
dialog.mainloop()
If I select the file directly like this...
file1 = 'thefile.ifc'
instead of with the above this...
tk.Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
file1 = askopenfilename(initialdir=os.getcwd()) # show an "Open" dialog box and return the path to the selected file - this in the current directory where we'll start looking
then this issue doesn't come up and the command prompt will accept new commands after I close the dialog which is "created" at the end.
Since you have created two instances of Tk(): one in the line tk.Tk().withdraw() and one in the line dialog = tk.Tk(), so the line dialog.mainloop() will not return until both windows are closed. However you cannot close the withdrawn window because it is invisible.
You should create only one instance of Tk(), hide it and then show the file dialog. Then show it back and proceed as normal:
...
# create the main window and hide it initially
dialog = tk.Tk()
dialog.withdraw()
file1 = askopenfilename(initialdir=os.getcwd()) # show an "Open" dialog box and return the path to the selected file - this in the current directory where we'll start looking
...
# show back the main window
dialog.deiconify()
dialog.geometry('500x200')
...
dialog.mainloop()

Pypdf2 merger function and startswith

first time coder here. I'm trying to create a program to help automate some of my work in the office using python.
what I'm trying to do is to merge pdf file from Folder 1, with another pdf file from folder 2 with the same name. I also would like to use Tkinter gui
this is what I get so far
from tkinter import *
from PyPDF2 import PdfFileMerger
root = Tk()
# Creating a Label Widget
MainLabel = Label(root, text="PDF Rawat Jalan")
# Shoving it onto the screen
MainLabel.pack()
#Prompt Kode
KodeLabel = Label(root, text="Masukan Kode")
KodeLabel.pack()
#Input Kode
kode = Entry(root, bg="gray",)
kode.pack()
#function of Merge Button
def mergerclick():
kode1 = kode.get()
pdflocation_1 = "C:\\Users\\User\\Desktop\\PDF\\Folder 1\\1_"+kode1+".pdf"
pdflocation_2 = "C:\\Users\\User\\Desktop\\PDF\\Folder 2\\2_"+kode1+".pdf"
Output = "C:\\Users\\User\\Desktop\\PDF\\output\\"+kode1+".pdf"
merger = PdfFileMerger()
merger.append(pdflocation_1)
merger.append(pdflocation_2)
merger.write(open(Output, 'wb'))
confirmation = kode1 +" merged"
testlabel = Label(root, text=confirmation)
testlabel.pack()
#Merge Button
mergerButton = Button(root, text= "Merge", command=mergerclick)
mergerButton.pack()
root.mainloop()
Now there is a third file i'm supposed to append, but the third file i'm supposed to append has date in its file name. for example: file 1 (010.pdf); file 2 (010.pdf); file 3 (010_2020_10_05).
There is like 9000 file per folder
How I'm supposed to do this?
I think what you need is a way to just find files prefixed with a particular string. Based on the date suffix I'm guessing the file names may not be unique so I'm writing this to find all matches. Something like this will do that:
import pathlib
def find_prefix_matches(prefix):
dir_path = pathlib.Path(directory_name)
return [str(f_name) for f_name in dir_path.iterdir()
if str(f_name).startswith(prefix)]
If you are just learning to write code, this example is relatively simple. However it is not efficient if you need to match 9,000 files at the same time. To make it run faster you'll want to load the file list once instead of per request.
import pathlib
def find_prefix_matches(prefix, file_list):
return [f for f in file_list if f.startswith(prefix)]
file_list = [str(f_name) for f_name in dir_path.iterdir()]
for file_name_prefix in your_list_of_files_to_append:
file_matches = find_prefix_matches(file_name_prefix, file_list)

how to connect gui and main code in python

I wanna make a dictionary program that could be run every platform. I coded it and it works basically, the user selects a word with a double click before clicking 'Q' and it gives selected word definition. Then I need a GUI. I made it but I couldn't connect them.
dict.txt's example : https://i.stack.imgur.com/Z9WMJ.png
Sceptral (a.) Of or pertaining to a scepter; like a scepter.
Scern (v.t.) To discern; to perceive.
Schade (n.) Shade; shadow.
Schah (n.) SeeShah.
Schediasm (n.) Cursory writing on a loose sheet.
main code;
import pyautogui as pya
import pyperclip
import time
import keyboard
import re
import sys
liste = list()
def copy_clipboard():
time.sleep(5)
pya.hotkey('ctrl', 'c')
time.sleep(.01)
return pyperclip.paste()
def click(key, *args,**kwargs): #
oldword = pyperclip.paste()
time.sleep(.01)
pya.hotkey('ctrl','c')
newword = pyperclip.paste()
time.sleep(.01)
pyperclip.copy(oldword)
capitalizing = newword.capitalize()
delete_space = capitalizing.strip()
word = delete_space
print(word)
file = open('dict.txt', 'r')
for line in file:
if word == line.split(" ")[0]:
letters = re.sub(word, " ", line)
liste.append(letters)
print(liste)
file.close()
while True:
try:
if keyboard.on_press_key('q',click):
print('You Pressed a Key!')
sleep(.01)
break
else:
pass
except:
break
gui;
import tkinter as tk
window = tk.Tk()
window.geometry("300x400+1200+200")
window.title("dict")
#window.wm_attributes("-alpha")
button = tk.Button(text = "Yuppi")
button.pack()
sbr = tk.Scrollbar(window)
sbr.pack(side=tk.RIGHT,fill="y")
text1 = tk.Text(window)
text1.insert(tk.INSERT, liste)#letters or liste has to be here
text1.pack()
window.mainloop()
Unfortunately connecting a GUI to a backend program requires a overhaul of the backend code. When you make a Tkinter GUI, a lot of the controls that you would usually use in backend, such as "print (…)" becomes more complicatd with tk.Label(window, text=…).place(x=x,y=y). So you will essentially have to incorporate your GUI into your backend code.

Python pass variable values in functions

So this is my full code. All I want is append excel files to one excel by sheets from a specific folder. It's GUI and has 3 buttons browse, append, and quit. How do i get path value from browsed folder(filename) ? thanks
from tkinter import *
from tkinter.filedialog import askdirectory
import tkinter as tk
import glob
import pandas as pd
import xlrd
root = Tk()
def browsefunc():
filename = askdirectory()
pathlabel.config(text=filename)
return filename
def new_window():
all_data = pd.DataFrame()
all_data1 = pd.DataFrame()
path = browsefunc()+"/*.xlsx"
for f in glob.glob(path):
df = pd.read_excel(f,sheetname='Scoring',header=0)
df1 = pd.read_excel(f,sheetname='Sheet1',header=0)
all_data = all_data.append(df,ignore_index=False)
all_data1 = all_data1.append(df1,ignore_index=True)
writer = pd.ExcelWriter('pandas_simple.xlsx', engine='xlsxwriter')
all_data.to_excel(writer, sheet_name='Scoring')
all_data1.to_excel(writer, sheet_name='Sheet1')
writer.save()
browsebutton = Button(root, text="Browse", command=browsefunc).pack()
Button(root, text='Append', command=new_window).pack()
Button(root, text='quit', command=root.destroy).pack()
pathlabel = Label(root)
pathlabel.pack()
mainloop()
It is not entirely clear what you are asking, so can you edit the question to be more specific?
I think you are trying to get the local variable filename (from inside the function browsefunc) able to be accessed outside the function as a global variable. Use return. This tutorial explains it nicely.
At the end of browsefunc you add
return filename
and when you call browsefunc you run
path = browsefunc()
That assigns the variable fdback to whatever you return from browsefunc. It can be an integer, float, string, or list etc.
So, final code is:
def browsefunc():
filename = askdirectory()
pathlabel.config(text=filename)
return filename
def new_window():
path = browsefunc()
I would recommend using more explicit variable and function names.

Building an interface to search a .txt file depending on the user input, then print the results next to it

I've been playing around with this quite a bit and I feel like I'm making a mess of it.
I need an interface where if someone enters a word in the text field, it'll print any lines within a .txt file containing that word in the box next to it.
Here's what I have so far:
import Tkinter as tk
from Tkinter import *
from scipy import *
import math
def cbc(id, tex):
return lambda : callback(id, tex)
def callback(id, tex):
t = Search(id)
tex.insert(tk.END, t)
tex.see(tk.END)
#def retrieve_input():
# input = self.entn.get("0.0",END)
def Search(id):
with open("file.txt", "r") as s:
searchlines = s.readlines()
for i, line in enumerate(searchlines):
if entn.get() in line:
for line in searchlines[i:i+1]: print line,
print
top = tk.Tk()
tex = tk.Text(master=top)
tex.pack(side=tk.RIGHT)
bop = tk.Frame()
bop.pack(side=tk.LEFT)
entn = tk.Entry()
entn.pack(side=tk.TOP, fill=Y)
tb = "Search"
b = tk.Button(bop, text=tb, command=cbc(id, tex))
b.pack()
tk.Button(bop, text='Exit', command=top.destroy).pack()
top.mainloop()
I'm pretty new to this, as you can probably tell - so any help will be really appreciated.
Your callback is inserting the result of Search(id) but that function isn't returning anything. You need to add a return statement in that function to return the strings you want to show in the text widget.
A better way might be to pass in a reference to tne text widget to Search so that you can directly insert each match as you find them.

Categories