按下按钮时获取 PyQt4 以打开另一个 Qt 窗口

Posted

技术标签:

【中文标题】按下按钮时获取 PyQt4 以打开另一个 Qt 窗口【英文标题】:Get PyQt4 to open another Qt window when a button is pressed 【发布时间】:2014-01-28 23:32:21 【问题描述】:

我试图让一个 Qt 窗口在按下按钮时在另一个 Qt 窗口中显示 matplotlib 图。我有一个 .py 文件可以生成带有按钮的 UI,另一个 .py 文件在运行时会打开一个显示图形的 QT 窗口。

如果我只运行第二个 .py 文件,会打开显示图形的 QT 窗口,没问题。

但是,问题是当我通过第一个运行第二个 .py 文件时,当我单击运行第二个的按钮时 pythonw.exe 崩溃了strong>.py 文件。

这是代码(一个 .py 文件。它为用户创建 UI,如果他们想查看 matplotlib 图形,他们可以单击按钮):

import matplotlib
matplotlib.use('Qt4Agg')
import pylab
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

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)

import matplotlibtest
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(690, 786)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.widget_2 = QtGui.QWidget(self.centralwidget)
        self.widget_2.setGeometry(QtCore.QRect(120, 20, 471, 51))
        self.widget_2.setObjectName(_fromUtf8("widget_2"))

        #...some other irrelevant code...
        
        self.plotButton = QtGui.QPushButton(self.layoutWidget_2)
        self.plotButton.setMinimumSize(QtCore.QSize(0, 23))
        self.plotButton.setObjectName(_fromUtf8("plotButton"))
        self.gridLayout_2.addWidget(self.plotButton, 9, 1, 1, 1)
        self.plotButton.clicked.connect(self.showimage)

    def showimage(self):
        matplotlibtest.main()

所以当用户点击plotButton时,ma​​tplotlibtest.py的main函数运行。

ma​​tplotlibtest.py 中,我有这段代码(来自 http://packtlib.packtpub.com/library/9781847197900/ch06)。此代码在运行时会打开一个 QT 窗口,该窗口显示一个简单的 matplotlib 图。这里没有问题——当这段代码运行时,它会按照我想要的方式打开图表。

# for command-line arguments
import sys
# Python Qt4 bindings for GUI objects
from PyQt4 import QtGui
# Numpy functions for image creation
import numpy as np
# Matplotlib Figure object
from matplotlib.figure import Figure
import matplotlib
matplotlib.use('Qt4Agg')
# import the Qt4Agg FigureCanvas object, that binds Figure to
# Qt4Agg backend. It also inherits from QWidget
from matplotlib.backends.backend_qt4agg \
import FigureCanvasQTAgg as FigureCanvas
# import the NavigationToolbar Qt4Agg widget
from matplotlib.backends.backend_qt4agg \
import NavigationToolbar2QTAgg as NavigationToolbar

class Qt4MplCanvas(FigureCanvas):

    def __init__(self, parent):
        # plot definition
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)
        t = np.arange(0.0, 3.0, 0.01)
        s = np.cos(2*np.pi*t)
        self.axes.plot(t, s)
        # initialization of the canvas
        FigureCanvas.__init__(self, self.fig)
        # set the parent widget
        self.setParent(parent)
        # we define the widget as expandable
        FigureCanvas.setSizePolicy(self,
        QtGui.QSizePolicy.Expanding,
        QtGui.QSizePolicy.Expanding)
        # notify the system of updated policy
        FigureCanvas.updateGeometry(self)

class ApplicationWindow(QtGui.QMainWindow):
    def __init__(self):
        # initialization of Qt MainWindow widget
        QtGui.QMainWindow.__init__(self)
        # set window title
        self.setWindowTitle("Matplotlib Figure in a Qt4 Window With NavigationToolbar")
        # instantiate a widget, it will be the main one
        self.main_widget = QtGui.QWidget(self)
        # create a vertical box layout widget
        vbl = QtGui.QVBoxLayout(self.main_widget)
        # instantiate our Matplotlib canvas widget
        qmc = Qt4MplCanvas(self.main_widget)
        # instantiate the navigation toolbar
        ntb = NavigationToolbar(qmc, self.main_widget)
        # pack these widget into the vertical box
        vbl.addWidget(qmc)
        vbl.addWidget(ntb)
        # set the focus on the main widget
        self.main_widget.setFocus()
        # set the central widget of MainWindow to main_widget
        self.setCentralWidget(self.main_widget)

def main():
    # create the GUI application
    qApp = QtGui.QApplication(sys.argv)
    # instantiate the ApplicationWindow widget
    aw = ApplicationWindow()
    # show the widget
    aw.show()
    sys.exit(qApp.exec_())

if __name__ == '__main__':
    main()    

如何在单击按钮时显示 matplotlib 图形?

为什么pythonw.exe会崩溃?

编辑:

如果我想传递参数 (x = [1,2,3], y=[1,1,1]) 来制作图形,我会输入class Qt4MplCanvas(FigureCanvas): def __init__(self,parent,x,y),当我构造它时我会写qmc = Qt4MplCanvas(self.main_widget, [1,2,3], [1,1,1])?

