adding a filename to a list in tkinter - python-3.x

i have a method that opens a file and then calls another method,
which opens up a window (i am using tkinter) that asks the user whether he would like to open another file. Now, each time a file gets opened i want to add the filename to a list, but in my case when i look at the result the list only contains the last selected filename.
I will include my stripped down code:
def fileopening(self):
from tkinter.dialog import askopenfilename
import os.path
self.inputfilenamelist = []
self.fileopenname.set(askopenfilename(filetypes = [("binary files","*.bin*"),("all files","*.*")]))
basename = os.path.basename(self.fileopenname.get())
self.inputfilenamelist.append(basename)
self.askforanotherinput()
def askforanotherinput(self):
inputwindow = tk.Toplevel(root)
inputwindow.title("Inputselection")
inputwindow.minsize(400,200)
asklabel = tk.Label(inputwindow,text="Select another inputfile?")
asklabel.pack()
answeryesbutton = tk.Button(inputwindow,text="Yes")
answeryesbutton.pack()
answeryesbutton["command"]=lambda:[inputwindow.destroy(),self.fileopening()]
answernobutton = tk.Button(inputwindow,text="No")
answernobutton.pack()
answernobutton["command"]=lambda:[inputwindow.destroy(),self.fileopeningcounter.set(0)]
Can anyone help me ? The thing is i need this "method-calling-loop" since i am using the opened files in further data conversion as a whole.

Related

How do I dynamically set the name of a tkinter label

I have this code in my project:
def savespack():
savelabelcount = 0
for i in range(saveamount):
savelabelcount = savelabelcount + 1
savebuttontext = "Save " + str(savelabelcount)
Button(scrollable_frame, text=savebuttontext, width="53", height="5").pack()
The user can create multiple saves in the program, and when the project is reopened, the correct amount of save files will be shown as Tkinter buttons. I've created the buttons by reading a number from an external file. I need to make the buttons have different variable names to call the correct save file and load the correct properties when a button is pressed (for example "Save 2" needs to load save2.txt's properties)
Simply put I need to give Button(scrollable_frame, text=savebuttontext, width="53", height="5").pack() a new variable name for each iteration of the loop, I dont know how to do this. I read something about dictionaries and lists but it was very confusing and I dont know if it can be applied in this situation.
The variable names should be something like: savebutton1, savebutton2, savebutton3 etc.
Any way I could do this would be appreciated, thanks!
The example below shows how to save each button widget inside a list rather than as separate variables.
It also will call the saveFile function when the button is pressed which currently just prints to the screen the save file number but this function could be replaced with the code that actually saves each file. With this method, it might not even be necessary to keep the buttons in a list.
I'd normally do this using classes rather than globals but this will work for your purposes
import tkinter as tk
saveamount = 5
save_buttons = []
def saveFile(fileNumber):
print("Saving File ", fileNumber)
def savespack():
global save_buttons
savelabelcount = 0
for i in range(saveamount):
savelabelcount = savelabelcount + 1
savebuttontext = "Save " + str(savelabelcount)
currentButton = tk.Button(scrollable_frame, text=savebuttontext, width="53", height="5")
currentButton['command'] = lambda x=savelabelcount: saveFile(x)
currentButton.pack()
save_buttons.append(currentButton)
root = tk.Tk()
scrollable_frame = tk.Frame(root)
scrollable_frame.pack()
savespack()
root.mainloop()
You could use a dictionary rather than a list but given your use case, I'm not sure there is any benefit. Just use save_buttons[2] to access the third button.

os.startfile strange behaviour

