Maya UI not docking after rerunning script - python

I have made a UI window for Autodesk Maya 2015. Every time I run the script within Maya's script editor, it works fine, the UI gets launched and it docks properly on the main Maya window.
However, after closing the UI window and rerunning the script, the window doesn't dock anymore. It gets stuck on the main screen and I have to close the whole software. It seems that the UI can't find the main Maya Window anymore after I close it the first time round. I'm not sure how to fix this. Can anyone give me some advice on how to fix this problem?
Here is my code:
def getMayaWindow():
ptr = apiUI.MQtUtil.mainWindow()
if ptr is not None:
return shiboken.wrapInstance(long(ptr), QtGui.QMainWindow)
class pipeWindow(formClass,baseClass):
def __init__(self, parent=getMayaWindow()):
super(pipeWindow,self).__init__(parent)
self.setupUi(self)
self.setObjectName('pipe_window')
try:
cmds.deleteUI('dockPane')
except:
pass
self.pane = cmds.paneLayout('dockPane', cn='single')
if 'pipeDock' not in cmds.lsUI(ctl=1) :
cmds.dockControl('pipeDock', con=self.pane, area='right',
allowedArea = ['right','left'], label =
"ANMD_Pipeline", w=365)
else:
pass
cmds.control( 'pipe_window', e=True, p=self.pane)

After trying out multiple things, I have managed to resolve this issue. I have used
if cmds.dockControl('pipeDock', q=1, ex=1):
cmds.deleteUI('pipeDock')
Then I have a super(className, self).closeEvent(event) inside a closeEvent function. This did the trick for me. This did the trick for me. Previously I had the cmds.deleteUI within my closeEvent function which did not work, I suspect it was because I did not close the Event itself, so the UI just hides itself whenever I press the cross button instead of deleting it.

Related

PyQt different windows during a script

I developed a script for pcba testing and it works fine.
Now I want to implement a very simple flow like this:
Window popup just to let the user start the test
Run the test without any window (the terminal is just fine)
Window popup to show pass/fail result of the test
I already developed the two windows in two other .py files, which run without any problems when "standalone".
If I implement these two within the script, the first appears normally, but the second opens and closes istantly.
Without being too complicated, the test function is defined in serial.py, the first window in infoBox.py and the final window in getResult.py.
Inside the serial.py I tried:
import infoBox
import getResult
[...]
def work():
[...]
if __name__ == '__main__':
app1 = QApplication([])
win1 = infoBox.infoBox("""Turn on 24V alim and press OK.""")
win1.show()
app.exec()
[...]
work()
[...]
app2 = QApplication([])
generateWindow(esiti=lst_esiti, info=lst_info) # <------- this calls getResult.getResult class and .show() the widget
win2 = getResult.getResult(lst_esito=lst_esiti, lst_info=lst_info)
win2.show()
app.exec()
So, when serial.py is lounched by terminal, the infoBox instance appears, the work() function does what it has to, and the getResult instance (which has a OK button to be closed) is instantly closed.
Maybe the error is the definition of two QApplication? I tried a lot but I'm not able to manage it.
Thank you very much.
Finally I came up with this.
It was easier than expected...
Solved opening a unique QApplication and call app.exec() after each subclass calling.

Continue a code after calling a class method which opens a tkinter window

I have created a class "Node" which creates a binary tree. (I know i can use binarytree module but its a project given to me in DSA subject.)
class Node:
def __init__(self, data) -> None:
#initialisation
def addNode(self, data):
# Code to add data.
def traverse(self):
#traverses the tree and returns a dict
def view(
self,
length=500,
width=1000,
yDist=50,
xDistScale=0.25,
title='Tree View',
):
# shows the tree in a tkinter window as in the screenshot attached
tree = self.traverse()
root = tk.Tk()
self.root=root
root.geometry(str(width)+'x'+str(length))
root.title(title)
# ........ some code which places the nodes on the window using the place() method
root.mainloop()
Now, I import the code in an another file, create an instance of the class add some nodes and call the view() method it works fine but the code after the view() methd does not run till I close the tkinter window.
How can I make the code after view() run without the window being closed?
Its ok if the window is not able to update.
Code where I import and use the node class :
t1 = Node(15)
t1.addNode(12)
t1.addNode(27)
t1.addNode(7)
t1.addNode(14)
t1.addNode(20)
t1.addNode(88)
t1.addNode(23)
t1.view()
# The code here does not run until I close the window.
Output of the above code :
Link to image
I tried googling and also viewed following stackoverflow posts:
Calling a tkinter application from a different class in python,
A code needs to be continued...(Python with Tkinter)
How would I continue to run code after importing a Tkinter file?
Few other websites and guides...
But nothing was helpful.
Please help/guide me.
I am new to StackOverflow and Python.
Thanks in Advance :)
Method 1: Don't update window
You could replace the root.mainloop() with root.update(). This will stop showing any changes to the window. The window will only and always close if the program stops running.
Method 2: using threading
You could useimport threading to run t1.view() in another thread: threading.Thread(target=t1.view).start(). This may result in a Tcl_AsyncDelete error.

