Auto-save function implementation with Python and Tkinter - python-2.7

This might be a general question. I'm modifying a Python code wrote by former colleague. The main purpose of the code is
Read some file from local
Pop out a GUI to do some modification
Save the file to local
The GUI is wrote with Python and Tkinter. I'm not very familiar with Tkinter actually. Right now, I want to implement an auto-save function, which runs alongside Tkinter's mainloop(), and save modified files automatically for every 5 minutes. I think I will need a second thread to do this. But I'm not sure how. Any ideas or examples will be much appreciated!! Thanks

Just like the comment says, use 'after' recursion.
import Tkinter
root = Tkinter.Tk()
def autosave():
# do something you want
root.after(60000 * 5, autosave) # time in milliseconds
autosave()
root.mainloop()
Threaded solution is possible too:
import threading
import time
import Tkinter
root = Tkinter.Tk()
def autosave():
while True:
# do something you want
time.sleep(60 * 5)
saver = threading.Thread(target=autosave)
saver.start()
root.mainloop()
before leaving I use sys.exit() to kill all running threads and gui. Not sure is it proper way to do it or not.

Related

Better looking Tkinter File Dialogs for Python 2.7

In my application, the user needs to browse for files. However, the askdirectory from tkFileDialog isn't really comfortable for using and browsing files since it's somewhat outdated.
It looks like this:
What I want to achieve should look like the "default" windows browse dialog. Like this:
(Source https://www.pythontutorial.net/tkinter/tkinter-open-file-dialog/)
I am not sure (since I couldn't find proof) but I remember someone telling me that it looks like this because I am using Python 2.7 and not 3+.
Is that true? Does an alternative exist?
It seems it has something to do with your version, as I have done a bit of research and I am using python 3 with the included tkinter and it shows a normal windows explorer popup. So, if you are using one of the up-to-date versions, it should be the OS' default. (I am unable to test that as python 2 will not work properly on my machine although I can confirm since you are using an older one)
I recreated your case with this code:
from tkinter import *
root = Tk()
filedialog.askdirectory()
root.mainloop()
You can try using askopenfilename(). It displays the standard Open File dialog box.
For example:
from tkinter import *
from tkinter import filedialog as fd
root = Tk()
root.title("Button to open files")
root.geometry("500x500")
def openfd(*args):
askk = askopenfilename()
btn = Button(root, text="Click to open file", command=openfd)
btn.place(x=200, y=200)
root.mainloop()
You can read more about it at https://www.pythontutorial.net/tkinter/tkinter-open-file-dialog/.

automated creation of pdf with Matplotlib blocks the code execution

I have a Python code that contains a function where a figure is created in order to be saved as a pdf (it never shows on the screen during execution). For some reason, the execution of this subroutine keeps the figure open and blocks the following operations in the code. I tried to use the cla(), clf() and clear() functions but I could not get it to work...
Here is a partial view of the subroutine:
def trace_pdf(a,b,c,d):
x = np.linspace(0,100,a)
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
ax2.plot(b,c,'b', label='BA',linewidth=3.5)
ax2.set_title('a pdf like no other')
fig2.savefig('file.pdf', format='pdf')
fig2.clf()
fig2.clear()
I do not see why my code is blocked... (I checked that if I comment the call to the trace_pdf function, everything works fine).
So here is what I did to fix my problem. I decided to try to run my function as an independent process so I added to my code:
from multiprocessing import Process, Queue
def trace_pdf(a,b,c,d):
x = np.linspace(0,100,a)
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
ax2.plot(b,c,'b', label='BA',linewidth=3.5)
ax2.set_title('a pdf like no other')
fig2.savefig('file.pdf', format='pdf')
plt.close()
trace_pdf = Process(target=trace_pdf, args=(a,b,c,d))
trace_pdf.start()
This way, the plt_close() call does not impact the main graphic interface as I believe its action is limited to the separate process... For details regarding running a function as an independent process I used this post.

tkinter button to open new window and run script

I have a tkinter button that I want to use to run an existing python script in a new cmd window. How would I do that?
I can get the new cmd window to appear, but how do I run the script in it?
Thanks,
Chris.
Multiline code is more readable if you edit your question to add it (allowed, just mark it as edited and say so in the comment) rather than in a comment.
from Tkinter import *
from sys import executable
from subprocess import Popen, CREATE_NEW_CONSOLE
import os
def delprof(): Popen(["cmd.exe"], creationflags=CREATE_NEW_CONSOLE) `
If you get a console with a prompt, you can run python or do anything else. To run a particular python program, the following works for me (3.4).
from tkinter import *
from subprocess import call
pyprog = 'tem2.py'
def callpy(): call(['python', '-i', pyprog] )
root = Tk()
Button(root, text='Run', command=callpy).pack()
root.mainloop()
When running a program, the console normally disappears when the program ends. To prevent that with a python program, so output can be seen, either put something like
input('hit enter to exit')
at the end of the program or start it with '-i', as I did above. This also allows execution of additional interactive statements to examine the result

Wrapinstance without sip or shiboken in python

I have some issues in maxplus, the python distribution in 3ds max with pyside.
I try to parent my qtmainwindow to the max window. To minimize my qtmainwindow when max is minimized.
We want to leave the maxplus python installation untouched so I cannot install sip or shiboken to use wrapinstance to get a qobject. Now I would like to know how the parenting would be possible without those packages.
edit:
I recognized that shiboken is available but when I try to parent my QMainWindow to the applicatin it gives a
** system exception **
here is a bit of code i hope that helps to understand:
from PySide import QtCore, QtGui,shiboken
import MaxPlus
class ControlMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(ControlMainWindow, self).__init__(parent)
maxWinHwd = MaxPlus.Core.GetWindowHandle()
parent=shiboken.wrapInstance(long(maxWinHwd), QtGui.QWidget)
self.setParent(parent)
def main():
global app
app = QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication(sys.argv)
global window
window=ControlMainWindow()
window.show()
if __name__ == '__main__':
main()
Thanks in advance
I'm tackling the exact same problem now, so this is the best solution I've found so far that works OOTB without having to resort to relying on the Blur 3ds max Python extensions:
http://tech-artists.org/forum/showthread.php?5162-MaxPlus-parent-PySide-Window-to-Max-Window
I've tried to make a commented version of the code here as well, though I'm new to ctypes, so it may not be 100% correct:
http://pastebin.com/Sed2g89N
I hope that helps!

Good sources on general program layout (preferably Python or C++)

So I can do a little C++ console stuff with classes (nothing too fancy I think) and just started with Python (awesome language, it's like C++ without worries) and Tkinter.
The thing is that I don't really have a clue how in general a program with a GUI is structured. I know you have to separate the interface from the internal workings, but that's about it. As an example I am working on a small app that converts Excel tables to LaTeX tables and so far I have this:
from Tkinter import *
class ExcelToLateX:
def __init__(self,master):
self.convert = Button(master,text="Convert",command=self.Conversion)
self.convert.pack(side=BOTTOM,fill=X)
self.input=Input(master,40)
self.output=Output(master,40)
def Conversion(self):
self.output.Write(self.input.Read())
class Input:
def __init__(self,master,x):
self.u=Text(master,width=x)
self.u.pack(side=LEFT)
self.u.insert(1.0,"Paste Excel data here...")
def Read(self):
return self.u.get(1.0,END)
class Output:
def __init__(self,master,x):
self.v=Text(master,width=x)
self.v.pack(side=RIGHT)
self.v.insert(1.0,"LaTeX code")
def Write (self,input):
self.input=input
if self.v.get(1.0,END)=="":
self.v.insert(1.0,self.input)
else:
self.v.delete(1.0,END)
self.v.insert(1.0,self.input)
#Test script
root=Tk()
Window=ExcelToLateX(root)
root.mainloop()
So I have two Text widgets that can read and write stuff and a (for now) empty conversion class that will take Excel tables and spew out LaTeX code. I have no idea if this is the way to go (so any comments/tips are appreciated).
So in short I have two questions:
Are there any widely acknowledged sources that provide information on how a program with a GUI is structured? (preferably Python and Tkinter because that's what I'm doing right know, although it may be a bit more general (cross-language))
Is my current application any good when it comes to structure, and if not, what are some rules of thumb and things I can improve?
I'm just going to throw a couple short comments into the hat. I don't have experience with Tkinter, so my knowledge derives from PyQt4 experience.
Right now you are using composition for your classes, by making the single widget a member attribute. This can obviously work but a useful pattern is to subclass a GUI widget, and then compose the layout by adding more child widgets and parenting to that class. See the examples on this random Tkinter tutorial link I found: http://zetcode.com/tutorials/tkintertutorial/
class Example(Frame):
def __init__(self, parent):
super(Example, self).__init__(parent)
...
And just as a general python convention, you should try and stick with capitalization for your class names, and camelCase or under_score for class instance methods and variables. As you have it, you are using capital for instances (Window =) and methods (Write)
Also, if you aren't going to be subclassing Tkinter widgets, make sure to at least use the new-style classes by subclassing from object: http://realmike.org/blog/2010/07/18/introduction-to-new-style-classes-in-python/
You might also want to nest that last part of your code where you run the event loop inside of the classic python idiom:
if __name__ == "__main__":
root=Tk()
window = ExcelToLateX(root)
root.mainloop()
It prevents your app from immediately being executed if you were to import this module into another application as a library.