rajasekhar9035 | 2020-12-14 07:30:23 UTC | #1
I build an application with PyQt5 and i used QTableWidget for the table view i need to add 0th row and delete the 1000 th row every 1 millisecond once. my code has to receive the message payload every 1 millisecond once from the mqtt and update into the table every 1 millisecond once. i was tried with 100 milliSeconds once at that time it was working fine. If i test with 1 millisecond once its getting crashed and its giving python has crashed message. Please give me any sugestions.
Adding to QTableWidget: Data=[1,2,3,4] self.table.insertRow(0) for item in Data: self.table.setItem(0,i, QTableWidgetItem(str(item)))
Removing from QTableWidget: self.table.setRowCount(1000)
martin | 2020-12-14 19:41:54 UTC | #2
Hi @rajasekhar9035 welcome to the forum. Can you provide the error your seeing in Python?
Are you using threads to collect the data, these types of rate-dependent errors usually indicate that you're passing data between threads and triggering a segmentation fault.
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
rajasekhar9035 | 2020-12-15 13:20:01 UTC | #3
Thanks for your response @martin, i am seeing this error.
I am using QRunnable Widget and multi process with message Queue for sharing memory. process1: MQTT subscription Queue.put(Message.payload) process2:(QRunnable) Updating into Table Queue.get(Message.payload)
martin | 2020-12-16 16:29:44 UTC | #4
What is in the message payload?
If it's complex data (i.e. a list of objects) you might want to consider serializing the data somehow/doing a complete deepcopy before passing it. The Queue only ensures the the outer object is not shared between threads, but not any nested objects. This isn't a problem e.g. if you have a list of simple types (strings, ints, etc.) but if you have nested structures it can cause issues.
If you can shared some of your code, I can see if that's likely to be a problem here.
rajasekhar9035 | 2020-12-18 13:07:00 UTC | #5
[quote="martin, post:4, topic:633"] If it’s complex data (i.e. a list of objects) you might want to consider serializing the data somehow/doing a complete deepcopy before passing it. The Queue only ensures the the outer object is not shared between threads, but not any nested objects. This isn’t a problem e.g. if you have a list of simple types (strings, ints, etc.) but if you have nested structures it can cause issues. [/quote]
My message payload is like this:
c,1608182721,500,8,1,2,3,4,5,6,7,8 \r\n
c,1608182722,400,8,11,22,33,44,55,66,77,88\r\n\r\n
Hear is my subscription code, i am taking the message payload and split with "\r\n" .the out put is nested list eg:
WholeData=['c,1608182721,500,8,1,2,3,4,5,6,7,8','c,1608182722,400,8,11,22,33,44,55,66,77,88']
Means list of strings.
def on_message(client, userdata, message):
msg=message.payload
WholeData=[]
WholeData=msg.decode("utf-8").split('\r\n')#for middle \r\n
tableQue.put(WholeData)
And hear is my table updation [QRunnable widget] code
def UpdateTable(self):
while True:
if not self.Que.empty():
self.table.setRowCount(1000)
WholeData = self.Que.get()
for item in WholeData:
if len(item)>0:
try:
RawData=[]
RawData=item.split(',')
dummy= RawData[-1].split("\r\n")#for ending \r\n
RawData[-1]=dummy[0]
Data=[]
self.table.insertRow(0)
for i in range(1,4):
self.table.setItem(0, i-1, QTableWidgetItem(str(Data[i])))
for i in range(0,int(Data[3])):
self.table.setItem(0, i+3, QTableWidgetItem(str(Data[i+4])))
except:
print("exception updating into a table")
As per your suggestion i have tried with deep copy of my list like this
def on_message(client, userdata, message):
msg=message.payload
WholeData=[]
WholeData=msg.decode("utf-8").split('\r\n')
WholeData_copy = copy.deepcopy(WholeData)
tableQue.put(WholeData_copy)
Still crashing is there.
I hope you can understand the code flow, if its not understandable please let me know i will provide my full code.
martin | 2020-12-18 13:19:31 UTC | #6
Where is the following bit of code running, is this in your thread? (... it must be in another thread, or the while True
would block the GUI).
def UpdateTable(self):
while True:
I think then that the problem is that you're updating your widgets from your other thread -- you can't do this! Widgets can only be updated from the GUI thread.
You can emit the data from your thread using Qt signals, and listen to this signal in your GUI thread to trigger the updates. There is an example of emitting data via signals in this tutorial .
I think you could just replace your queue with this, then your updateTable
method would be (on your mainwindow).
def UpdateTable(self, WholeData):
# Defined on your main window. Receives updated data via signal.
for item in WholeData:
if len(item)>0:
try:
RawData=[]
RawData=item.split(',')
dummy= RawData[-1].split("\r\n")#for ending \r\n
RawData[-1]=dummy[0]
Data=[]
self.table.insertRow(0)
for i in range(1,4):
self.table.setItem(0, i-1, QTableWidgetItem(str(Data[i])))
for i in range(0,int(Data[3])):
self.table.setItem(0, i+3, QTableWidgetItem(str(Data[i+4])))
except:
print("exception updating into a table")
The signal would be defined for the type of data you're sending (a list)
class Signals(QObject):
data = pyqtSignal(list)
class MyRunner(QRunner):
signals = Signals()
....
Then you would hook your runner up to this, e.g. (on the main window)
runner = MyRunner()
runner.signals.data.connect(self.updateTable)
Does that make sense? You eliminate the while
loop since your handler method is only called when a signal is sent (i.e. when data is actually available) rather than waiting on a queue.