PyQt Creates Additive Dialogs After Each Click
<p>The title pretty much sums this issue up. I have a GUI that I've coded already and I'm trying to modify my error handling to better take advantage of PyQt's signals and slots. However, I've ran into a bit of an issue. I am testing an error handling statement where if a use clicks on a specific button there get a dialog telling them they have not entered the correct information yet. This dialog is controlled by signals and slots and does appear when it is supposed to. However, if I close the dialog then click the button again, the dialog pop up twice. This occurs additively. That is, if I click the button a third time the dialog comes up three times and so on. I'm not sure what else to do. I tried checking to make sure that all the QThreads end. I've even go so far as to use QThread.terminate() which you should never do and I still ended up with the same outcome. Any ideas as to what is causing this? Code snipet is below.</p>

<pre><code>def error_check_in_thread(self, method):
    self.connect(method, QtCore.SIGNAL("selenium_error"), lambda: self.error_launch("selenium_error"))
    self.connect(method, QtCore.SIGNAL("attribute_error"), lambda: self.error_launch("attribute_error"))
    self.connect(method, QtCore.SIGNAL("name_error"), lambda: self.error_launch("name_error"))
    self.connect(method, QtCore.SIGNAL("os_error"), lambda: self.error_launch("os_error"))
    self.connect(method, QtCore.SIGNAL("finished()"), lambda: self.append_log(0))
    self.connect(method, QtCore.SIGNAL("terminated()"), lambda: self.append_log(1))
    method.start()
    return

def error_launch(self, error):
    dialog = ErrorDialogs()
        if error == "selenium_error":
            dialog.pipeline_pilot_automation_error()
        elif error == "attribute_error":
            dialog.attribute_error()
        elif error == "os_error":
            dialog.path_error()
        elif error == "session_info_error":
            dialog.session_info_error()
        self.error_counter += 1
        return

def append_log(self, exit_type):
    if exit_type == 0:
        self.log_edit_area.appendPlainText(str(MainGui.log_output[0]))
    elif exit_type == 1:
        self.log_edit_area.appendPlainText("THE METHOD WAS TERMINATED PREMATURELY\n" + "#"*50)
    MainGui.log_output = []


class WorkingThread(QtCore.QThread):
    def __init__(self, selector):
        QtCore.QThread.__init__(self)
        self.selector = selector
        self.method_info = None

    def __del__(self):
        self.wait()

    # Controls which function to launch in another thread based on button presses in MainGui
    def run(self):
        print("start")
        try:
            if self.selector == 1:
                self.method_info = "DIRECTORIES AND SUBDIRECTORIES CREATION "
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
                asa.mkdirsda(MainGui.hdg_da_path, MainGui.da_batch_folder, MainGui.da_batch_subfolders)
            elif self.selector == 2:
                self.method_info = "LIMS SAMPLE SHEET MOVEMENT TO AUTOSCORE SUBDIRECTORY "
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
                asa.mvlims(MainGui.needs_gs_lims_file, MainGui.subfolder_autoscore,
                           MainGui.lims_samplesheet)
            elif self.selector == 3:
                self.method_info = "GENOMESTUDIO "
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "STARTED FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
                asa.gsprocess(MainGui.subfolder_genomestudio, MainGui.da_batch_name,
                              MainGui.lims_samplesheet_file)
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
            elif self.selector == 4:
                self.method_info = "FINAL REPORT MOVEMENT TO AUTOSCORE SUBDIRECTORY "
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
                asa.mvfinalreport(MainGui.subfolder_genomestudio, MainGui.da_batch_name,
                                  MainGui.finalreport_file, MainGui.subfolder_autoscore)
            elif self.selector == 5:
                self.method_info = "PIPELINE PILOT AUTOMATION "
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "STARTED FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
                asa.pipelineas(MainGui.userid, MainGui.userpass, MainGui.da_batch_name,
                               MainGui.raw_data_path)
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.da_batch_name + "\n" + "#"*50)
            elif self.selector == 6:
                self.method_info = "GBS SET DIRECTORIES CREATION"
                MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                          self.method_info + "SUCCESSFUL FOR: " + MainGui.gbs_set_name + "\n" + "#"*50)
                asa.mkdirsgbs(MainGui.gbs_path, MainGui.gbs_set_name)
        except (ElementNotVisibleException, ElementNotSelectableException, NoSuchElementException,
                NoSuchWindowException, UnexpectedAlertPresentException):
            MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                      self.method_info + "FAILED DUE TO SELENIUM ERROR\n" + "#"*50)
            selenium_error = QtCore.pyqtSignal()
            self.emit(QtCore.SIGNAL("selenium_error"))
            return
        except AttributeError:
            MainGui.log_output.append("ACTION AT: " + "[[" + str(datetime.datetime.now()) + "]]" + "\n" +
                                      self.method_info + "FAILED DUE TO ATTRIBUTE ERROR\n" + "#"*50)
            attribute_error = QtCore.pyqtSignal()
            self.emit(QtCore.SIGNAL("attribute_error"))
            print("stop")
            return
        return
</code></pre>

<p>I've answered my own question. The issue wasn't caused by any of my error handling but rather how I was passing information to the QThread class instances I was creating to start new thread. I was creating instances of QThread objects within the <strong>init</strong> method of my script and this wasn't letting the instances be collected as garbage because they were constantly in use in the main GUI loop. The solution was just to move the creation of QThread objections into a separate function.</p>

python user-interface error-handling dialog pyqt4