I have a problem regarding the real-time update in a Q Label, because when I click the "start" button, the screen stays static for a few seconds while it performs the calculations, but what I need is that in the QLabel the status messages are displayed while advancing with the simulation. I have tried with the use of threads, but I do not understand it very well since it does not work out, if someone could help me with this I would appreciate it, since I do not handle much the Thread issue in Pyqt5. (I do not understand) Thank you very much
I attach both the code and the images of the interface:
INTERFACE
Before execution:
During execution:
After execution:
Codigo
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_())
Here I show the separate code of the call of simulacion.ui
Codigo
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_())
This part of the code is where I describe the functions that will be used within the Monte Carlo algorithm. where the texts that are specified should be shown in the QTextEdit It is important to mention that in the Montecarlo function, the data list is generated, which is what keeps all the simulations performed. This variable is necessary so that the save function in the simulation class can be executed
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)