Parent pyqt window/widget to blender's window

Creating pyqt windows/widgets in blender and interacting with blenders python api.
So far everything seems to be working fine however if i click on blender the qt window will go behind blender window.

Essentially I am trying to parent a QMainWindow to a non-qt application (blender). Any ideas on how to do this?

I could use Qt.WindowStaysOnTopHint flag but then it’s on top of everything which isn’t ideal and i would still need to identify blender being minimized or some other application taking focus.

Using Linux.

Also: in case anyone is wondering why I’m not using blenders gui features is because the tools I’m making though primarily may be used in blender may also be used standalone (for cases where it wouldn’t interact with specific blender code). Like a browser for example. Furthermore some of the base classes used are used outside of blender as well.

Cheers

Hi,

I am also using QT (pyside2) to development a tool for Blender. The purpose is also to have it able to be stand-alone.
I am also facing the same problem in blender. The QT window cannot be parent / on top of the Blender. I tried the QT.WindowsStaysOnTopHint flag, it is not what I want as it freeze the blender out of the QT window.
Is there any solution you found and can share?
Thanks.

Hi,
To keep your window on top of Blender, you can watch this little exemple that i wrote.
It’s for PySide2 but should work too with PyQt

import bpy

from bpy.types import Panel, Operator
from PySide2.QtCore import Qt, QEventLoop
from PySide2 import QtWidgets



class MyWindow(QtWidgets.QWidget):
    
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setWindowFlags(
            self.windowFlags() ^ Qt.WindowStaysOnTopHint)
            
        self.show()

            

class PYSIDE_PT_tools_my_panel(Panel):
    bl_label = "Test Pyside"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout
        layout.operator('pyside.display_window')
        
        
class PYSIDE_OT_display_window(Operator):
    '''  '''
    bl_idname = 'pyside.display_window'
    bl_label = "Display Window"
    bl_options = {'REGISTER'}
    

    def execute(self, context):
        
        self.app = QtWidgets.QApplication.instance()
        if not self.app:
            self.app = QtWidgets.QApplication(['blender'])

        self.event_loop = QEventLoop()

        self.widget = MyWindow()

        return {'FINISHED'}


CLASSES = [PYSIDE_OT_display_window, PYSIDE_PT_tools_my_panel]

def register():
    for cls in CLASSES:
        bpy.utils.register_class(cls)
        
def unregister():
    for cls in CLASSES:
        bpy.utils.unregister_class(cls)
        
        
if __name__ == "__main__":
    register()
1 Like

Will keep searching for How-To-Install-PySide for Blender.
Whether it is PyQt5 or PySide2 wouldn’t matter. PySide2 is preferred as a standard, and most common visual effects tools are PySide based. Along with seeing posts as above, where it is showing an instance of using PySide with Blender, hopefully there is a reliable method for installing PySide to use with Blender.

Is there a how-to for installing PySide2? And since most artists are not developers, hopefully it is as straight forward as the standard Python pip install.

Forgive if this is slightly off topic. Will look more to see if a similar topic is listed, and begin one if not.

Thank you very much for sharing your code. I have a question:
Do I need the QEventLoop() ? If I comment it the code still works. What is the purpose of the QEventLoop?

@mifth - Did you ever get an asnwer to this question? I’m also wondering why I need QEventloop…

I didn’t get the answer. I didn’t use QEventLoop() in my tool and all worked fine.

Since my question is relevant and I don’t think the OP’s question was ever actually answered in this thread- how would one get a QT window to show on top of only Blender? Per the OP’s question (and mine):

I could use Qt.WindowStaysOnTopHint flag but then it’s on top of everything which isn’t ideal and i would still need to identify blender being minimized or some other application taking focus.

@pistiwique’s example shows how to make a QT window show on top of everything, but if Blender is minimized the QT window will still remain on top. I’m looking for something like a tool window (Qt.Tool) that will also disappear when Blender is minimized.

Okay, after spending a day investigating it doesn’t appear to be possible only using Pyside, because you need to be able to set the QApplication parent to the currently running Blender process hwnd (which Pyside doesn’t have a way of accessing). This led me down the path of using win32.dll to find the process and set the parent that way. Before I was able to do any of that work, however- I ran across BQT, which is a nascent Pyside wrapper for Blender. It has Windows and Darwin application bindings, but nothing for linux (yet), which suits me just fine for now. Figured I would update this thread with what I ended up doing for those who find it via search in the future. The included ‘hello world’ demo does exactly what the OP (and myself) were looking to accomplish- which is to create a non-modal floating tool/dialog window that is parented to the Blender process (does not draw on top of any other applications)

1 Like

just be aware that current version of bqt breaks blender when alt tabbing in and out.
there is a PR in process but not merged in yet.

I haven’t noticed any issues with alt-tab but I have noticed that if you lock the computer, Blender’s viewport navigation won’t work until you press the windows/super key.

every time i alt tab out and back in, the alt tab is stuck untill i press it.

when i hold ctrl and click on another window, when going back to blender ctrl is stuck untill i press it

it sounds you have the same with the windows key.

there is a fix in PR for ctrl, alt, shift
but good to know windows key also has this issue, i ll see if it can be added to the PR

can you link your PR so I can merge it in locally? that’d be a handy fix to have for sure

this is the one https://github.com/techartorg/bqt/pull/32
just added windows key being stuck to this PR too, tested locally and can’t get it stuck anymore.

a few more interesting PRs https://github.com/techartorg/bqt/pulls

1 Like

hrm, looking into BQT a bit more and it does currently have one critical flaw that people should be aware of- it has a modal operator (QFocusOperator) that runs non-stop in the background without the user knowing about it. This is a huge design flaw because autosave will not work while a modal operator is running, which means that if you have BQT installed (as of this writing), you are forfeiting autosave. A better way to handle this would be to use a background timer with a controlled refresh tick, as it would still enable constant monitoring of window focus without breaking autosave. The obvious downside is that timers don’t have access to input events, so you wouldn’t be able to detect modifier key events that way. Perhaps since it’s already using ctypes to send keyboard events, it could also use user32.GetKeyState() instead?

2 Likes

the modal operator has been removed from bqt.
this is now a normal operator instead, that triggers once it detects a change in focus in QT.

note this sometimes still doesn’t trigger. But using qt timers we should be able to recreate this “modal” operator again, but compatible with autosave.

If this is a major blocker, you can always set BQT WRAP env variable to disable the wrapping. which prevents this from happening, at the cost of qt windows wont stay in front of blender. (see the repo for env var instructions)

created a dedicated thread for BQT, so we can move any future discussion to BQT: custom UI for add-ons & tool in Blender with PyQt or PySide

quick demo of custom UI with bqt :
sample_blender_2way