Ask Your Question
1

tkinter from inside PSSE

asked 2012-08-20 11:09:42 -0600

jsexauer gravatar image

I am trying to develop a script which would run from within PSSE (ie, launched as an automation script via Ctrl+Shift+A) which displays a GUI using tkinter. The UI in general displays, but I've noticed odd quirks like clicking on a menu item in PSSE usually takes two or three clicks (kind of like the program is being unresponsive). Also sometimes fields in PSSE will not populate while the script is running. For example (in PSSE v30):

  1. Open the attached demo script using Ctrl+Shift+A. Keep the script running.
  2. Use GOUT to generate a diagram of any bus in your system.
  3. Double click on that bus, which will bring up the Network data bus viewer. The table in the viewer will not populate with data.
  4. Close the GOUT window and return to the network data viewer. (Still unpopulated)
  5. Now close the script. All of a sudden the data will populate.

It looks to me like tkinter is not giving full focus back to PSSE. Anyone know what to do to get this to work.

Sample Code:

# UI Example for psspy.org    
from Tkinter import *

class appForm( Frame ):    
    def __init__( self, master=None ):            
        """Create the GUI"""
        Frame.__init__( self, master )
        self.pack()

        self.btnTest = Button(self, text="Button")
        self.btnTest.pack()

if __name__ == "__main__":
    # Set up TK
    root = Tk()

    # Run the program
    app = appForm(master=root)
    app.mainloop()

Thanks!

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
1

answered 2013-12-30 07:31:26 -0600

jsexauer gravatar image

I contacted PTI regarding this issue and they gave me the follow advise for how to handle this in WX. I haven't tried it out yet, but hopefully it will work:

  1. Derive main program frame from wx.Dialog:

    Override ProcessClosedMainPanel:

    a. Call EndModal with the ID_CANCEL result

    b. Call app.Exit()

  2. Derive an App class from wx.App:

    Override RunApp:

    a. Instantiate your dlg class

    b. Set to top window

    c. Call ShowModal

    d. del dlg (on return from show modal)

  3. In Main function:

    a. Instantiate your app class

    b. Call RunApp

edit flag offensive delete link more

Comments

I'm keen to see if this works out for you. But I don't see how using wx would work where tKinter didn't. The same fundamental issue is occurring. PSSE suspends and waits for your program to finish execution.

JervisW gravatar imageJervisW ( 2013-12-31 22:03:02 -0600 )edit

I might do some experimentation. here is my line of thinking: - Button inside PSSE spawns new external to PSSE Python server - Button's script returns to PSSE - Python Server handles Tkinter I'll report back if anything works out ok.

JervisW gravatar imageJervisW ( 2013-12-31 22:08:59 -0600 )edit

Cool idea. But how would data from the external sever come back inside of PSSE? If you come up with something, I hope you'll post a gist for it!

jsexauer gravatar imagejsexauer ( 2014-01-09 09:51:47 -0600 )edit

I see your point about getting data back in. Here is the first step: a long lived process outside of PSSE https://gist.github.com/jtrain/8344157

JervisW gravatar imageJervisW ( 2014-01-09 17:27:49 -0600 )edit

Thinking about your original use case - a GUI, it becomes very difficult to notify PSSE that you've clicked a button using the long lived process. This gist looks like it may only be useful in limited situations..

JervisW gravatar imageJervisW ( 2014-01-09 18:15:08 -0600 )edit
1

answered 2012-08-20 15:11:36 -0600

JervisW gravatar image

updated 2014-01-09 18:01:57 -0600

Hi

Here is my take on what might be happening...

When running a Python script from within PSSE, a part of the core PSSE event loop is suspended and waits for the Python script to finish before resuming.

The part of the PSSE that is suspended must be related to updating the UI with fresh data.

Here is how I'd test this

if __name__ == "__main__":
    import time
    print "going to sleep for 2 minutes...try steps 2 - 5" 
    time.sleep(120)

I'd love to have tested this. But I'm travelling at the moment and am without PSSE. Can anyone else confirm or deny that they get similar results using this revised script?

My theory is that for the two minutes the script is sleeping that PSSE will not update its UI and behave similarly to your Tkinter example.

How to deal with this problem

(update)

Here is a proof of concept for a spawning a long running process outside of PSSE from inside of PSSE: https://gist.github.com/jtrain/8344157

I've copied the main.py script here.

"""
Main thread

Spawns a new process outside of itself.
"""
import subprocess
from tkFileDialog import askopenfilename

def main():

  childscript = askopenfilename(title="Run which script?")
  subprocess.Popen(
      ["python", childscript],
      creationflags=subprocess.CREATE_NEW_CONSOLE)

  print "finished main"

main()

the secret here is in subprocess with the CREATE_NEW_CONSOLE flag. The way it works is this

  1. From inside PSSE you run this main.py script.
  2. main.py asks you which file you'd like to open
  3. that child.py file you select will run outside of PSSE's control, and the UI becomes responsive again.

@jsexaur mentioned, the trick is now communicating with that external process that it's running. I'll report back when I develop more on that front.

edit flag offensive delete link more

Comments

Thanks JervisW. I tried your suggestion regarding time.sleep() and it just causes PSSE to hang for the two minutes (hour glass cursor, PSSE is completely unresponsive) as you predicted. I will have to look into the threading idea.

jsexauer gravatar imagejsexauer ( 2012-08-21 06:31:24 -0600 )edit

@jsexauer I suspect that the `threading` module won't bring any joy, so I wouldn't spent too long on it other than confirming that is the case. The problem being that PSSE is waiting for the script to finish and return before resuming its operation.

JervisW gravatar imageJervisW ( 2012-08-22 02:08:04 -0600 )edit

We need to brainstorm some ways that we can finish execution of the script, but allow Python to continue running in the background. Kind of like spawning a new process (rather than thread). Except the new process can still communicate with the already running PSSE instance.

JervisW gravatar imageJervisW ( 2012-08-22 02:09:51 -0600 )edit

I was thinking about something related to breaking out of the TK mainloop() periodically using after(). The only question is then how to break out of the python script itself periodically then come back into it. Any thoughts on how that could be done?

jsexauer gravatar imagejsexauer ( 2012-08-23 09:23:22 -0600 )edit

Maybe periodically call psspy.refreshgui()? I tried using that with root.after() but with no luck. I can't tell where psspy.refreshgui() does anything...

jsexauer gravatar imagejsexauer ( 2012-08-23 10:27:34 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

[hide preview]

Question Tools

2 followers

Stats

Asked: 2012-08-20 11:09:42 -0600

Seen: 1,898 times

Last updated: Jan 09 '14