Python 2.7: Close a dialog without exiting the entire application

I'm running a script coded in python from a scripts menu in a desktop application. It's basically a giant macro that I wrote and added a GUI to. I'm pretty sure the GUI is a really old one that my desktop app uses called dialogKit from MIT.
GitHub still has it here.
The problem is the word "stop" at the very end of the dialog code.
I keep getting a "stop is undefined" message, which I understand, but I've tried everything to close the dialog and if I use exit(), sys.exit(), I don't get an error, but it also closes my entire desktop app.
I need to close the dialog and keep the software open.
The limited dialog documentation for what I'm using can be found here.
(you might have to click on the Dialog section. Their site uses frames.)
class MyDialog:
def __init__(self):
self.d = Dialog(self)
self.d.size = Point(300, 340)
self.d.Center()
self.d.title = "Halftone" #<----- Title of the dialogue
self.d.AddControl(STATICCONTROL, Rect(aIDENT, aIDENT, aIDENT, aIDENT), "frame", STYLE_FRAME)
# more controls and methods..
def on_ok(self, code):
return 1
def on_cancel(self, code):
print "blah"
def Run(self):
return self.d.Run()
d = MyDialog()
if d.Run()!= 1:
stop
I just need a way to change stop to something that 1) will prevent the script from running, and 2) close the dialog without quitting the entire application. This is the functionality of a typical "cancel" button, which is what I want.
Another option is the method called on_cancel(), which I also tried and could get the event itself to work, but still the entire application quits with any kind of exit().
The docs show a method called End(), which claims to terminate the dialog object, but I've tried and failed to get that to work either.
Okay, I'm posting an answer because I think I have a handle on your problem.
Try replacing stop with:
d.d.End()
If that works, you might want to try putting:
self.d.End()
inside of the on_cancel function in your class. That should close the dialogue without closing your program.

How to open a popup window with a spinner in python + Gtk

I have a python Gtk application, with the GUI designed in Glade. It has a "scan" feature which will scan the network for a few seconds and then report its results to the user. During the scanning I want a popup window to appear stealing the focus from the parent until scanning is done.
I use a threading.Lock to synchronize the GUI and the scan thread, which makes the popup to last exactly the right time I want (see scanLock.acquire() ). It seems straightforward to me to implement something like a show() and hide() call before and after the scanLock.acquire(). I did use waitPopupShow and waitPopupHide instead of just calling the window.show() and window.hide() because I also may want to set the Label in the popup or start/stop the GtkSpinner. Here is some code from the GUI class:
def scan(self):
sT = scannerThread(self,self.STagList)
self.dataShare.threadsList.append(sT)
sT.start() # start scanning
self.waitPopupShow('Scanning... Please Wait')
self.scanLock.acquire() # blocks here until scan is finished
self.waitPopupHide()
def waitPopupShow(self, msg): # shows a GtkSpinner until the semaphore is cleared
self.waitDialogLabel.set_text(msg)
self.waitDialogBox.show_all()
self.waitDialog.show()
self.waitDialogSpinner.start()
def waitPopupHide(self):
# how to get the handle to the spinner and stop it?
self.waitDialogSpinner.stop()
self.waitDialog.hide()
def getAll(self):
# GUI
self.builder = Gtk.Builder()
self.builder.add_from_file(path to main GUI)
# ... getting stuff from a first glade file
# getting stuff from the waitDialog glade file
self.builder.add_from_file(path to waitDialog GUI)
self.waitDialog = self.builder.get_object("waitDialog") # GtkWindow
self.waitDialogBox = self.builder.get_object("waitDialogBox") # GtkBox
self.waitDialogLabel = self.builder.get_object("waitDialogLabel") # GtkLabel
self.waitDialogSpinner = self.builder.get_object("waitDialogSpinner") # GtkSpinner
self.waitDialog.hide()
I'm trying hardly since a couple of days to show a dialog with a label and a Gtk.Spinner. The best I obtain at the moment is to have the window showing up with no content. Please note that the self.waitDialog.hide() right after getting it with self.builder.get_object is needed because I set the property of the waitDialog Gtkwindow to Visibile. If I stop with the debugger before .hide() the waitDialog shows up perfectly. Afterwards its broken.
This is the waitDialog GUI file: http://pastebin.com/5enDQg3g
So my best guess is that I'm dooing something wrong, and I could find nothing on creating a new Gtk window over the main one, only basic examples and dialogs. A pointer to the documentation saying a bit about this would be a good starting point...

