在学习和测试PyQt相关部件功能的时候,老猿经常是不同的窗口新建一个类,再新建一个Application来使用这个窗口类进行测试。

为了减少应用框架代码的重复开发,老猿决定采用主窗口叠加测试窗口的模式来进行功能测试,即主窗口和主程序基本保持不变,采用主窗口点击按钮弹出测试窗口的形式来验证测试窗口的功能,这样不用每回都新建工程,也不用重写(其实基本上是赋值粘贴)主程序的代码。

于是老猿创建了一个QWidget类型的应用主窗口,在主窗口上加了一个“弹出窗口”的按钮,并建立了按钮clicked信号和槽函数之间的连接。槽函数代码如下:

def popWin(self):
         popwin = popWinTestWin()    #创建测试窗口对象
         popwin.show()

代码完成后,执行却发现窗口一闪而逝。进行代码调试,发现大部分情况下,如果采用单步跟踪模式则可以,有时也不行,其他都无法正常显示子窗口。于是到处查资料,没有查到PyQt在网上有类似的问题,而Qt的C语言代码倒是碰到过,有人答复是不该在槽函数本地空间中创建对象,会导致栈溢出,也有人说主窗口和弹出窗口不能是同一种类型,但没有详细说是大类型如QWidget还是派生类型自定义的。

老猿写了个测试程序,提供不同类型的弹出窗在不同名字空间创建后弹出的功能。

如图:

python子窗体可以放在模块中 python创建子窗口_弹窗


对应槽函数代码如下:

def createPopwin(self,winTypeChoice):
        if winTypeChoice == 0:
            w = popWinTestWin()
        elif winTypeChoice == 1:
            w = widgetPopWin()
        else:
            w = dialogPopWin()
        return w

    def popWin(self):
       winTypeChoice = self.popTypeChoice.checkedId()
       namespaceChoice = self.popNamespaceChoice.checkedId()
       if namespaceChoice == 0:
           popwin = self.createPopwin(winTypeChoice)
           popwin.show()
       elif namespaceChoice == 1:
           self.popwin = self.createPopwin(winTypeChoice)
           self.popwin.show()
       else:
           QtWidgets.qApp.popwin = self.createPopwin(winTypeChoice)
           QtWidgets.qApp.popwin.show()

经过测试发现就是弹窗采用槽函数局部变量创建时存在问题,但问题原因还是没找到,夜深了直接睡了,第二天一醒来豁然开朗,这个问题其实就是局部变量的生命周期问题,槽函数结束局部变量生命周期结束,因此对应窗口就消失了。所以在槽函数中弹出窗口,必须用非局部变量。