You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5主窗口打开的子窗口控件无法点击问题求助

问题:PyQt5子窗口控件无法点击,主窗口关闭后恢复正常

我用PyQt5开发桌面应用,点击主窗口按钮打开QWidget子窗口后,窗口能正常显示,但所有按钮、ComboBox控件都无法点击;关闭主窗口后,子窗口仍保持打开,且控件恢复可点击状态。以下是子窗口代码和主窗口调用方法,求解决。

子窗口代码

from PyQt5 import QtCore, QtGui, QtWidgets

class Interaction:
    def __init__(self):
        self.wanted = False
        self.interaction_type = None
        self.chain = None
        self.res_type = None
        self.res_number = None
        self.atom_name = None
        
    def set_interaction_type(self, interaction_type):
        self.interaction_type = interaction_type
    
    def set_chain(self, chain):
        self.chain = chain
    
    def set_res_type(self, res_type):
        self.res_type = res_type
        
    def set_res_number(self, res_number):
        self.res_number = res_number
        
    def set_atom_name(self, atom_name):
        self.atom_name = atom_name
    
    def set_wanted(self, wanted):
        if isinstance(wanted, bool):
            self.wanted = wanted
            
class Ui_Form(QtWidgets.QWidget):
    def __init__(self, list_of_available_items, parent):
        super().__init__()
        self.interactions_type = ['R', 'H', 'vdW']
        self.items = list_of_available_items
        self.filter = Interaction()
        self.setupUi()
        self.setFocusPolicy(QtCore.Qt.StrongFocus)
        # self.show()
    
    def setupUi(self):
        self.setObjectName("Form")
        self.resize(542, 128)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.interactionTypeLabel = QtWidgets.QLabel(self)
        self.interactionTypeLabel.setFocusPolicy(QtCore.Qt.NoFocus)
        self.interactionTypeLabel.setObjectName("interactionTypeLabel")
        self.gridLayout.addWidget(self.interactionTypeLabel, 0, 0, 1, 2)
        self.interactionTypeComboBox = QtWidgets.QComboBox(self)
        self.interactionTypeComboBox.setObjectName("interactionTypeComboBox")
        self.gridLayout.addWidget(self.interactionTypeComboBox, 0, 2, 1, 2)
        self.wantedRadioButton = QtWidgets.QRadioButton(self)
        self.wantedRadioButton.setObjectName("wantedRadioButton")
        self.gridLayout.addWidget(self.wantedRadioButton, 0, 4, 1, 1)
        self.unwantedRadioButton = QtWidgets.QRadioButton(self)
        self.unwantedRadioButton.setObjectName("unwantedRadioButton")
        self.gridLayout.addWidget(self.unwantedRadioButton, 0, 5, 1, 1)
        self.interactionChainLabel = QtWidgets.QLabel(self)
        self.interactionChainLabel.setObjectName("interactionChainLabel")
        self.gridLayout.addWidget(self.interactionChainLabel, 1, 0, 1, 1)
        self.interactionResTypeLabel = QtWidgets.QLabel(self)
        self.interactionResTypeLabel.setObjectName("interactionResTypeLabel")
        self.gridLayout.addWidget(self.interactionResTypeLabel, 1, 1, 1, 2)
        self.interactionResNLabel = QtWidgets.QLabel(self)
        self.interactionResNLabel.setObjectName("interactionResNLabel")
        self.gridLayout.addWidget(self.interactionResNLabel, 1, 3, 1, 1)
        self.interactionAtomNameLabel = QtWidgets.QLabel(self)
        self.interactionAtomNameLabel.setObjectName("interactionAtomNameLabel")
        self.gridLayout.addWidget(self.interactionAtomNameLabel, 1, 4, 1, 2)
        self.interactionChainComboBox = QtWidgets.QComboBox(self)
        self.interactionChainComboBox.setObjectName("interactionChainComboBox")
        self.gridLayout.addWidget(self.interactionChainComboBox, 2, 0, 1, 1)
        self.interactionResTypeComboBox = QtWidgets.QComboBox(self)
        self.interactionResTypeComboBox.setObjectName("interactionResTypeComboBox")
        self.gridLayout.addWidget(self.interactionResTypeComboBox, 2, 1, 1, 2)
        self.interactionResNComboBox = QtWidgets.QComboBox(self)
        self.interactionResNComboBox.setObjectName("interactionResNComboBox")
        self.gridLayout.addWidget(self.interactionResNComboBox, 2, 3, 1, 1)
        self.interactionAtomNameComboBox = QtWidgets.QComboBox(self)
        self.interactionAtomNameComboBox.setObjectName("interactionAtomNameComboBox")
        self.gridLayout.addWidget(self.interactionAtomNameComboBox, 2, 4, 1, 2)
        self.interactionDialogButtonBox = QtWidgets.QDialogButtonBox(self)
        self.interactionDialogButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.interactionDialogButtonBox.setObjectName("interactionDialogButtonBox")
        self.gridLayout.addWidget(self.interactionDialogButtonBox, 3, 4, 1, 2)

        self.retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self)
        
        self.interactionTypeComboBox.currentIndexChanged.connect(self.set_interaction_type)
        self.wantedRadioButton.clicked.connect(self.set_filter_wanted)
        self.unwantedRadioButton.clicked.connect(self.set_filter_unwanted)
        
        # DEFAULTS
        self.populate_interactions_type()
        self.wantedRadioButton.click()

    # CLASS METHODS
    def populate_interactions_type(self):
        for interaction in self.interactions_type:
                self.interactionTypeComboBox.addItem(interaction)
    
    def set_interaction_type(self):
        self.filter.set_interaction_type(self.interactionTypeComboBox.currentText())
        
    def set_filter_wanted(self):
        if self.wantedRadioButton.isChecked():
            self.filter.set_wanted(True)
        else:
            self.filter.set_wanted(False)
    
    def set_filter_unwanted(self):
        if self.unwantedRadioButton.isChecked():
            self.filter.set_wanted(False)
        else:
            self.filter.set_wanted(True)
    
    def get_interaction_obj(self):
        return self.filter

    def retranslateUi(self):
        self.interactionTypeLabel.setText("Select interaction type:")
        self.wantedRadioButton.setText("Enable")
        self.unwantedRadioButton.setText("Disable")
        self.interactionChainLabel.setText("Chain:")
        self.interactionResTypeLabel.setText("Res Type:")
        self.interactionResNLabel.setText("Res #:")
        self.interactionAtomNameLabel.setText("Atom Name:")

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_Form(list(), QtWidgets.QMainWindow)
    ui.show()
    sys.exit(app.exec_())

主窗口调用代码

def add_interaction(self):
    self.interaction_ui = Ui_Form(list(), self)
    self.interaction_ui.show()

解决方案

  • 问题根源:创建子窗口时未将父窗口参数传递给QWidget构造函数,导致子窗口未正确关联主窗口作为父控件,引发两个问题:

    1. 子窗口无法获取正确的焦点和事件处理权限,控件无法响应点击
    2. 主窗口关闭时,子窗口因无父控件关联,不会被自动销毁,独立存在
  • 修复步骤:
    修改子窗口__init__方法,将parent参数传递给父类构造函数:
    原代码:

    def __init__(self, list_of_available_items, parent):
        super().__init__()
    

    修改为:

    def __init__(self, list_of_available_items, parent):
        super().__init__(parent)
    
  • 额外优化:
    若希望子窗口为模态窗口(打开后主窗口无法操作),可在调用show()前添加self.setWindowModality(QtCore.Qt.ApplicationModal),符合常规弹窗交互逻辑。

内容的提问来源于stack exchange,提问作者NiccoloB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 17:15:36