Tkinter Keyboard Binds

I'm working on an interface using Tkinter and the canvas widget, and so far have found answers to issues I have had from others questions and the answers posted, but I am stumped on this one.
I have several keyboard binds in the class where my GUI elements are created, and they all work fine when the program is started. The binds looks something like this:
self.canvas.get_tk_widget().bind("<Control-o>",self.flash_open)
and are within the __init__ function of the class. As of yesterday, I initialized this class
to start the program, then waited for the user to select open from a menu, which then opened (among other things) a tkmessagebox
self.specfilename =askopenfilename(filetypes=[("spec", "")],initialdir= self.pathname)
With this filename I am able to retrieve my required variable names from a certain filetype (inconsequential to the problem). Today I modified the __init__ function to call the open function when the program starts. Since nothing else can be done until this file is opened, it would make sense to open it first thing. Once the file is selected and the Tkmessagebox is closed, the root window is active, but none of the keyboard binds work. My functions still work using the menu/buttons assigned to them, just not the binds. I have tried binding the shortcuts to the root, with the same result, and am now thinking it may be an issue with the order I am calling them
def __init__(self):
...
self.openfile() #calls the tkmessagebox
self.root.mainloop() #starts gui
I had actually run into this issue before, where a toplevel() instance was closed/destroyed and disabled the binds of the parent window. There isn't any error message to speak of, the binds just don't do anything. I should also mention I have tried to focus on the root window again using
self.openfile()
self.root.mainloop()
self.root.focus_set()
I got around it before by using the wm_withdraw() and wm_deiconify() functions to simply hide the child window, then close it after the program is complete. This fix is a little more difficult to apply in this case however. If anyone can shed some light on the cause of the problem I'd appreciate it.
Edit:
I've written up a runable code segment to show exactly what my issue is.
import os
from tkFileDialog import askopenfilename
from Tkinter import *
class Start:
def __init__(self):
self.root = Tk()
self.root.title('Binding Troubles')
menubar = Menu(self.root)
#add items and their commands to the menubar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Do work", command=self.do_work)
filemenu.add_command(label="Open File",command=self.openfile)
menubar.add_cascade(label="File", menu=filemenu)
#bind control-o to perform the do work function
self.root.bind("<Control-o>",self.flash_do_work)
self.root.bind("<Control-O>",self.flash_do_work)
#add the menubar to the GUI
self.root.config(menu=menubar)
#initially open a tkdialog to open a file
self.openfile()#comment out this line to make the bind work
self.root.focus()#also tried self.root.focus_set()
self.root.mainloop()
def flash_do_work(self,event):
#indirect tie to the do_work() function, I'm don't know a
#proper way to make functions handle calls from both events and non-events
self.do_work()
def openfile(self):
#gets current path
self.pathname = os.getcwd()
#Requests filename using a tkdialog
self.filename =askopenfilename(initialdir= self.pathname)
print self.filename
def do_work(self):
#placeholder for actual function; shows whether the bind is working or not
print "work"
Start()
The bind will work if self.openfile() is removed from __init__, and used only from the menu
Another Edit: I've updated the example again, giving a menu option to run the openfile() function. I noticed that if openfile() is called in __init__, the bind will not work. But if next the openfile function is called again, this time manually from the menu, the bind will start working again. Not exactly sure what to take from this. Also, my apologies for the post getting so long.
Change
self.openfile()
to
self.root.after(1, self.openfile)
This moves the call to askopenfilename into the main event loop. Having it outside the main event loop is somehow clobbering your event bindings.
I had this kind of problem a couple of times and it took quite a while until I found a solution I was comfortable with. As #Steven Rumbalski suggests I tried with delaying the application, which works but seems shaky.
Then I found the functions for waiting until something is complete, in this case wait_visibility(widget). This will delay execution until the widget is visible, which seems to be the thing to be waiting for. Try this:
self.root.wait_visibility(self.root) # Wait for root to be displayed
self.openfile()
Now; I'm not sure why this is so, and it seems that there may be differences depending on platform: Tkinter window event . This has nevertheless worked for me on Windows10 and Python 3.10.5.

Categories

Resources