我有一個包含複選框的對話窗口,當他們每個都被選中時,一個特定的類需要被實例化並且在一個單獨的線程上運行一個任務(每個複選框一個)。我有14個複選框來檢查.isChecked()
屬性,並且可理解地檢查返回的布爾值,因爲它們中的每一個都不是高效的,並且需要更多的編碼。Pyqt和一般的python,這可以被認爲是一種正確的編碼方法嗎?
因此,我決定讓所有對應於複選框元素的子項目,只取得那些被選中的元素,將它們的名字附加到列表中,並通過它們匹配它們的名稱到d字典中循環,其中的關鍵字是支票的名稱框和值是相應的類來實例化。
例子:的可運行(即使他們中的一些使用不同的全局功能)
# class dictionary
self.summary_runnables = {'dupStreetCheckBox': [DupStreetDesc(),0],
'notStreetEsuCheckBox': [StreetsNoEsuDesc(),1],
'notType3CheckBox': [Type3Desc(False),2],
'incFootPathCheckBox': [Type3Desc(True),2],
'dupEsuRefCheckBox': [DupEsuRef(True),3],
'notEsuStreetCheckBox': [NoLinkEsuStreets(),4],
'invCrossRefCheckBox': [InvalidCrossReferences()],
'startEndCheckBox': [CheckStartEnd(tol=10),8],
'tinyEsuCheckBox': [CheckTinyEsus("esu",1)],
'notMaintReinsCheckBox': [CheckMaintReins()],
'asdStartEndCheckBox': [CheckAsdCoords()],
'notMaintPolysCheckBox': [MaintNoPoly(),16],
'notPolysMaintCheckBox': [PolyNoMaint()],
'tinyPolysCheckBox': [CheckTinyEsus("rd_poly",1)]}
# looping through list
self.long_task = QThreadPool(None).globalInstance()
self.long_task.setMaxThreadCount(1)
start_report = StartReport(val_file_path)
end_report = EndReport()
# start_report.setAutoDelete(False)
# end_report.setAutoDelete(False)
end_report.signals.result.connect(self.log_progress)
end_report.signals.finished.connect(self.show_finished)
# end_report.setAutoDelete(False)
start_report.signals.result.connect(self.log_progress)
self.long_task.start(start_report)
# print str(self.check_boxes_names)
for check_box_name in self.check_boxes_names:
run_class = self.summary_runnables[check_box_name]
if run_class[0].__class__.__name__ is 'CheckStartEnd':
run_class[0].tolerance = tolerance
runnable = run_class[0]()
runnable.signals.result.connect(self.log_progress)
self.long_task.start(runnable)
self.long_task.start(end_report)
例如
我不能張貼內容寫入文件作爲全局函數它們太多而不是全部14個任務執行相同類型的功能。這些函數的參數是包含報告靜態內容的其他字典和返回報告主要動態內容的SQL查詢的整型鍵。現在
class StartReport(QRunnable):
def __init__(self, file_path):
super(StartReport,self).__init__()
# open the db connection in thread
db.open()
self.signals = GeneralSignals()
# self.simple_signal = SimpleSignal()
# print self.signals.result
self.file_path = file_path
self.task = "Starting Report"
self.progress = 1
self.org_name = org_name
self.user = user
self.report_title = "Validation Report"
print "instantiation of start report "
def run(self):
self.signals.result.emit(self.task, self.progress)
if self.file_path is None:
print "I started and found file none "
return
else:
global report_file
# create the file and prints the header
report_file = open(self.file_path, 'wb')
report_file.write(str(self.report_title) + ' for {0} \n'.format(self.org_name))
report_file.write('Created on : {0} at {1} By : {2} \n'.format(datetime.today().strftime("%d/%m/%Y"),
datetime.now().strftime("%H:%M"),
str(self.user)))
report_file.write(
"------------------------------------------------------------------------------------------ \n \n \n \n")
report_file.flush()
os.fsync(report_file.fileno())
class EndReport(QRunnable):
def __init__(self):
super(EndReport,self).__init__()
self.signals = GeneralSignals()
self.task = "Finishing report"
self.progress = 100
def run(self):
self.signals.result.emit(self.task, self.progress)
if report_file is not None:
# write footer and close file
report_file.write("\n \n \n")
report_file.write("---------- End of Report -----------")
report_file.flush()
os.fsync(report_file.fileno())
report_file.close()
self.signals.finished.emit()
# TODO: checking whether opening a db connection in thread might affect the db on the GUI
# if db.isOpen():
# db.close()
else:
return
class DupStreetDesc(QRunnable):
"""
duplicate street description report section creation
:return: void if the report is to text
list[string] if the report is to screen
"""
def __init__(self):
super(DupStreetDesc,self).__init__()
self.signals = GeneralSignals()
self.task = "Checking duplicate street descriptions..."
self.progress = 16.6
def run(self):
self.signals.result.emit(self.task,self.progress)
if report_file is None:
print "report file is none "
# items_list = write_content(0, 0, 0, 0)
# for item in items_list:
# self.signals.list.emit(item)
else:
write_content(0, 0, 0, 0)
,我以前用這種方法,它無需使用多一直工作得很好。在這種情況下,它的工作原理很好的在一定程度上,我可以運行任務的第一時間,但如果我嘗試第二次,我得到了下面的Python錯誤運行:
self.long_task.start(run_class[0])
RuntimeError: wrapped C/C++ object of type DupStreetDesc has been deleted
我試圖運行它們之前,使用run_class[0].setAutoDelete(False)
在循環中,但pyQt崩潰與小型轉儲錯誤(我在QGIS中運行的代碼),我的程序存在很少機會了解發生了什麼。另一方面,如果我單獨運行我的類,檢查每個複選框的if else語句,那麼它工作正常,我可以再次運行任務,並且C++類不會被刪除,但它不是被刪除的,但它不是'至少從我很少的經驗來看,這是一種很好的編碼方法。
有沒有其他人可以建議不同的方法,以使這個運行順利,而不使用太多的代碼行?或者知道是否有更高效的模式來處理這個問題,我認爲這一點很常見?
似乎你以某種方式失去了你的對象引用。如果在循環結束時將'self.summary_runnables = {key:鍵的值,self.summary_runnables.items()}中的值'放在循環的結尾處,可以嘗試嗎? –
你能告訴我你在哪裏使用我的代碼並使用我使用的變量名稱來放這段代碼嗎? – user3523583
在你的循環中'self.long_task.start(run_class [0])'後面加'self.summary_runnables = {key:key,value in self.summary_runnables.items()}'的值。 –