[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Re: [PyQt] =?utf-8?q?Embed_PyQt_scripting_in_PyQt_app=E2=80=8F?=
From:       oliver <oliver.schoenborn () gmail ! com>
Date:       2015-10-18 21:27:38
Message-ID: CAMb+DaUrj5jweT04oND+o_V7eiW6eZp_w1kmBTi_WEmU0doQQA () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Sun, Oct 18, 2015 at 1:10 PM, Adrien Tétar <adri-from-59@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@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

[Attachment #5 (text/html)]

<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Oct \
18, 2015 at 1:10 PM, Adrien Tétar <span dir="ltr">&lt;<a \
href="mailto:adri-from-59@hotmail.fr" \
target="_blank">adri-from-59@hotmail.fr</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi \
all,<br> <br>
<br>
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.<br> 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. \
</blockquote><div><br></div><div>  Your code repository has quite a few files, but \
I&#39;m guessing you have a main window (MainWindow) and from there, user can ask to \
open another &quot;top level&quot; window (MainScriptingWindow) which allows user to \
load and display a script then run it, and you want to support additional &quot;top \
level&quot; 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:  </div><div><br></div><div>...</div><div>def \
do_something(self):  </div><div>      window = YourWidget()   # top-level \
window</div><div>      window.show()</div><div>       </div><div>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:  \
</div><div><br></div><div><div>def do_something(self):  </div><div>      self.window \
= YourWidget()   # top-level window</div><div>      \
self.window.show()</div></div><div><br></div><div>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:  \
</div><div><ol><li>ask the user to register the top level window<br></li><li>make the \
top level window automatically register itself<br></li><li>provide a global list in \
the script in which user can store top-level widgets, if desired<br></li><li>require \
the widget to have a specific widget of your app as parent (as you \
did)</li></ol></div><div>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 &quot;win = \
createNewWindow(WidgetDefinedInScript)&quot; which accepts a class as argument and \
will instantiate it, register it, and return it.  \
</div><div><br></div><div>Oliver</div><div><br></div><blockquote class="gmail_quote" \
style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">How \
to make it work as a top-level script?<br> <br>
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.<br> <br>
I considered spawning a separate thread but scripts mutate app data that wasn&#39;t \
made to be thread-safe, so it&#39;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?<br> <br>
The application in question is TruFont (a font editor), by the way:  <a \
href="http://trufont.github.io/" rel="noreferrer" \
target="_blank">http://trufont.github.io/</a><br> <br>
My scripting facility is here: <a \
href="https://github.com/trufont/trufont/blob/master/Lib/defconQt/scriptingWindow.py" \
rel="noreferrer" target="_blank">https://github.com/trufont/trufont/blob/master/Lib/defconQt/scriptingWindow.py</a><br>
 <br>
Thanks,<br>
<br>
<br>
Adrien Tétar  <br>
_______________________________________________<br>
PyQt mailing list      <a \
href="mailto:PyQt@riverbankcomputing.com">PyQt@riverbankcomputing.com</a><br> <a \
href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" rel="noreferrer" \
target="_blank">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a></blockquote></div><br><br \
clear="all"><div><br></div>-- <br><div class="gmail_signature"><div \
dir="ltr"><div><div dir="ltr"><div><font size="2" \
style="font-size:small">Oliver</font><div style="font-size:small"><font size="1">Open \
Source contributions:  <a href="http://pubsub.sf.net/" style="color:rgb(17,85,204)" \
target="_blank">PyPubSub</a>, L<a href="http://lua-icxx.sf.net/" \
style="color:rgb(17,85,204)" target="_blank">ua-iCxx</a>,  <a \
href="http://iof.sf.net/" style="color:rgb(17,85,204)" \
target="_blank">iof</a></font></div><div style="font-size:small"><font size="1"><a \
href="http://stackoverflow.com/users/869951/schollii" style="color:rgb(17,85,204)" \
target="_blank">StackOverflow</a>  contributions</font></div></div><div><font \
size="1"><br></font></div><div></div></div></div></div></div> </div></div>


[Attachment #6 (text/plain)]

_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic