如何使用 PyQt 从另一个 window 单击按钮打开一个 window?

How to open a window with a click of a button from another window using PyQt?

我正在尝试创建一个应用程序,但我一直被 "simple" 这样的东西打扰,如何通过单击按钮打开一个新的 window?我尝试使用 new_lib_btn.clicked.connect(newlib)newlib 是包含我的第二个 window 的文件,new_lib_btn 是应该打开 window 的按钮,它在我的主 window 如您所见:

mainwindow.py

from PyQt4 import QtCore, QtGui
import newlib
import sys
# Main Window

class Window (QtGui.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        centralwidget = QtGui.QWidget(self)
        self.mainLayout = QtGui.QVBoxLayout(centralwidget)
        self.mainLayout.setAlignment(QtCore.Qt.AlignCenter)
        self.setCentralWidget(centralwidget)

        self.resize(800, 600)
        self.setWindowTitle("Virtual Library")
        self.setStyleSheet("Window {border-image: url(lib.jpg);}")

        # ExitOption
        menu_action1 = QtGui.QAction("Exit", self)
        menu_action1.setShortcut("Ctrl+Q")
        menu_action1.setStatusTip('Exit The App')
        menu_action1.triggered.connect(self.close_application)

        self.statusBar()

        # MenuBar
        main_menu = self.menuBar()
        file_menu = main_menu.addMenu('Options')
        file_menu.addAction(menu_action1)



        self.home()

    def home(self):
        # NewLibrary btn
        new_lib_btn = QtGui.QPushButton("New Library", self)
        new_lib_btn.setGeometry(QtCore.QRect(310, 180, 141, 41))
        new_lib_btn.setStyleSheet("color: black;")

        # AccessLibrary btn
        access_lib_btn = QtGui.QPushButton("Access Library", self)
        access_lib_btn.setGeometry(QtCore.QRect(310, 250, 141, 41))
        access_lib_btn.setStyleSheet("color: black;")

        # FindNewBooks btn
        find_nbooks = QtGui.QPushButton("Find New Books*", self)
        find_nbooks.setGeometry(QtCore.QRect(310, 320, 141, 41))
        find_nbooks.setStyleSheet("color: black;")

        self.mainLayout.addWidget(new_lib_btn)
        self.mainLayout.addWidget(access_lib_btn)
        self.mainLayout.addWidget(find_nbooks_btn)
        self.show()

    def close_application(self):
        choice = QtGui.QMessageBox.question(self, 'Exit',
                                        "Close the application?",
                                        QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if choice == QtGui.QMessageBox.Yes:
            sys.exit()
        else:
            pass


def run():
    app = QtGui.QApplication(sys.argv)
    GUI = Window()
    sys.exit(app.exec_())


run()

这是我的第二个 window,我想用 new_lib_btn

打开

newlib.py

class NewLibrary (QtGui.QMainWindow):
    def __init__(self):
         super(NewLibrary, self).__init__()

         self.resize(800,600)
         self.setWindowTitle("New Library")
         self.setStyleSheet("NewLibrary {border-image: url(wood.jpg);}")

         # File Options
         file_action1 = QtGui.QAction("New Library", self)
         file_action1.setShortcut("Ctrl+N")
         file_action1.setStatusTip("Creates a new library")

         file_action2 = QtGui.QAction("Exit this!", self)
         file_action2.setShortcut("Ctrl+Q")
         file_action2.setStatusTip("Closes The App")
         file_action2.triggered.connect(self.close_application)

         #File Menu
         main_menu = self.menuBar()
         file_menu = main_menu.addMenu("File")
         file_menu.addAction(file_action1)
         file_menu.addAction(file_action2)
         self.newLib()

         self.newLib()

     def newLib(self):
         centralwidget = QtGui.QWidget(self)
         self.mainLayout = QtGui.QVBoxLayout(centralwidget)
         self.mainLayout.setAlignment(QtCore.Qt.AlignCenter)

         #some useful buttons in the future

         self.setCentralWidget(centralwidget)
         self.show()

     def close_application(self):
         choice = QtGui.QMessageBox.question(self, 'Exit',
                                        "Close the application?",
                                        QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
         if choice == QtGui.QMessageBox.Yes:
             sys.exit()
         else:
             pass
def runNewLib():
    app = QtGui.QApplication(sys.argv)
    gui = NewLibrary()
    sys.exit(app.exec_())
runNewLib()

我搜索了很多关于这个但我无法理解少数与我的情况有些接近的,所以我寻求帮助,看起来很简单但我不明白:/,单击 new_lib_btn 打开第二个 window 应该怎么做?请帮助。

我认为您发布的代码存在几个问题。首先,NewLibrary 构造函数中有两次对 self.newLib() 的调用。其次,您可能希望将对 runNewLib() 的调用放在 newlib.py 底部的 if __name__... 块后面,如下所示:

if __name__ == '__main__':
    runNewLib()

否则,每次您尝试导入 newlib.py 时,它都会尝试 运行 NewLibrary 作为单独的应用程序。

关于您提出的问题,我认为您实际上并不想在 Window.home()NewLibrary.newLib() 中调用 self.show()。更典型的模式是创建 WindowNewLibrary 的实例,然后在该实例上调用 show()。因此,在您的 Window class 中,您将添加一个函数来创建 NewLibrary 的实例,然后在其上调用 show,就像这样

def create_new_library_window(self):
    self.new_lib = newlib.NewLibrary()
    self.new_lib.show()

请注意,正如 ekhumoro 指出的那样,您必须保留对 new_lib 的引用,否则函数退出时它将被垃圾回收。然后在 NewLibrary.home() 创建 new_lib_btn 后将其连接到这个新函数:

new_lib_btn.clicked.connect(self.create_new_library_window)

工作示例

此示例创建了一个带有一个大按钮的主 window,单击该按钮将打开第二个 window。它使用两个 classes 继承自 QMainWindow,如您的问题。首先,在 main.py:

from PyQt4 import QtGui
from new_window import NewWindow


class Window(QtGui.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self._new_window = None
        self._button = QtGui.QPushButton('New Window', self)
        self._button.clicked.connect(self.create_new_window)
        self.setCentralWidget(self._button)

    def create_new_window(self):
        self._new_window = NewWindow()
        self._new_window.show()

if __name__ == '__main__':
    app = QtGui.QApplication([])
    gui = Window()
    gui.show()
    app.exec_()

__init__ 函数创建一个按钮并将其连接到 create_new_window 函数。单击按钮时,将调用 create_new_window。在 create_new_window 内部,我们创建了一个 NewWindow 的实例并将其分配给 class 成员以维护对 window 的引用并防止它被垃圾收集。然后我们在这个新的 window 上调用 show 来显示它。

在底部,我们使用通常的 if __name__ == '__main__': 模式来控制此文件是否 运行 是应用程序。如果此文件是从命令行执行的(如 python main.py),__name__ == '__main__' 的计算结果为真,GUI 应用程序将启动。这样做的好处是允许该文件具有双重用途:它可以作为标准 python 包导入,或作为应用程序执行,所有这些都使用同一个文件。

然后在 new_window.py:

from PyQt4 import QtGui


class NewWindow(QtGui.QMainWindow):
    def __init__(self):
        super(NewWindow, self).__init__()
        self._new_window = None
        self._label = QtGui.QLabel('Hello, is it me you\'re looking for?')
        self.setCentralWidget(self._label)


if __name__ == '__main__':
    app = QtGui.QApplication([])
    gui = NewWindow()
    gui.show()
    app.exec_()

此文件定义了第二个 QMainWindow,它使用标签作为其中央小部件。它还使用 __name__ == '__main__' 模式;这个文件也可以作为一个独立的应用程序执行,或者像上面的 main.py 一样导入。