QtWidget未显示 [英] QtWidget is not showing

查看:0
本文介绍了QtWidget未显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用PyQt5来显示两个小部件,第一个是关于sin、cos和tan函数的图。我使用的是pyqtgraph,并使用了在这个question的答案中找到的代码。我还使用了另一个使用PyOpenGL绘制立方体的小部件,以这个link中的例子为例。我试图在一个主小部件中显示这两个小部件,即主窗口。我的方法如下

  1. 获取主小工具。
  2. 在主小部件中,使用QVBoxLayout()
  3. 在QVBoxLayout中,上面提到的两个小部件
但当我运行代码时,只显示使用pyqtgraph的曲线图,而不显示使用PyOpenGL绘制的立方体。经过一点调试后,我发现Cube小部件的高度默认设置为0。我不确定为什么会这样。我试着拨打glWidget.resize(640,480)。但这并没有奏效。我对使用PyQt和PyOpenGL是个新手。如果我的假设是正确的,我想我遗漏了一些允许glWidget高度大于0的细节。此外,我也不确定这是否真的可能做到。我当前的代码如下所示,有点凌乱。

import sys
from OpenGL.GL.images import asWrapper

from PyQt5.QtWidgets import QApplication, QGridLayout
from PyQt5 import QtWidgets
import pyqtgraph as pg
from OpenGL.GL import *
from OpenGL.GLU import *
from PyQt5 import QtGui
from PyQt5.QtOpenGL import *
from PyQt5 import QtCore, QtWidgets
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtOpenGL
import OpenGL.GL as gl
from OpenGL import GLU  
from OpenGL.arrays import vbo

class TimeLine(QtCore.QObject):
    frameChanged = QtCore.pyqtSignal(int)

    def __init__(self, interval=60, loopCount=1, parent=None):
        super(TimeLine, self).__init__(parent)
        self._startFrame = 0
        self._endFrame = 0
        self._loopCount = loopCount
        self._timer = QtCore.QTimer(self, timeout=self.on_timeout)
        self._counter = 0
        self._loop_counter = 0
        self.setInterval(interval)

    def on_timeout(self):
        if self._startFrame <= self._counter < self._endFrame:
            self.frameChanged.emit(self._counter)
            self._counter += 1
        else:
            self._counter = 0
            self._loop_counter += 1
        
        if self._loopCount > 0:
            if self._loop_counter >= self.loopCount():
                self._timer.stop()
    
    def setLoopCount(self, loopCount):
        self._loopCount = loopCount
    
    def loopCount(self):
        return self._loopCounts
    interval = QtCore.pyqtProperty(int, fget=loopCount, fset=setLoopCount)

    def setInterval(self, interval):
        self._timer.setInterval(interval)
    
    def interval(self):
        return self._timer.interval()

    interval = QtCore.pyqtProperty(int, fget=interval, fset=setInterval)

    def setFrameRange(self, startFrame, endFrame):
        self._startFrame = startFrame
        self._endFrame = endFrame

    @QtCore.pyqtSlot()
    def start(self):
        self._counter = 0
        self._loop_counter = 0
        self._timer.start()

class GLWidget(QtOpenGL.QGLWidget):
    def __init__(self, parent = None):
        self.parent = parent
        QtOpenGL.QGLWidget.__init__(self, parent)
        self.resizeGL(640,800)
    
    def initializeGL(self):
        self.qglClearColor(QtGui.QColor(0,0,255))
        gl.glEnable(gl.GL_DEPTH_TEST)

        self.initGeometry()

        self.rotX = 0.0
        self.rotY = 0.0
        self.rotZ = 0.0

    def resizeGL(self, width, height):
        gl.glViewport(0, 0, width, height)
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        print(width, height)
        aspect = width / float(height)

        GLU.gluPerspective(45.0, aspect, 1.0, 100.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)

    def paintGL(self):
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glPushMatrix()

        gl.glTranslate(0.0, 0.0, -50.0)
        gl.glScale(20.0, 20.0, 20.0)
        gl.glRotate(self.rotX, 1.0, 0.0, 0.0)
        gl.glRotate(self.rotY, 0.0, 1.0, 0.0)
        gl.glRotate(self.rotZ, 0.0, 0.0, 1.0)
        gl.glTranslate(-0.5, -0.5, -0.5)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnableClientState(gl.GL_COLOR_ARRAY)

        gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertVBO)
        gl.glColorPointer(3, gl.GL_FLOAT, 0, self.colorVBO)

        gl.glDrawElements(gl.GL_QUADS, len(self.cubeIdxArray), gl.GL_UNSIGNED_INT, self.cubeIdxArray)

        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)

        gl.glPopMatrix()

    def initGeometry(self):
        self.cubeVtxArray = np.array(
                [[0.0, 0.0, 0.0],
                 [1.0, 0.0, 0.0],
                 [1.0, 1.0, 0.0],
                 [0.0, 1.0, 0.0],
                 [0.0, 0.0, 1.0],
                 [1.0, 0.0, 1.0],
                 [1.0, 1.0, 1.0],
                 [0.0, 1.0, 1.0]])
        self.vertVBO = vbo.VBO(np.reshape(self.cubeVtxArray,
                                          (1, -1)).astype(np.float32))
        self.vertVBO.bind()
        
        self.cubeClrArray = np.array(
                [[0.0, 0.0, 0.0],
                 [1.0, 0.0, 0.0],
                 [1.0, 1.0, 0.0],
                 [0.0, 1.0, 0.0],
                 [0.0, 0.0, 1.0],
                 [1.0, 0.0, 1.0],
                 [1.0, 1.0, 1.0],
                 [0.0, 1.0, 1.0 ]])
        self.colorVBO = vbo.VBO(np.reshape(self.cubeClrArray,
                                           (1, -1)).astype(np.float32))
        self.colorVBO.bind()

        self.cubeIdxArray = np.array(
                [0, 1, 2, 3,
                 3, 2, 6, 7,
                 1, 0, 4, 5,
                 2, 1, 5, 6,
                 0, 3, 7, 4,
                 7, 6, 5, 4 ])

    def setRotX(self, val):
        self.rotX = np.pi * val

    def setRotY(self, val):
        self.rotY = np.pi * val

    def setRotZ(self, val):
        self.rotZ = np.pi * val
    