I'm receiving a string from a web extension. The string is a local file path, and I'm trying to open the filepath using the default OS setting for whatever that may be.
edit: Sorry! The question is: how can I successfully open the given path with the OS default app?
The filepath is initially a string formatted as below:
'file:///C:/Test/File/Path.docx'
WEIRD THINGS!
If Word is already open, it works fine.
If Word isn't already open, the blue Word "launching" screen shows for a split second then disappears (crashes, as subsequent attempts show the "start word in safe mode?" dialog for a split second instead).
It won't work at all unless I use "os.startfile" twice specifically as written. One outside a try statement, one inside. Any other combo won't work.
From IDLE, it works 100% of the time with just one "os.startfile" call.
I've also tried to use subprocess.check_call, but that fails to launch anything at all.
Here is the script:
#!/usr/bin/env python
import sys
import json
import struct
import re, subprocess, os
def read_thread_func(queue):
while 1:
text_length_bytes = sys.stdin.buffer.read(4)
if len(text_length_bytes) == 0:
sys.exit(0)
text_length = struct.unpack("i", text_length_bytes)[0]
text = sys.stdin.read(text_length)
data = json.loads(text)
fileStr = data['url']
filePath = re.sub('file:\/{1,3}','',fileStr)
filePath = filePath.replace("/","\\")
filePath = os.path.normpath(filePath)
os.startfile(filePath)
try:
os.startfile(filePath)
except AttributeError:
"nothing to see here"
sys.exit(0)
def Main():
read_thread_func(None)
sys.exit(0)
if __name__ == '__main__':
Main()

Remove letter from python text widget using bind function

I have just started to create a simple text editor. I have already bound a couple of functions to certain keypresses and now I'm trying to add a function that operates on the Return delete being pressed. The aim is to remove the last character entered into the text widget. Here is my code:
from tkinter import *
from tkinter import filedialog
import os
root = Tk()
root.geometry('{}x{}'.format(500, 500))
def addchar(event):
w.insert(END, event.char)
def deletechar(event):
current = w.get()
new = current[:-1]
w.delete(0,END)
w.insert(END, new)
def savefile(event):
file = filedialog.asksaveasfilename(defaultextension=".txt")
if file is None:
return
text2save = str(w.get())
file.append(data)
file.close()
w = Entry(root, bd=1)
w.pack()
w.place(x=0, y=0, width=500)
root.bind("<Key>", addchar)
root.bind("<BackSpace>", deletechar)
root.bind("<Control-s>", savefile)
root.bind("<Return>", newline)
root.mainloop()
The issue I'm having is that nothing is removed upon pressing delete to remove the last character entered. Any help appreciated. P.S. Ive tried adding a savefile function to save the text to a file but it doesn't work if anyone can help there also, it would again be appreciated :)
I didn't try to run your code right know because I'm running out of time. However, first of all, you should not use pack and place geometry manager in the same Toplevel, you should only use one. Second, in your savefile function, you did not open the file, so your file variable is only a string. You should use something like file = open(file).

Unable to see the created .xlsx file in the directory