__init__ 中对于任何Qt 对象,我们是否运行super 的__init__ 来初始化Qt 对象的父对象? 为什么super(MyMainWindow,self) 的参数是?

为什么我们在 class Ui_MainWIndow(object): 但我们使用'QtGui.QMainWindow' class MyMainWindow(QtGui.QMainWindow)?

'object' 和 'QtGui.QMainWindow' 是参数吗?

当我们构造一个Ui_MainWindow的时候,为什么要写 self.ui = Ui_MainWindow() 并不是 self.ui = Ui_MainWindow(object)?

【问题讨论】:

您只是想打开一个单独的窗口还是在主窗口中显示该窗口? 我正在尝试打开一个单独的窗口。 【参考方案1】:

好的,你的代码有几个问题:

    您有一个Ui 定义对象,但您没有使用它。 您不能在一次运行中使用两次matplotlib.use(一次在主 .py 中,一次在 matplotlibtest 中) 如果您想运行 PyQt 应用程序,您必须创建一个 QApplication 对象 其他涉及布局的小错误

对于解决方案,请检查代码,这是我对您的代码进行的一些修改以使其正常工作:

在您的 .py 主文件中

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_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(690, 786)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget) #here
        self.centralwidget.setLayout(self.gridLayout_2) #here

        #...some other irrelevant code...

        self.plotButton = QtGui.QPushButton() #here
        self.plotButton.setMinimumSize(QtCore.QSize(0, 23))
        self.plotButton.setObjectName(_fromUtf8("plotButton"))
        self.gridLayout_2.addWidget(self.plotButton, 9, 1, 1, 1)
        self.plotButton.clicked.connect(self.showimage)

    def showimage(self):
        #changes here
        from matplotlibtest import ApplicationWindow
        self.aw = ApplicationWindow()
        self.aw.show()

#class that actually shows something
class MyMainWindow(QtGui.QMainWindow):

    def __init__(self,parent=None):
        super(MyMainWindow,self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

#put the main window here
def main():
    import sys
    qApp = QtGui.QApplication(sys.argv)
    aw = MyMainWindow()
    aw.show()
    sys.exit(qApp.exec_())

if __name__ == '__main__':
    main()  

ma​​tplotlibtest.py 中:

# Python Qt4 bindings for GUI objects
from PyQt4 import QtGui
# Numpy functions for image creation
import numpy as np
# Matplotlib Figure object
from matplotlib.figure import Figure
import matplotlib
matplotlib.use('Qt4Agg')
# import the Qt4Agg FigureCanvas object, that binds Figure to
# Qt4Agg backend. It also inherits from QWidget
from matplotlib.backends.backend_qt4agg \
import FigureCanvasQTAgg as FigureCanvas
# import the NavigationToolbar Qt4Agg widget
from matplotlib.backends.backend_qt4agg \
import NavigationToolbar2QTAgg as NavigationToolbar

class Qt4MplCanvas(FigureCanvas):

    def __init__(self, parent):
        # plot definition
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)
        t = np.arange(0.0, 3.0, 0.01)
        s = np.cos(2*np.pi*t)
        self.axes.plot(t, s)
        # initialization of the canvas
        FigureCanvas.__init__(self, self.fig)
        # set the parent widget
        self.setParent(parent)
        # we define the widget as expandable
        FigureCanvas.setSizePolicy(self,
        QtGui.QSizePolicy.Expanding,
        QtGui.QSizePolicy.Expanding)
        # notify the system of updated policy
        FigureCanvas.updateGeometry(self)

class ApplicationWindow(QtGui.QMainWindow):
    def __init__(self):
        # initialization of Qt MainWindow widget
        QtGui.QMainWindow.__init__(self)
        # set window title
        self.setWindowTitle("Matplotlib Figure in a Qt4 Window With NavigationToolbar")
        # instantiate a widget, it will be the main one
        self.main_widget = QtGui.QWidget(self)
        # create a vertical box layout widget
        vbl = QtGui.QVBoxLayout(self.main_widget)
        # instantiate our Matplotlib canvas widget
        qmc = Qt4MplCanvas(self.main_widget)
        # instantiate the navigation toolbar
        ntb = NavigationToolbar(qmc, self.main_widget)
        # pack these widget into the vertical box
        vbl.addWidget(qmc)
        vbl.addWidget(ntb)
        # set the focus on the main widget
        self.main_widget.setFocus()
        # set the central widget of MainWindow to main_widget
        self.setCentralWidget(self.main_widget)

#deleted the main function here

【讨论】:

它有效。谢谢!关于你所做的事情,我有一些小问题,我在我的帖子的编辑中写道。你能看看我的问题吗?

以上是关于按下按钮时获取 PyQt4 以打开另一个 Qt 窗口的主要内容,如果未能解决你的问题,请参考以下文章

Qt:脚本在按下按钮之前运行

qt中当鼠标移到按钮上如何改变颜色

如何通过按下 Pyqt5 或 PyQt4 工具栏中的按钮来设置表单的显示

信号和槽Qt

在 iOS 中按下按钮时打开另一个视图

使用 Qt 同时运行线程