class MainGui(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.resize(600,600)
        self.cube = GLWidget(self)
        self.setupUI()

    def setupUI(self):
        central_widget = QtWidgets.QWidget()
        central_layout = QtWidgets.QVBoxLayout()
        central_widget.setLayout(central_layout)

        self.setCentralWidget(central_widget)
        
        pg.setConfigOption('background',0.95)
        pg.setConfigOptions(antialias=True)
        
        self.plot = pg.PlotWidget()
        self.plot.setAspectLocked(lock = True, ratio = 0.01)
        #self.cube = GLWidget(self)
        #self.cube.resize(200,200)
        
        central_layout.addWidget(self.cube)
        central_layout.addWidget(self.plot)

        self._plots = [self.plot.plot([], [], pen=pg.mkPen(color=color, width=2)) for color in ('g', 'r', 'y')]
        self._timeline = TimeLine(loopCount = 0, interval = 10)
        self._timeline.setFrameRange(0,720)
        self._timeline.frameChanged.connect(self.generate_data)
        self._timeline.start()
    def plot_data(self, data):
        for plt, val in zip(self._plots, data):
            plt.setData(range(len(val)),val)

    @QtCore.pyqtSlot(int)
    def generate_data(self, i):
        ang = np.arange(i, i + 720)
        cos_func = np.cos(np.radians(ang))
        sin_func = np.sin(np.radians(ang))
        tan_func = sin_func/cos_func
        tan_func[(tan_func < -3) | (tan_func > 3)] = np.NaN
        self.plot_data([sin_func, cos_func, tan_func])


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    gui = MainGui()
    gui.show()
    sys.exit(app.exec_())

推荐答案

似乎QGLWidget(顺便说一句,它已弃用,应该使用QOpenGLWidget)没有实现sizeHint(),因此它返回无效的大小(QSize(-1, -1)),这意味着可以将小部件的大小调整为0宽度和/或高度。

由于绘图小工具具有扩展大小策略(并动态重新实现sizeHint()),因此gl小工具完全隐藏,高度为0。

一种可能的解决方案是将带有适当stretch参数的小部件添加到布局中。

如果希望两个Widget具有相同的高度,可以执行以下操作:

    central_layout.addWidget(self.cube, stretch=1)
    central_layout.addWidget(self.plot, stretch=1)

请注意,拉伸是基于比率的(仅考虑整数),因此,如果您希望立方体具有绘图高度的一半:

    central_layout.addWidget(self.cube, stretch=1)
    central_layout.addWidget(self.plot, stretch=2)

或者,您可以使用setMinimumHeight()作为gl小部件,但由于绘图具有扩展策略(通常优先),gl小部件将始终具有该高度。更好的解决方案是为GL小工具实现QSizeHint设置展开策略,但请记住,绘图小工具具有动态大小提示,因此它始终需要一定的大小优先级。

class GLWidget(QtOpenGL.QGLWidget):
    def __init__(self, parent = None):
        QtOpenGL.QGLWidget.__init__(self, parent)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

    def sizeHint(self):
        return QtCore.QSize(300, 150)

    # ...

应该不需要手动调用__init__中的resizeGL(),也应该始终使用动态访问parent()函数来获取父级。

这篇关于QtWidget未显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