[Python] RuntimeError: Internal C++ object (PySide6.QtWidgets.QHBoxLayout) already deleted...

Discussão em 'Python' iniciado por Stack, Janeiro 23, 2025.

  1. Stack

    Stack Membro Participativo

    I am working on a PySide6 application that dynamically shows or hides a custom input row (QLineEdit widgets) based on a selection from a QComboBox. The application allows users to select "Custom Input" from the ComboBox to enter custom project scope details, and when another option is selected, the custom input row is removed.

    This error only occurs if I switch the combo box to "Custom Input" and then another option.

    Below is the runtime error I encountered:

    Log file will be created at: C:\Users\Chris\OneDrive\Programming\Python_Projects\Current\Invoicing_UI\log_info.log
    Log file 'C:\Users\Chris\OneDrive\Programming\Python_Projects\Current\Invoicing_UI\log_info.log' created successfully.
    Traceback (most recent call last):
    File "C:\Users\Chris\OneDrive\Programming\Python_Projects\Current\Invoicing_UI\app\windows\email_creator_window.py", line 287, in update_email_type_combo_box_selection
    self.handle_combo_box_user_input()
    File "C:\Users\Chris\OneDrive\Programming\Python_Projects\Current\Invoicing_UI\app\windows\email_creator_window.py", line 300, in handle_combo_box_user_input
    self._delete_custom_input_row()
    File "C:\Users\Chris\OneDrive\Programming\Python_Projects\Current\Invoicing_UI\app\windows\email_creator_window.py", line 328, in _delete_custom_input_row
    self.customInputRowLayout.deleteLater()
    RuntimeError: Internal C++ object (PySide6.QtWidgets.QHBoxLayout) already deleted.


    The section of code I believe is causing the error:

    def update_email_type_combo_box_selection(self, selected_value):
    actions = self.get_report_type_actions()
    #FIXME set values for {orignalContainerNumber} and {NewContainerNumber}

    # Update the label using the dictionary stored in actions
    action_text = actions.get(selected_value, "Invalid selection. Please choose an email type.")
    self.emailTypeSelectionLabel.setText(actions.get(action_text))

    # Define Variables for Project scope Type, and description for Type
    self.projectScopeDescription = action_text
    self.getProjectScopeType = selected_value


    # Handle user 'Custom Input' selection in combobox.
    self.handle_combo_box_user_input()

    def handle_combo_box_user_input(self):
    #TODO make logic that checks if "Custom Input combo box" is navigated away from and then call self._delete_custom_input_row() instead of everytime Custom Input is not selected.
    if self.is_custom_input_selected() == True:
    # Create horizontal layout for the row
    self.customInputRowLayout = QHBoxLayout()
    self._create_custom_input_row()
    self.customInputRow = self.formLayout.rowCount() # Track the row index
    self.formLayout.addRow("Enter project scope details:", self.customInputRowLayout)
    else:
    # Remove the "Custom Input" row if it exists
    if hasattr(self, "customInputRowLayout"):
    self._delete_custom_input_row()


    def _create_custom_input_row(self):
    # Creates Custom input row.
    # Create widgets
    self.userProjectScopeType = QLineEdit()
    self.userProjectScopeType.setPlaceholderText('Enter Project scope, Example: "Transload", "Inspection", or "other".')

    self.userProjectScopeDetails = QLineEdit()
    self.userProjectScopeDetails.setPlaceholderText("Enter Project Scope details, containers, etc")

    # Add widgets to the horizontal layout
    self.customInputRowLayout.addWidget(self.userProjectScopeType)
    self.customInputRowLayout.addWidget(self.userProjectScopeDetails)


    def custom_row_actions(self):
    """
    Collects user inputs and returns them as a dictionary.
    """
    return {
    self.userProjectScopeType.text() : self.userProjectScopeDetails.text(),
    }

    def _delete_custom_input_row(self):
    # Deletes Custom input row.
    self.formLayout.removeRow(self.customInputRow)
    self.customInputRowLayout.deleteLater()
    del self.customInputRowLayout
    del self.customInputRow


    The class that is trying to access self.userProjectScopeType is:

    def create_email(self):
    """
    Creates an email by dynamically generating its body based on user input or predefined options.

    Description:
    ------------
    This method initializes an instance of the `EmailLogic` class and generates the email body based on whether
    custom input is selected or predefined options are being used. If `is_custom_input_selected` is `True`,
    the email body is constructed using the values from `userProjectScopeType` and `custom_row_actions`.
    Otherwise, it uses the selected report type from `emailTypeSelectionComboBox`. The generated email is
    then printed to the console.

    Parameters:
    -----------
    None

    Instance Attributes Used:
    --------------------------
    - `is_custom_input_selected` (bool): A flag indicating whether custom input is selected.
    - `userProjectScopeType` (QLineEdit): A line edit widget for entering custom project scope types.
    - `custom_row_actions` (function): A function that dynamically generates additional input data for custom input.
    - `emailTypeSelectionComboBox` (QComboBox): A combo box containing predefined report type options.
    - `currentDate` (datetime): The current date to include in the email.
    - `get_container_seal_actions` (method): Retrieves container seal-related actions.
    - `TextEditor.save_plain_text_to_variable` (method): Retrieves the plain text from the text editor.
    - `photoFiles` (str): A string containing the filenames of attached photos.

    Returns:
    --------
    None
    """
    self.email = EmailLogic()

    if self.is_custom_input_selected and hasattr(self, 'userProjectScopeType'):
    self.email.generate_email_body(self.userProjectScopeType.text(), self.custom_row_actions(),
    self.currentDate, self.get_container_seal_actions(), self.TextEditor.save_plain_text_to_variable(), self.photoFiles)

    else:
    self.email.generate_email_body(self.emailTypeSelectionComboBox.currentText(), self.get_report_type_actions(),
    self.currentDate, self.get_container_seal_actions(), self.TextEditor.save_plain_text_to_variable(), self.photoFiles)
    self.email.print_email()


    After studying for some time, I think the issue is related to self.userProjectScopeType is referencing a widget that was deleted when the custom input row was removed. I understand this happens because the layout or widgets tied to the QLineEdit are deleted, but I can’t quite figure out the best way to handle this scenario.

    I’ve read that instead of deleting the layout and widgets, it might be better to use setVisible(False) to hide in turn preserving the references. Would that be a better approach when dealing with widgets that may still be referenced later? Or is there better way to handle dynamically added widgets and layouts?

    Continue reading...

Compartilhe esta Página