在PyQt中打开第二个窗口

13 投票
3 回答
45686 浏览
提问于 2025-04-15 16:26

我正在尝试使用pyqt,在点击QMainWindow上的一个按钮时显示一个自定义的QDialog窗口。但我总是遇到以下错误:

$ python main.py 
DEBUG: Launch edit window
Traceback (most recent call last):
  File "/home/james/Dropbox/Database/qt/ui_med.py", line 23, in launchEditWindow
    dialog = Ui_Dialog(c)
  File "/home/james/Dropbox/Database/qt/ui_edit.py", line 15, in __init__
    QtGui.QDialog.__init__(self)
TypeError: descriptor '__init__' requires a 'sip.simplewrapper' object but received a 'Ui_Dialog'

我看过几个在线教程,但大多数都没有详细讲解如何使用非内置的对话窗口。我使用pyuic4生成了主窗口和对话框的代码。我认为相关的代码如下。请问我缺少了什么呢?

class Ui_Dialog(object):
    def __init__(self, dbConnection):
        QtGui.QDialog.__init__(self)
        global c
        c = dbConnection

class Ui_MainWindow(object):
    def __init__(self, dbConnection):
        global c
        c = dbConnection

    def launchEditWindow(self):
        print "DEBUG: Launch edit window"
        dialog = QtGui.QDialog()
        dialogui = Ui_Dialog(c)
        dialogui = setupUi(dialog)
        dialogui.show()

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        conn = sqlite3.connect('meds.sqlite')
        c = conn.cursor()
        self.ui = Ui_MainWindow(c)
        self.ui.setupUi(self)

def main():
    app = QtGui.QApplication(sys.argv)
    program = StartQT4()
    program.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

附加问题:因为看起来在pyqt的函数回调中不能传递参数,那么把本来应该作为参数传递的东西(这个命名不太好的“c”)设置为全局变量,是不是获取信息到这些函数里的最佳方法呢?

3 个回答

1
class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

为什么要用 QtGui.QWidget.__init___ ???

应该用这个:

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)

你必须从父类调用 __init__ 方法(括号里的名字 '()')

QDialog 有两个很有用的功能:

exec_()
show()

第一个是等待对话框关闭,然后你可以访问对话框里的任何字段。第二个是显示对话框但不等待,这样你就需要设置一些信号和槽的连接,以便对话框的操作能正常工作。

比如,对于 exec_():

class Dialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(parent)
        line_edit = QLineEdit()
    ...

dialog = Dialog()
if dialog.exec_():   # here dialog will be shown and main script will wait for its closing (with no errors)
    data = dialog.line_edit.text()

小提示:你可以把你的 UI 类改成带布局的控件。而且可能问题在于你的 __init__ 应该是 __init__(self, parent=None, dbConnection)

因为当你在一个已有的控件里创建新的控件时,PyQt 可能会尝试把它设置为已有控件的子控件。(所以要把所有的 init 改成有额外的 parent 参数,这个参数必须放在第二个位置)。

3

Ui_Dialog应该从QtGui.QDialog继承,而不是从object继承。

class Ui_Dialog(QtGui.QDialog):
    def __init__(self, dbConnection):
        QtGui.QDialog.__init__(self)
        global c
        c = dbConnection
19

我以前也这样做过,可以告诉你这样是有效的。假设你的按钮叫做“Button”。

class Main(QtGui.QMainWindow):
    ''' some stuff '''
    def on_Button_clicked(self, checked=None):
        if checked==None: return
        dialog = QDialog()
        dialog.ui = Ui_MyDialog()
        dialog.ui.setupUi(dialog)
        dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        dialog.exec_()

这对我的应用程序有效,我相信对你的也应该没问题。希望这能帮到你,做一些简单的修改就能适应你的情况。祝大家有个愉快的一天。

撰写回答