![](/img/trans.png)
[英]How can I update the text in real time while doing the calculations in a QTextEdit, without the interface freezing?
[英]How can I update the text in real time while doing the calculations in a QLabel, without the interface freezing?
我對Q標簽中的實時更新有問題,因為當我單擊“開始”按鈕時,屏幕在執行計算時會保持靜止幾秒鍾,但是我需要的是QLabel中的狀態在進行仿真時會顯示消息。 我已經嘗試過使用線程,但是由於無法解決問題,所以我不太了解,如果有人可以幫助我,我將不勝感激,因為我在Pyqt5中處理的線程問題不多。 (我不明白)非常感謝
我同時附上了接口的代碼和圖像:
接口
執行前:
執行期間:
執行后:
科迪哥
import sys
from PyQt5.QtWidgets import QStyleFactory,QApplication, QMainWindow,QFileDialog
from PyQt5.uic import loadUi
from PyQt5.QtGui import QTextCursor
from PyQt5.QtCore import *
import random
import time
import pandas as pd
parametros = [['Area', 0, 5]]
class simulacion(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
loadUi('simulacion.ui', self)
self.setStyle(QStyleFactory.create('Fusion'))
self.numsim = 10000000
self.pushButton.clicked.connect(self.calibracion)
self.pushButton_2.clicked.connect(self.save)
def cerrar(self):
self.close()
def calibracion(self):
self.montecarlo(self.numsim)
def generar_aleatorio(self):
aleatorio = []
for i in range(len(parametros)):
aleatorio.append(random.uniform(parametros[i][1],parametros[i][2]))
return aleatorio
def area(self,x1):
area = 3.1416 * x1**2
return area
def estado(self,starttime,last_print,contador, n, area):
global ult_print
acttime = time.time()
if acttime - last_print >= 2:
avg_time_per_run = (acttime - starttime) / (contador + 1)
timestr = time.strftime("%H:%M:%S", time.gmtime(round(avg_time_per_run * (n - (contador + 1)))))
text = ('Simulacion %i de %i - Tiempo estimado restante: %s\n' % (contador, n,timestr)+'Area = %5.3f' % (area)+'\n\n')
self.textEdit.moveCursor(QTextCursor.End)
self.textEdit.insertPlainText(text)
self.textEdit.moveCursor(QTextCursor.End)
ult_print = time.time()
return text
def montecarlo(self,n):
QApplication.processEvents()
global ult_print
text='Iniciando iteraciones con {} repeticiones...\n\n'.format(n)
self.textEdit.setText(text)
self.textEdit.moveCursor(QTextCursor.End)
ult_print = time.time()
starttime = time.time()
contador = 0
self.data=[]
self.num_sim=[]
QApplication.setOverrideCursor(Qt.WaitCursor)
while contador < n:
contador +=1
#Generar el numero aleatorio
z = self.generar_aleatorio()
#Simulacion del modelo con el numero aleatorio
y = self.area(z[0])
#Calculo de la funcion objetivo
self.estado(starttime,ult_print,contador,n,y)
QApplication.setOverrideCursor(Qt.CustomCursor)
def save(self):
file,_=QFileDialog.getSaveFileName(self,'Guardar Archivo de Simulación','','(*.csv)')
if file:
columns= []
for valor in self.num_sim:
columns.append('Simulación '+str(valor))
#print(columns)
df = pd.DataFrame(self.data,index=columns)
a = df.transpose()
a.to_csv(file,sep=';',index=False,encoding='utf-8')
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = simulacion()
widget.show()
sys.exit(app.exec_())
在這里,我顯示了simulacion.ui調用的單獨代碼
科迪哥
import sys
from PyQt5.QtWidgets import QStyleFactory,QApplication,
QMainWindow,QFileDialog
from PyQt5.uic import loadUi
from PyQt5.QtGui import QTextCursor
from PyQt5.QtCore import *
import random
import time
import pandas as pd
'''This part of the code calls the window designed in QTDesigner'''
class simulacion(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
loadUi('simulacion.ui', self)
self.setStyle(QStyleFactory.create('Fusion'))
self.numsim = 10000000
self.pushButton.clicked.connect(self.calibracion)
self.pushButton_2.clicked.connect(self.save)
def cerrar(self):
self.close()
def calibracion(self):
self.montecarlo(self.numsim)
def save(self, data):
file,_=QFileDialog.getSaveFileName(self,'Guardar Archivo de Simulación','','(*.csv)')
if file:
df = pd.DataFrame(data)
df.to_csv(file,sep=';',index=False,encoding='utf-8')
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = simulacion()
widget.show()
sys.exit(app.exec_())
在這部分代碼中,我描述了將在蒙特卡洛算法中使用的功能。 應該在QTextEdit中顯示指定的文本的位置。務必要提到的是,在Montecarlo函數中,將生成數據列表,這將保持所有模擬的執行。 該變量是必需的,以便可以執行模擬類中的保存功能
parametros = [['Area', 0, 5]]
def generar_aleatorio():
aleatorio = []
for i in range(len(parametros)):
aleatorio.append(random.uniform(parametros[i][1],parametros[i][2]))
return aleatorio
def area(x1):
area = 3.1416 * x1**2
return area
def estado(starttime,last_print,contador, n, area):
global ult_print
acttime = time.time()
if acttime - last_print >= 2:
avg_time_per_run = (acttime - starttime) / (contador + 1)
timestr = time.strftime("%H:%M:%S", time.gmtime(round(avg_time_per_run * (n - (contador + 1)))))
text = ('Simulacion %i de %i - Tiempo estimado restante: %s\n' % (contador, n,timestr)+'Area = %5.3f' % (area)+'\n\n')
self.textEdit.moveCursor(QTextCursor.End)
self.textEdit.insertPlainText(text)
self.textEdit.moveCursor(QTextCursor.End)
ult_print = time.time()
return text
def montecarlo(n):
global ult_print
text='Iniciando iteraciones con {} repeticiones...\n\n'.format(n)
#self.textEdit.setText(text)
#self.textEdit.moveCursor(QTextCursor.End)
ult_print = time.time()
starttime = time.time()
contador = 0
data=[]
num_sim=[]
#QApplication.setOverrideCursor(Qt.WaitCursor)
while contador < n:
contador +=1
#Generar el numero aleatorio
z = generar_aleatorio()
#Simulacion del modelo con el numero aleatorio
y = area(z[0])
#Calculo de la funcion objetivo
estado(starttime,ult_print,contador,n,y)
data.append(list(z+y))
#QApplication.setOverrideCursor(Qt.CustomCursor)
適當的解決方案是在另一個線程中執行阻塞任務,然后通過信號將數據發送到主線程中的GUI,Qt禁止從另一個主線程更新GUI,使用processEvents
強制GUI更新一些主線程。參數不能保證正確的操作,您可以在以下鏈接中了解有關此主題的更多信息: 我應該使用QCoreApplication :: processEvents()還是QApplication :: processEvents()? 。
在下面的示例中,我將在2個信號旁邊使用本機python線程,一個將發送文本,另一個將發送數據。
import random
import sys
import time
from threading import Thread
import pandas as pd
from PyQt5.QtCore import QObject, pyqtSignal, Qt
from PyQt5.QtWidgets import QApplication, QFileDialog, QStyleFactory, QMainWindow
from PyQt5.uic import loadUi
parametros = [['Area', 0, 5]]
def generar_aleatorio():
return random.uniform(*parametros[0][1:])
def area(x1):
area = 3.1416 * x1 ** 2
return area
class Helper(QObject):
send_signal = pyqtSignal(str)
data_signal = pyqtSignal(list)
helper = Helper()
def estado(starttime, last_print, contador, n, area):
acttime = time.time()
if acttime - last_print <= 2:
avg_time_per_run = (acttime - starttime) / (contador + 1)
timestr = time.strftime("%H:%M:%S", time.gmtime(round(avg_time_per_run * (n - (contador + 1)))))
text = 'Simulacion %i de %i - Tiempo estimado restante: %s\n' % (contador, n, timestr) \
+ 'Area = %5.3f\n\n' % area
helper.send_signal.emit(text)
def montecarlo(n):
data = []
text = 'Iniciando iteraciones con {} repeticiones...\n\n'.format(n)
helper.send_signal.emit(text)
ult_print = time.time()
starttime = time.time()
for contador in range(n):
z = generar_aleatorio()
y = area(z)
estado(starttime, ult_print, contador + 1, n, y)
ult_print = time.time()
time.sleep(0.001)
data.append([z, y])
helper.data_signal.emit(data)
class simulacion(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
loadUi('simulacion.ui', self)
self.setStyle(QStyleFactory.create('Fusion'))
self.numsim = 10000000
self.pushButton.clicked.connect(self.calibracion)
self.pushButton_2.clicked.connect(self.save)
def calibracion(self):
thread = Thread(target=montecarlo, args=(self.numsim,))
helper.send_signal.connect(self.textEdit.append, Qt.QueuedConnection)
helper.data_signal.connect(self.obtener_resultados)
thread.start()
def obtener_resultados(self, data):
self.data = data
def save(self, data):
file, _ = QFileDialog.getSaveFileName(self, 'Guardar Archivo de Simulación', '', '(*.csv)')
if file:
df = pd.DataFrame(self.data)
df.to_csv(file, sep=';', index=False, encoding='utf-8')
app = QApplication(sys.argv)
w = simulacion()
w.show()
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.