Integration of a OpenGLWidget in a QT main.window.ui using PyQT5
-
wrote on 27 Mar 2023, 12:46 last edited by
Hi guys, I'm trying to integrate an OpenGLWidget in a 'mainwindow.ui' from QTDesigner using PyQT5.
Don't take care of the buttons in the GUI, they are useful right now
I have this simple code :import sys from OpenGL.GL import * from OpenGL.GLU import * from PyQt5.QtWidgets import QApplication, QMainWindow, QOpenGLWidget from OpenGL.GLUT import * from PyQt5.uic import * class GLWidget(QOpenGLWidget): def initializeGL(self): print("\033[4;30;102m INITIALIZE GL \033[0m") glutInit(sys.argv) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_DEPTH_TEST) def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # draw frame glLineWidth(5) # X-axis glBegin(GL_LINES) glColor3fv((1, 0, 0)) # red glVertex3fv((0,0,0)) glVertex3fv((5, 0, 0)) glEnd() # Z-axis glBegin(GL_LINES) glColor3fv((0, 1, 0)) # green glVertex3fv((0,0,0)) glVertex3fv((0, 5, 0)) glEnd() # Y-axis glBegin(GL_LINES) glColor3fv((0, 0, 1)) # blue glVertex3fv((0,0,0)) glVertex3fv((0, 0, 5)) glEnd() glLoadIdentity() glLineWidth(1) glColor3fv((1, 1, 1)) glTranslatef(0.0, 0.0, -5.0) glutWireCube(2) self.update() def resizeGL(self, width, height): glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() aspect = width / height gluPerspective(45.0, aspect, 0.1, 100.0) glMatrixMode(GL_MODELVIEW) class MainWindow(QMainWindow): def __init__(self, *args): super().__init__() super(MainWindow, self).__init__(*args) loadUi('mainwindow.ui', self) self.openGLWidget = GLWidget(self) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
I get this :
but I want something like this:
Here is my 'mainwindow.ui' :
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>1027</width> <height>529</height> </rect> </property> <property name="palette"> <palette> <active/> <inactive/> <disabled/> </palette> </property> <property name="contextMenuPolicy"> <enum>Qt::DefaultContextMenu</enum> </property> <property name="windowTitle"> <string>IMU 3D Visual</string> </property> <property name="windowOpacity"> <double>1.000000000000000</double> </property> <property name="autoFillBackground"> <bool>true</bool> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonIconOnly</enum> </property> <property name="documentMode"> <bool>false</bool> </property> <property name="tabShape"> <enum>QTabWidget::Rounded</enum> </property> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="EXITBtn"> <property name="geometry"> <rect> <x>720</x> <y>460</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Exit</string> </property> </widget> <widget class="QPushButton" name="portList"> <property name="geometry"> <rect> <x>720</x> <y>50</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Port List</string> </property> </widget> <widget class="QPushButton" name="extrude"> <property name="geometry"> <rect> <x>720</x> <y>140</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Extrude</string> </property> </widget> <widget class="QPushButton" name="clear_map"> <property name="geometry"> <rect> <x>840</x> <y>90</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Clear Map</string> </property> </widget> <widget class="QPushButton" name="save_file"> <property name="geometry"> <rect> <x>720</x> <y>280</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Save</string> </property> <property name="checkable"> <bool>false</bool> </property> <property name="autoDefault"> <bool>false</bool> </property> <property name="default"> <bool>false</bool> </property> <property name="flat"> <bool>false</bool> </property> </widget> <widget class="QDoubleSpinBox" name="length"> <property name="geometry"> <rect> <x>720</x> <y>90</y> <width>91</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename"> <property name="geometry"> <rect> <x>820</x> <y>50</y> <width>151</width> <height>31</height> </rect> </property> <property name="text"> <string/> </property> </widget> <widget class="QLabel" name="filename_2"> <property name="geometry"> <rect> <x>830</x> <y>470</y> <width>121</width> <height>20</height> </rect> </property> <property name="text"> <string>pw, version 0.1</string> </property> </widget> <widget class="QLabel" name="label"> <property name="geometry"> <rect> <x>720</x> <y>190</y> <width>151</width> <height>21</height> </rect> </property> <property name="font"> <font> <pointsize>10</pointsize> <weight>50</weight> <bold>false</bold> </font> </property> <property name="text"> <string>KML Options</string> </property> </widget> <widget class="QLabel" name="title"> <property name="geometry"> <rect> <x>720</x> <y>20</y> <width>151</width> <height>21</height> </rect> </property> <property name="font"> <font> <pointsize>10</pointsize> <weight>50</weight> <bold>false</bold> </font> </property> <property name="text"> <string>Create Polygon</string> </property> </widget> <widget class="QComboBox" name="port_selector"> <property name="geometry"> <rect> <x>720</x> <y>230</y> <width>91</width> <height>31</height> </rect> </property> <item> <property name="text"> <string>Green</string> </property> </item> <item> <property name="text"> <string>Orange</string> </property> </item> <item> <property name="text"> <string>Red</string> </property> </item> <item> <property name="text"> <string>Blue</string> </property> </item> </widget> <widget class="QDoubleSpinBox" name="alpha"> <property name="geometry"> <rect> <x>830</x> <y>230</y> <width>71</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename_3"> <property name="geometry"> <rect> <x>910</x> <y>229</y> <width>61</width> <height>31</height> </rect> </property> <property name="text"> <string>Opacity</string> </property> </widget> <widget class="QDoubleSpinBox" name="line_width"> <property name="geometry"> <rect> <x>830</x> <y>280</y> <width>71</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename_4"> <property name="geometry"> <rect> <x>910</x> <y>280</y> <width>81</width> <height>31</height> </rect> </property> <property name="text"> <string>Line Width</string> </property> </widget> <widget class="QOpenGLWidget" name="openGLWidget"> <property name="geometry"> <rect> <x>10</x> <y>10</y> <width>691</width> <height>491</height> </rect> </property> </widget> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionHelp"> <property name="text"> <string>Help</string> </property> </action> <action name="actionExit"> <property name="text"> <string>Exit</string> </property> </action> <action name="actionHow_to_Use"> <property name="checkable"> <bool>false</bool> </property> <property name="enabled"> <bool>true</bool> </property> <property name="text"> <string>How to Use</string> </property> </action> <action name="actionOpen_File"> <property name="text"> <string>Open File</string> </property> <property name="visible"> <bool>false</bool> </property> </action> <action name="actionSave_File"> <property name="text"> <string>Save File</string> </property> </action> <action name="actionExit_2"> <property name="text"> <string>Exit</string> </property> </action> </widget> <resources/> <connections/> </ui>
Do you have an idea why I cant affect the OpenGLWidget to the one in the mainwindow.ui ?
-
Hi guys, I'm trying to integrate an OpenGLWidget in a 'mainwindow.ui' from QTDesigner using PyQT5.
Don't take care of the buttons in the GUI, they are useful right now
I have this simple code :import sys from OpenGL.GL import * from OpenGL.GLU import * from PyQt5.QtWidgets import QApplication, QMainWindow, QOpenGLWidget from OpenGL.GLUT import * from PyQt5.uic import * class GLWidget(QOpenGLWidget): def initializeGL(self): print("\033[4;30;102m INITIALIZE GL \033[0m") glutInit(sys.argv) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_DEPTH_TEST) def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # draw frame glLineWidth(5) # X-axis glBegin(GL_LINES) glColor3fv((1, 0, 0)) # red glVertex3fv((0,0,0)) glVertex3fv((5, 0, 0)) glEnd() # Z-axis glBegin(GL_LINES) glColor3fv((0, 1, 0)) # green glVertex3fv((0,0,0)) glVertex3fv((0, 5, 0)) glEnd() # Y-axis glBegin(GL_LINES) glColor3fv((0, 0, 1)) # blue glVertex3fv((0,0,0)) glVertex3fv((0, 0, 5)) glEnd() glLoadIdentity() glLineWidth(1) glColor3fv((1, 1, 1)) glTranslatef(0.0, 0.0, -5.0) glutWireCube(2) self.update() def resizeGL(self, width, height): glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() aspect = width / height gluPerspective(45.0, aspect, 0.1, 100.0) glMatrixMode(GL_MODELVIEW) class MainWindow(QMainWindow): def __init__(self, *args): super().__init__() super(MainWindow, self).__init__(*args) loadUi('mainwindow.ui', self) self.openGLWidget = GLWidget(self) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
I get this :
but I want something like this:
Here is my 'mainwindow.ui' :
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>1027</width> <height>529</height> </rect> </property> <property name="palette"> <palette> <active/> <inactive/> <disabled/> </palette> </property> <property name="contextMenuPolicy"> <enum>Qt::DefaultContextMenu</enum> </property> <property name="windowTitle"> <string>IMU 3D Visual</string> </property> <property name="windowOpacity"> <double>1.000000000000000</double> </property> <property name="autoFillBackground"> <bool>true</bool> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonIconOnly</enum> </property> <property name="documentMode"> <bool>false</bool> </property> <property name="tabShape"> <enum>QTabWidget::Rounded</enum> </property> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="EXITBtn"> <property name="geometry"> <rect> <x>720</x> <y>460</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Exit</string> </property> </widget> <widget class="QPushButton" name="portList"> <property name="geometry"> <rect> <x>720</x> <y>50</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Port List</string> </property> </widget> <widget class="QPushButton" name="extrude"> <property name="geometry"> <rect> <x>720</x> <y>140</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Extrude</string> </property> </widget> <widget class="QPushButton" name="clear_map"> <property name="geometry"> <rect> <x>840</x> <y>90</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Clear Map</string> </property> </widget> <widget class="QPushButton" name="save_file"> <property name="geometry"> <rect> <x>720</x> <y>280</y> <width>91</width> <height>31</height> </rect> </property> <property name="styleSheet"> <string notr="true"/> </property> <property name="text"> <string>Save</string> </property> <property name="checkable"> <bool>false</bool> </property> <property name="autoDefault"> <bool>false</bool> </property> <property name="default"> <bool>false</bool> </property> <property name="flat"> <bool>false</bool> </property> </widget> <widget class="QDoubleSpinBox" name="length"> <property name="geometry"> <rect> <x>720</x> <y>90</y> <width>91</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename"> <property name="geometry"> <rect> <x>820</x> <y>50</y> <width>151</width> <height>31</height> </rect> </property> <property name="text"> <string/> </property> </widget> <widget class="QLabel" name="filename_2"> <property name="geometry"> <rect> <x>830</x> <y>470</y> <width>121</width> <height>20</height> </rect> </property> <property name="text"> <string>pw, version 0.1</string> </property> </widget> <widget class="QLabel" name="label"> <property name="geometry"> <rect> <x>720</x> <y>190</y> <width>151</width> <height>21</height> </rect> </property> <property name="font"> <font> <pointsize>10</pointsize> <weight>50</weight> <bold>false</bold> </font> </property> <property name="text"> <string>KML Options</string> </property> </widget> <widget class="QLabel" name="title"> <property name="geometry"> <rect> <x>720</x> <y>20</y> <width>151</width> <height>21</height> </rect> </property> <property name="font"> <font> <pointsize>10</pointsize> <weight>50</weight> <bold>false</bold> </font> </property> <property name="text"> <string>Create Polygon</string> </property> </widget> <widget class="QComboBox" name="port_selector"> <property name="geometry"> <rect> <x>720</x> <y>230</y> <width>91</width> <height>31</height> </rect> </property> <item> <property name="text"> <string>Green</string> </property> </item> <item> <property name="text"> <string>Orange</string> </property> </item> <item> <property name="text"> <string>Red</string> </property> </item> <item> <property name="text"> <string>Blue</string> </property> </item> </widget> <widget class="QDoubleSpinBox" name="alpha"> <property name="geometry"> <rect> <x>830</x> <y>230</y> <width>71</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename_3"> <property name="geometry"> <rect> <x>910</x> <y>229</y> <width>61</width> <height>31</height> </rect> </property> <property name="text"> <string>Opacity</string> </property> </widget> <widget class="QDoubleSpinBox" name="line_width"> <property name="geometry"> <rect> <x>830</x> <y>280</y> <width>71</width> <height>31</height> </rect> </property> </widget> <widget class="QLabel" name="filename_4"> <property name="geometry"> <rect> <x>910</x> <y>280</y> <width>81</width> <height>31</height> </rect> </property> <property name="text"> <string>Line Width</string> </property> </widget> <widget class="QOpenGLWidget" name="openGLWidget"> <property name="geometry"> <rect> <x>10</x> <y>10</y> <width>691</width> <height>491</height> </rect> </property> </widget> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionHelp"> <property name="text"> <string>Help</string> </property> </action> <action name="actionExit"> <property name="text"> <string>Exit</string> </property> </action> <action name="actionHow_to_Use"> <property name="checkable"> <bool>false</bool> </property> <property name="enabled"> <bool>true</bool> </property> <property name="text"> <string>How to Use</string> </property> </action> <action name="actionOpen_File"> <property name="text"> <string>Open File</string> </property> <property name="visible"> <bool>false</bool> </property> </action> <action name="actionSave_File"> <property name="text"> <string>Save File</string> </property> </action> <action name="actionExit_2"> <property name="text"> <string>Exit</string> </property> </action> </widget> <resources/> <connections/> </ui>
Do you have an idea why I cant affect the OpenGLWidget to the one in the mainwindow.ui ?
wrote on 27 Mar 2023, 12:58 last edited by JonB@Poy_ said in Integration of a OpenGLWidget in a QT main.window.ui using PyQT5:
from PyQt5.uic import *
I think this is not a good idea. (Use
from PyQt5 import uic
and use theuic
object explicitly.) Took me ages to figure what yourloadUi('mainwindow.ui', self)
does.super().__init__() super(MainWindow, self).__init__(*args)
Is double-initialization a good idea?
self.openGLWidget = GLWidget(self)
I don't know how
uic.loadUi('mainwindow.ui', self)
works. Are you sure it creates aself.openGLWidget
variable? [Even if it does the following pertains anyway.] If this creates a brand newQOpenGLWidget
withself
(main window) as parent (as i think it does) it would produce just the screenshot you show. If you have an emptyQOpenGLWidget
from your.ui
file, in a layout etc., don't you have to find that widget in whatloadUi()
created and replace it where it is? -
@Poy_ said in Integration of a OpenGLWidget in a QT main.window.ui using PyQT5:
from PyQt5.uic import *
I think this is not a good idea. (Use
from PyQt5 import uic
and use theuic
object explicitly.) Took me ages to figure what yourloadUi('mainwindow.ui', self)
does.super().__init__() super(MainWindow, self).__init__(*args)
Is double-initialization a good idea?
self.openGLWidget = GLWidget(self)
I don't know how
uic.loadUi('mainwindow.ui', self)
works. Are you sure it creates aself.openGLWidget
variable? [Even if it does the following pertains anyway.] If this creates a brand newQOpenGLWidget
withself
(main window) as parent (as i think it does) it would produce just the screenshot you show. If you have an emptyQOpenGLWidget
from your.ui
file, in a layout etc., don't you have to find that widget in whatloadUi()
created and replace it where it is?wrote on 27 Mar 2023, 13:11 last edited byThanks @JonB for your response.
I tested with
uic.loadUi()
, I also removed the doucle initialisation, doesnt work yet.In debug I can clearly see :
<PyQt5.QtWidgets.QOpenGLWidget object at 0x7f4b440eb1f0>
for the openGLWidget object right after the
uic.loadUi()
.How can I find the 'empty'
openGLWidget
and replace it with my new one ? -
Thanks @JonB for your response.
I tested with
uic.loadUi()
, I also removed the doucle initialisation, doesnt work yet.In debug I can clearly see :
<PyQt5.QtWidgets.QOpenGLWidget object at 0x7f4b440eb1f0>
for the openGLWidget object right after the
uic.loadUi()
.How can I find the 'empty'
openGLWidget
and replace it with my new one ?wrote on 27 Mar 2023, 14:39 last edited by JonB@Poy_ said in Integration of a OpenGLWidget in a QT main.window.ui using PyQT5:
How can I find the 'empty' openGLWidget and replace it with my new one ?
Having the
self.openGLWidget
variable can be used to locate the design-timeQOpenGLWidget
in your widget/layout hierarchy, but writing to it will not replace it in-place, which is what you need.You seem to have a
QWidget
for yourQMainWidget.setCentralWidget()
and then as immediate children a number of widgets. This is wrong and will not look right. Qt Designer is indicating this to you by showing you that central widget with a small "red no-entry" on it, for a missing layout. In Designer use Set layout to set an appropriate layout, so that warning goes away.Then you need to replace the existing
QOpenGLWidget
by removing it from its parent layout and putting the newGLWidget
back at the same place on the layout. You can find any widgets layout viaQWidget.layout()
. You can find the index of a widget on a layout viaQLayout.indexOf()
. And you can use that to position the new widget viaQBoxLayout::insertWidget()
.There is also a simplified
QLayout::replaceWidget()
. If that works you might find something like:newGLWidget = GLWidget(self) layout = self.openGLWidget.layout() layout.replaceWidget(self.openGLWidget, newGLWidget) self.openGLWidget = newGLWidget
does what you want. You must also copy any properties you set in Designer from the old widget to the new one, e.g.
newGLWidget.setGeometry(self.openGLWidget.geometry())
before the last line above. -
@Poy_ said in Integration of a OpenGLWidget in a QT main.window.ui using PyQT5:
How can I find the 'empty' openGLWidget and replace it with my new one ?
Having the
self.openGLWidget
variable can be used to locate the design-timeQOpenGLWidget
in your widget/layout hierarchy, but writing to it will not replace it in-place, which is what you need.You seem to have a
QWidget
for yourQMainWidget.setCentralWidget()
and then as immediate children a number of widgets. This is wrong and will not look right. Qt Designer is indicating this to you by showing you that central widget with a small "red no-entry" on it, for a missing layout. In Designer use Set layout to set an appropriate layout, so that warning goes away.Then you need to replace the existing
QOpenGLWidget
by removing it from its parent layout and putting the newGLWidget
back at the same place on the layout. You can find any widgets layout viaQWidget.layout()
. You can find the index of a widget on a layout viaQLayout.indexOf()
. And you can use that to position the new widget viaQBoxLayout::insertWidget()
.There is also a simplified
QLayout::replaceWidget()
. If that works you might find something like:newGLWidget = GLWidget(self) layout = self.openGLWidget.layout() layout.replaceWidget(self.openGLWidget, newGLWidget) self.openGLWidget = newGLWidget
does what you want. You must also copy any properties you set in Designer from the old widget to the new one, e.g.
newGLWidget.setGeometry(self.openGLWidget.geometry())
before the last line above.wrote on 29 Mar 2023, 08:35 last edited byThanks a lot @JonB !
Here is my final solution in my for MainWindow.init():class MainWindow(QMainWindow): def __init__(self, *args): super(MainWindow, self).__init__(*args) loadUi('mainwindow.ui', self) newGLWidget = GLWidget(self) newGLWidget.resize(800,600) self.mainGridLayout.addWidget(newGLWidget, 0, 0, 1, 1) self.openGLWidget = newGLWidget
-
-
Thanks a lot @JonB !
Here is my final solution in my for MainWindow.init():class MainWindow(QMainWindow): def __init__(self, *args): super(MainWindow, self).__init__(*args) loadUi('mainwindow.ui', self) newGLWidget = GLWidget(self) newGLWidget.resize(800,600) self.mainGridLayout.addWidget(newGLWidget, 0, 0, 1, 1) self.openGLWidget = newGLWidget
-
@Poy_
Since you neither usedreplaceWidget()
nor removed the existing design-time widget, assuming you still have one in the.ui
file as you showed you now have twoQOpenGLWidget
s.
7/7