I had generated a few values and had populated them into a spreadsheet using xlsxwriter. This is how I did it:
class main1():
.
.
.
.
def fun1():
workbook = xlsxwriter.Workbook(self.Output_fold+'Test'+time.strftime("%H_%M_%S_%d_%m_%Y")+'.xlsx')
worksheet_A = workbook.add_worksheet('Sheet_A')
.
.
worksheet_A.write(row,col,<val>)
.
.
workbook.close()
Now, since I had to make multiple writes, and added more complex logic, I decided to have another function introduced fun2 which would write the values accordingly. The new logic requires generating values in fun1 as well as fun2 (by calling another function fun3). So, I decided to replace variables workbook etc with self.workbook and likewise. My modified script looks like this :
main_file.py
import xlsxwriter
import libex
import os
import time
import sys
import string
class main_cls():
def __init__(self):
self.i=0
self.t1=""
self.t2=""
pwd=os.getcwd().split('\\')
base='\\'.join(pwd[0:len(pwd)-1])+'\\'
print base
self.Output_fold=base+"Output\\"
self.Input_fold=base+"Input\\"
self.workbook=xlsxwriter.Workbook(self.Output_fold+'Test_'+time.strftime("%H_%M_%S_%d_%m_%Y")+'.xlsx')
self.worksheet_A = self.workbook.add_worksheet('Sheet_A')
self.worksheet_A.write(self.i,self.i,"Text 1")
self.worksheet_A.write(self.i,self.i+1,"Text 2")
self.i+=1
def fun1(self):
self.t1="1"
self.t2="2"
self.worksheet_A.write(self.i,self.i,self.t1)
self.worksheet_A.write(self.i,self.i+1,self.t2)
self.i+=1
self.eg=libex.exlib()
self.t1=self.eg.gen(0)
self.t2=self.eg.gen(0)
self.fun2()
self.workbook.close()
def fun2(self):
if option==1:
self.fun3()
def fun3(self):
self.t1=self.eg.gen(0)
self.t2=self.eg.gen(1)
self.worksheet_A.write(self.i,self.i,self.t1)
self.worksheet_A.write(self.i,self.i+1,self.t2)
self.i+=1
option=int(sys.argv[1])
if len(sys.argv)==2:
p=main_cls()
if option==1:
p.fun1()
else:
pass
else:
print "Wrong command"
libex.py
class exlib():
def __init__(self):
self.a="duh"
def gen(self,x):
if int(x)==0:
return(self.a)
elif int(x)==1:
self.a=str(self.a+" "+self.a+" "+self.a+" !!!")
return(self.a)
Now, this works in this particular case but in the actual code, it doesn't. The file itself is not getting created in the output directory. Then, I added the following line:
print "Workbook created at path : ",self.workbook.filename
to see if the file is getting created and it surprisingly showed with full path!!!
Where could I be going wrong here and how can I get this fixed?
UPDATE1: I played around a bit with it and found that removing self from self.workbook moving workbook to __init__(self) creates the file with the initial values populated.
UPDATE2: Have replicated my code in a minimal way as suggested. And this one works pretty well!!!
Tried to reproduce, file is being created just fine, maybe you have a problem with the self.Output_fold variable, or with file permissions or with your code editor's file explorer.

How to display Folders and recent items

I have 2 questions in trying to retrieve a set of data from a directory and displays it out into the ListWidget.
As I am a linux user, I set my ListWidget to read my directory from Desktop in which insides contains say 5 folders and 5 misc items (.txt, .py etc)
Currently I am trying to make my ListWidget to display just the folders but apparently it does that but it also displays all the items, making it a total of 10 items instead of 5.
I tried looking up on the net but I am unable to find any info. Can someone help me?
Pertaining to Qns 1, I am wondering if it is possible to display the top 3 recent folders in the ListWidget, if a checkbox is being checked?
import glob
import os
def test(object):
testList = QListWidget()
localDir = os.listdir("/u/ykt/Desktop/test")
testList.addItems(localDir)
Maybe you should try "QFileDialog" like the following:
class MyWidget(QDialog):
def __init__(self):
QDialog.__init__(self)
fileNames = QFileDialog.getExistingDirectory(self, "list dir", "C:\\",QFileDialog.ShowDirsOnly)
print fileNames
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
app.exec_()
2nd question, you could reference to this: enter link description here
I guess that you are expecting that os.listdir() will return only the directory names from the given path. Actually it returns the file names too. If you want to add only directories to the listWidget, do the following:
import os
osp = os.path
def test(object):
testList = QListWidget()
dirPath = "/u/ykt/Desktop/test"
localDir = os.listdir(dirPath)
for dir in lacalDir:
path = osp.join(dirPath, dir)
if osp.isdir(path):
testList.addItem(dir)
This will add only directories to the listWidget ignoring the files.
If you want to get the access time for the files and/or folders, use time following method:
import os.path as osp
accessTime = osp.getatime("path/to/dir") # returns the timestamp
Get access time for all the directories and one which has the greatest value is the latest accessed directory. This way you can get the latest accessed 3 directories.

Resources