简体   繁体   English

从主窗口中的 UI 文件加载带有信号槽定义的小部件

[英]Load widget with signal-slot defintions from UI file in main window

I am having difficulties to load a widget generated by Qt Designer into my MainWindow.我很难将 Qt Designer 生成的小部件加载到我的 MainWindow 中。 It fails when I have also defined signals and slots in the UI file.当我还在 UI 文件中定义了信号和插槽时,它会失败。

# -*- coding: utf-8 -*-
import sys

from PyQt5 import QtWidgets
from PyQt5 import uic as pyuic

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args):
        super().__init__(*args)
        self.uifile = 'serialTandemGUI.ui'
        self.form_widget = pyuic.loadUi(self.uifile)
        _widget = QtWidgets.QWidget()
        _layout = QtWidgets.QVBoxLayout(_widget)
        _layout.addWidget(self.form_widget)
        self.setCentralWidget(_widget)

if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)

    w = MainWindow()
    w.show()

    app.exec_()

The error I get is: AttributeError: 'QWidget' object has no attribute 'init'我得到的错误是: AttributeError: 'QWidget' object has no attribute 'init'

Is it possible at all to inherit a widget this way?是否有可能以这种方式继承小部件? Tia!蒂亚!

Edit: Here's a simple UI file with a clicked() signal to demonstrate.编辑:这是一个带有 clicked() 信号的简单 UI 文件来演示。 It works as long as no signal definitions have been made (ie really just UI, but that is only half of the work, or even less).只要没有进行信号定义,它就可以工作(即实际上只是 UI,但这只是工作的一半,甚至更少)。

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QGroupBox" name="groupBox">
     <property name="title">
      <string>GroupBox</string>
     </property>
     <layout class="QGridLayout" name="gridLayout_2">
      <item row="0" column="0">
       <widget class="QPushButton" name="pushButton">
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>pushButton</sender>
   <signal>clicked()</signal>
   <receiver>Form</receiver>
   <slot>init()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>203</x>
     <y>162</y>
    </hint>
    <hint type="destinationlabel">
     <x>396</x>
     <y>201</y>
    </hint>
   </hints>
  </connection>
 </connections>
 <slots>
  <slot>init()</slot>
 </slots>
</ui>

Explanation:解释:

When you have created the .ui you have only pointed out that there is a connection between the clicked signal and the init method of the widget, but when you load it using loadUi() and do not pass it as a second parameter a QWidget will use the base class of the design, in your case QWidget, which clearly has no "init" method throwing you that error.当您创建 .ui 时,您只是指出单击信号和小部件的init方法之间存在连接,但是当您使用loadUi()加载它并且不将其作为第二个参数传递时,QWidget 将使用设计的基类,在你的情况下 QWidget,它显然没有“init”方法抛出你的错误。

Solution:解决方案:

You must create a class that inherits from QWidget and has the init method, and then use loadUi() to fill it out.必须创建一个继承自 QWidget 的类,并有init方法,然后使用loadUi()填写。

# -*- coding: utf-8 -*-
import os
import sys

from PyQt5 import QtCore, QtWidgets, uic as pyuic


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        current_dir = os.path.dirname(os.path.realpath(__file__))
        uifile = os.path.join(current_dir, "serialTandemGUI.ui")
        pyuic.loadUi(uifile, self)

    @QtCore.pyqtSlot()
    def init(self):
        print("init")


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.form_widget = Widget()
        _widget = QtWidgets.QWidget()
        _layout = QtWidgets.QVBoxLayout(_widget)
        _layout.addWidget(self.form_widget)
        self.setCentralWidget(_widget)


if __name__ == "__main__":
    app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)

    w = MainWindow()
    w.show()

    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM