QTableWidget is crashing when i am doing updating table every 1 millisecond once

Heads up! You've already completed this tutorial.

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.


rajasekhar9035 | 2020-12-15 13:20:01 UTC | #3

Thanks for your response @martin, i am seeing this error.

image|363x183

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:

python
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:

python
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.

python
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

python
 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

python
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).

python
 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).

python
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)

python
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)

python
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.


Over 10,000 developers have bought Create GUI Applications with Python & Qt!

To support developers in [[ countryRegion ]] I give a [[ localizedDiscount[couponCode] ]]% discount with the code [[ couponCode ]] — Enjoy!

For [[ activeDiscount.description ]] I'm giving a [[ activeDiscount.discount ]]% discount with the code [[ couponCode ]] — Enjoy!

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak