[PyQt] Embed PyQt scripting in PyQt app‏

oliver oliver.schoenborn at gmail.com
Sun Oct 18 22:27:38 BST 2015


On Sun, Oct 18, 2015 at 1:10 PM, Adrien Tétar <adri-from-59 at hotmail.fr>
wrote:

> Hi all,
>
>
> I have added scripting support to my application by using the Python
> primitives compile() and exec() on code passed by the user, and I
> selectively hand a couple of my app intrinsics that are to be mutated in
> the global variables passed to exec() – so far so good.
> Now, I would like to be able to run the event loop on the script as if it
> were the top-level window. Currently if you spawn a parent-less QWidget
> window in that embedded scripting engine, it will just close immediately.


 Your code repository has quite a few files, but I'm guessing you have a
main window (MainWindow) and from there, user can ask to open another "top
level" window (MainScriptingWindow) which allows user to load and display a
script then run it, and you want to support additional "top level" windows
being created from the script, and those are the windows that close
immediately unless you give them a parent? Closing immediately makes me
think that the window is going being destroyed, likely because after being
made visible the creator function returns immediately and there are no
strong references left to it (whereas there is a strong reference left to
it if you set the parent). For example the following pseudo-code:

...
def do_something(self):
    window = YourWidget()  # top-level window
    window.show()

will cause window to appear and almost immediately disappear. In order to
fix that, you either have to set its parent (as you did), or save a
reference to it:

def do_something(self):
    self.window = YourWidget()  # top-level window
    self.window.show()

Unless you provide your scripts a way of registering the widget they
create, it will disappear as soon as the window variable goes out of scope.
There are many ways to fix this issue, such as:

   1. ask the user to register the top level window
   2. make the top level window automatically register itself
   3. provide a global list in the script in which user can store top-level
   widgets, if desired
   4. require the widget to have a specific widget of your app as parent
   (as you did)

My preference #2, but provide this depends on your design: can the user
create any QWidget as top-level, or do they have to use a class you have
defined, like BaseScriptWindow? If latter, then that is where you auto
register the instance. If former, then #1 is next best, like "win =
createNewWindow(WidgetDefinedInScript)" which accepts a class as argument
and will instantiate it, register it, and return it.

Oliver

How to make it work as a top-level script?
>
> Right now what I am doing is passing a reference to the parent window in
> the global variables of the executed script so users have to use that as
> parent widget, but I would like to run scripts that are made to run as
> top-level.
>
> I considered spawning a separate thread but scripts mutate app data that
> wasn't made to be thread-safe, so it's not exactly what I want to resort
> to... any idea? how to make a scripting engine that runs the event loop as
> top-level?
>
> The application in question is TruFont (a font editor), by the way:
> http://trufont.github.io/
>
> My scripting facility is here:
> https://github.com/trufont/trufont/blob/master/Lib/defconQt/scriptingWindow.py
>
> Thanks,
>
>
> Adrien Tétar
> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> https://www.riverbankcomputing.com/mailman/listinfo/pyqt




-- 
Oliver
Open Source contributions: PyPubSub <http://pubsub.sf.net/>, Lua-iCxx
<http://lua-icxx.sf.net/>, iof <http://iof.sf.net/>
StackOverflow <http://stackoverflow.com/users/869951/schollii> contributions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20151018/f1cf0ebe/attachment.html>


More information about the PyQt mailing list