如何创建一个新窗口按钮 PySide/PyQt?

4 投票
2 回答
7493 浏览
提问于 2025-04-17 08:13

我在用Python 2.7的PyQt4/PySide做一个“新窗口”功能时遇到了问题。我把一个叫initNewWindow()的函数连接到一个操作上,这个操作是用来创建新窗口的,然后把它放在菜单栏里。这在桌面软件中是很常见的功能。但是,新的窗口并没有像我想的那样和原来的窗口并排显示,而是弹出来又关闭了。我正在处理的代码是专有的,所以我创建了一个示例,下面的代码也出现了同样的错误。有没有办法让这个功能正常工作?这个代码在Windows上用Python 2.7的PySide运行。

from PySide.QtCore import QSize
from PySide.QtGui import QAction
from PySide.QtGui import QApplication
from PySide.QtGui import QLabel
from PySide.QtGui import QMainWindow
from PySide.QtGui import QMenuBar
from PySide.QtGui import QMenu
from sys import argv

def main():
    application = QApplication(argv)
    window = QMainWindow()
    window.setWindowTitle('New Window Test')
    menu = QMenuBar(window)
    view = QMenu('View')
    new_window = QAction('New Window', view)
    new_window.triggered.connect(initNewWindow)
    view.addAction(new_window)
    menu.addMenu(view)
    label = QLabel()
    label.setMinimumSize(QSize(300,300))
    window.setMenuBar(menu)
    window.setCentralWidget(label)
    window.show()
    application.exec_()


def initNewWindow():
   window = QMainWindow()
   window.setWindowTitle('New Window')
   window.show() 


if __name__ == '__main__':
   main()

2 个回答

5

如果一个函数创建了一个PyQt对象,而这个对象是应用程序后续需要使用的,你就得确保有办法保持对它的引用。否则,当函数执行完毕后,Python的垃圾回收机制可能会立刻把它删除。

所以,你可以给这个对象指定一个父对象,或者把它作为其他对象的一个属性来保存。(原则上,这个对象也可以做成全局变量,但通常这样做被认为是不好的习惯)。

下面是你示例脚本的一个修改版本,展示了如何解决这个问题:

from PySide import QtGui, QtCore

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        menu = self.menuBar().addMenu(self.tr('View'))
        action = menu.addAction(self.tr('New Window'))
        action.triggered.connect(self.handleNewWindow)

    def handleNewWindow(self):
        window = QtGui.QMainWindow(self)
        window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        window.setWindowTitle(self.tr('New Window'))
        window.show()
        # or, alternatively
        # self.window = QtGui.QMainWindow()
        # self.window.setWindowTitle(self.tr('New Window'))
        # self.window.show()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.resize(300, 300)
    window.show()
    sys.exit(app.exec_())
3

initNewWindow() 函数执行完毕后,window 这个变量就会被删除,这样窗口的引用计数就变成了零,这就导致新创建的 C++ 对象也被删除了。所以你的窗口会立刻关闭。

如果你想让窗口保持打开状态,就需要保留一个引用。最简单的方法就是把新窗口设置为调用窗口的子窗口,并且设置它的 WA_DeleteOnClose 属性(可以查看 Qt::WidgetAttribute)。

撰写回答