1

I have one .py file which is generated by pyuic of Pyqt4. In this file, I have a toolbar and a rotate icon which is connected to actionRotate action. Here is a small partition of the code;

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Program(object):
    def setupUi(self, UI_Class):
        UI_Class.setObjectName(_fromUtf8("UI_Class"))
               ... 
        self.toolBar = QtGui.QToolBar(UI_Class)
        self.toolBar.setObjectName(_fromUtf8("toolBar"))
        UI_Class.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar.addAction(self.actionRotate)
        self.actionRotate = QtGui.QAction(UI_Class)
        self.actionRotate.setCheckable(True)
        self.actionRotate.setIcon(icon10)
        self.actionRotate.setObjectName(_fromUtf8("actionRotate"))

so if I try to reach the actionRotate button whether it is checked or not from another class it works like in the bottom example;

import PyQt4
import sys
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
from PyQt4 import QtGui
from DropDownActions import *
import pickle
import OpenGLcode
from OpenGL.GL import *
import PYQT_PROGRAM
import numpy as np
import sqlite3 as sq

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    from OpenGL import GL
except ImportError:
    app = QtGui.QApplication(sys.argv)
    QtGui.QMessageBox.critical(None, "OpenGL hellogl",
            "PyOpenGL must be installed to run this example.")
    sys.exit(1)

class UI_main_subclass(QMainWindow):

    def __init__(self, ui_layout):

        QMainWindow.__init__(self)
        self.ui = ui_layout
        ui_layout.setupUi(self)
        ....
        var1 = ui_layout.actionRotate.isChecked()

But when I try to reach the action from my OpenGL code I cannot achieve this. The below code shows the related part;

from OpenGL.GL import *
from PyQt4.QtOpenGL import *
from PyQt4 import QtCore

class glWidget(QGLWidget, QMainWindow):
    resized = QtCore.pyqtSignal()

    xRotationChanged = QtCore.pyqtSignal(int)
    yRotationChanged = QtCore.pyqtSignal(int)
    zRotationChanged = QtCore.pyqtSignal(int)

    def __init__(self, ui_layout, parent = None):
        super(glWidget,self).__init__(parent)

    def mousePressEvent(self, event):
        if self.ui.actionRotate.isChecked(self): # this code gives error below
            print("test 1")
            x, y = event.x(), event.y()
            w, h = self.width(), self.height()
            # required to call this to force PyQt to read from the correct, updated buffer
            glReadBuffer(GL_FRONT)
            data = self.grabFrameBuffer()  # builtin function that calls glReadPixels internally
            rgba = QColor(data.pixel(x, y)).getRgb()  # gets the appropriate pixel data as an RGBA tuple
            message = "You selected pixel ({0}, {1}) with an RGBA value of {2}.".format(x, y, rgba)

            self.lastPos = event.pos()

        else:
            pass

The error is ;

AttributeError: 'glWidget' object has no attribute 'ui'

I am not sure why this doesn't allow me to reach the action button generated in the main .py file, from the pyuic?

Any help is appreciated...

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
BjkOcean
  • 65
  • 1
  • 9
  • The module containing the `glWidget` class doesn't even import `Ui_Program` or `UI_main_subclass`, let alone attempt to use them in any way. So I don't understand why you think it should work. – ekhumoro Sep 27 '17 at 14:32
  • I actually import that with `import UI_Program` and i cannot import `UI_main_subclass` since `glWidget` class file is important in `UI_main_subclass`. – BjkOcean Sep 27 '17 at 18:29
  • But `glWidget` does not inherit `UI_Program`, nor does it create an instance of it. So why do you think it should have a `ui` attribute? – ekhumoro Sep 27 '17 at 18:33
  • How can I force `glWidget` to inherit from the `UI_Program` as well? – BjkOcean Sep 27 '17 at 19:19
  • You can file my files from these github pages; [link](https://github.com/oguzhantogay/stackoverflow/blob/master/V2_dev/OpenGLcode.py) [link](https://github.com/oguzhantogay/stackoverflow/blob/master/V2_dev/SABRE2_main_subclass.py) [link](https://github.com/oguzhantogay/stackoverflow/blob/master/V2_dev/SABRE2_GUI.py) – BjkOcean Sep 27 '17 at 19:28

1 Answers1

1

It seems you have most of the pieces in place: you just need to make use of them correctly.

In your main window class, pass the ui_layout to the glWidget:

class SABRE2_main_subclass(QMainWindow):    
    def __init__(self, ui_layout):
        QMainWindow.__init__(self)
        self.ui = ui_layout
        ...
        self.OpenGLwidget = OpenGLcode.glWidget(ui_layout)

Then keep a reference to it inside the glWidget:

class glWidget(QGLWidget, QMainWindow):    
    def __init__(self, ui_layout, parent = None):
        super(glWidget,self).__init__(parent)
        self.ui = ui_layout

Now glWidget can access the attributes of ui_layout:

    def mousePressEvent(self, event):
        if self.ui.actionRotate.isChecked():
            print("test 1")
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thanks, this solves the issue with action button, but it throws the arrow with the `DropDownActions.statusMessage(self.ui, message)` in line 86 of `glWidget`. How can I solve that? – BjkOcean Sep 28 '17 at 03:41
  • You will have to use `self.ui` everywhere in `glWidget` instead of `self.ui_layout` (see the amended code in my answer). Then you should be able to do `DropDownActions.statusMessage(self, message)` (because `self` will now have a `ui` attribute). (PS: if you found this answer useful, please upvote/accept). – ekhumoro Sep 28 '17 at 04:31