Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread
-
wrote on 18 Jun 2024, 04:55 last edited by
I have a large project that I've been working on and I recently wanted to change a large QLabel into a series of rows of QLabels. I managed to get the class for it visually working the way I want it to, but inconsistently it crashes with only a few of the QLabels shown and a "QObject::setParent: Cannot set parent, new parent is in a different thread" error. Is there a way to see what components this error is related to exactly?
I think it must have something to do with the self.qlabels[i].setText(txt) or self.qlabels[i].show() lines in the class, but when I run it standalone I can't get it to return any errors or crashes. In the larger part of the project I am calling setFullText from a different thread, but I haven't run into this problem before when setting things from other classes.
I'm open to other ideas for moving things around or creating and deleting QLabels instead of hide/show, but this is the class code that came closest to working:
from PyQt6.QtWidgets import QLabel, QWidget, QVBoxLayout #QWidget that reduces input text lines to fit a number of Qlabels in the widget's height #adds "..." at the top if lines are reduced and top is true #adds "...more" at the bottom if lines are reduced and top is false class LongVLabels(QWidget): def __init__(self, top=False): super(LongVLabels,self).__init__() self.top = top #boolean storing if the top of the text is shown (True) or the bottom (False) self.fullText = "" #two layouts in the widget, one to measure available size and one to store added widgets self.layoutMain = QVBoxLayout() self.layoutH = QVBoxLayout() #start with 100 widgets (QLabels), hidden self.widgetCount = 100 self.qlabels = [QLabel() for x in range(self.widgetCount)] for x in self.qlabels: x.setStyleSheet("qproperty-indent:8;background-color:#ffc5d1;border-radius: 6px;") x.setFixedSize(500,18) self.layoutH.addWidget(x) x.hide() self.layoutMain.addLayout(self.layoutH) self.setLayout(self.layoutMain) def make_reduced_lines_text(self): #get the current line space available availableHeight = self.geometry().height() #hide any existing qlabels for x in self.qlabels: x.hide() reducedText = "" maxLines = int(availableHeight/24) splitText = self.fullText.split("\n") #number of lines for the box lenSplitText = len(splitText) if splitText == [""]: reducedText = "Almost done!" elif splitText == ["DONE"]: reducedText = "" elif lenSplitText < maxLines: #all the text fits, no need to adjust line count reducedText = self.fullText else: #text lines don't fit, resize if self.top: reducedText = "\n".join(splitText[:maxLines-1]) + "\nmore...." else: start = lenSplitText - maxLines + 2 #extra line space for the ellipsis reducedText = "...\n" + "\n".join(splitText[start:]) for i, txt in enumerate(reducedText.split("\n")): if i < self.widgetCount: self.qlabels[i].setText(txt) self.qlabels[i].show() def setFullText(self, textInput): self.fullText = textInput self.make_reduced_lines_text() def resizeEvent(self, event): self.make_reduced_lines_text()
I'm running Windows10 with Python v3.10.11 and PyQt6 v6.7.0.
-
I have a large project that I've been working on and I recently wanted to change a large QLabel into a series of rows of QLabels. I managed to get the class for it visually working the way I want it to, but inconsistently it crashes with only a few of the QLabels shown and a "QObject::setParent: Cannot set parent, new parent is in a different thread" error. Is there a way to see what components this error is related to exactly?
I think it must have something to do with the self.qlabels[i].setText(txt) or self.qlabels[i].show() lines in the class, but when I run it standalone I can't get it to return any errors or crashes. In the larger part of the project I am calling setFullText from a different thread, but I haven't run into this problem before when setting things from other classes.
I'm open to other ideas for moving things around or creating and deleting QLabels instead of hide/show, but this is the class code that came closest to working:
from PyQt6.QtWidgets import QLabel, QWidget, QVBoxLayout #QWidget that reduces input text lines to fit a number of Qlabels in the widget's height #adds "..." at the top if lines are reduced and top is true #adds "...more" at the bottom if lines are reduced and top is false class LongVLabels(QWidget): def __init__(self, top=False): super(LongVLabels,self).__init__() self.top = top #boolean storing if the top of the text is shown (True) or the bottom (False) self.fullText = "" #two layouts in the widget, one to measure available size and one to store added widgets self.layoutMain = QVBoxLayout() self.layoutH = QVBoxLayout() #start with 100 widgets (QLabels), hidden self.widgetCount = 100 self.qlabels = [QLabel() for x in range(self.widgetCount)] for x in self.qlabels: x.setStyleSheet("qproperty-indent:8;background-color:#ffc5d1;border-radius: 6px;") x.setFixedSize(500,18) self.layoutH.addWidget(x) x.hide() self.layoutMain.addLayout(self.layoutH) self.setLayout(self.layoutMain) def make_reduced_lines_text(self): #get the current line space available availableHeight = self.geometry().height() #hide any existing qlabels for x in self.qlabels: x.hide() reducedText = "" maxLines = int(availableHeight/24) splitText = self.fullText.split("\n") #number of lines for the box lenSplitText = len(splitText) if splitText == [""]: reducedText = "Almost done!" elif splitText == ["DONE"]: reducedText = "" elif lenSplitText < maxLines: #all the text fits, no need to adjust line count reducedText = self.fullText else: #text lines don't fit, resize if self.top: reducedText = "\n".join(splitText[:maxLines-1]) + "\nmore...." else: start = lenSplitText - maxLines + 2 #extra line space for the ellipsis reducedText = "...\n" + "\n".join(splitText[start:]) for i, txt in enumerate(reducedText.split("\n")): if i < self.widgetCount: self.qlabels[i].setText(txt) self.qlabels[i].show() def setFullText(self, textInput): self.fullText = textInput self.make_reduced_lines_text() def resizeEvent(self, event): self.make_reduced_lines_text()
I'm running Windows10 with Python v3.10.11 and PyQt6 v6.7.0.
@gfinleyg said in Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread:
In the larger part of the project I am calling setFullText from a different thread
Don't do that! It is not supported. Only UI/main thread may access UI stuff.
If you want to trigger a change in the UI from another thread then emit a signal in that other thread and connect a slot in the main thread where you do the UI change. -
wrote on 18 Jun 2024, 06:39 last edited by
Thanks for the quick response jsulm. I'll check out some other examples and see if I can figure out an easy way to interact with it using signals/slots.
Any ideas on the other question I had or is that info not easily exposed?
"QObject::setParent: Cannot set parent, new parent is in a different thread" error. Is there a way to see what components this error is related to exactly? -
I have a large project that I've been working on and I recently wanted to change a large QLabel into a series of rows of QLabels. I managed to get the class for it visually working the way I want it to, but inconsistently it crashes with only a few of the QLabels shown and a "QObject::setParent: Cannot set parent, new parent is in a different thread" error. Is there a way to see what components this error is related to exactly?
I think it must have something to do with the self.qlabels[i].setText(txt) or self.qlabels[i].show() lines in the class, but when I run it standalone I can't get it to return any errors or crashes. In the larger part of the project I am calling setFullText from a different thread, but I haven't run into this problem before when setting things from other classes.
I'm open to other ideas for moving things around or creating and deleting QLabels instead of hide/show, but this is the class code that came closest to working:
from PyQt6.QtWidgets import QLabel, QWidget, QVBoxLayout #QWidget that reduces input text lines to fit a number of Qlabels in the widget's height #adds "..." at the top if lines are reduced and top is true #adds "...more" at the bottom if lines are reduced and top is false class LongVLabels(QWidget): def __init__(self, top=False): super(LongVLabels,self).__init__() self.top = top #boolean storing if the top of the text is shown (True) or the bottom (False) self.fullText = "" #two layouts in the widget, one to measure available size and one to store added widgets self.layoutMain = QVBoxLayout() self.layoutH = QVBoxLayout() #start with 100 widgets (QLabels), hidden self.widgetCount = 100 self.qlabels = [QLabel() for x in range(self.widgetCount)] for x in self.qlabels: x.setStyleSheet("qproperty-indent:8;background-color:#ffc5d1;border-radius: 6px;") x.setFixedSize(500,18) self.layoutH.addWidget(x) x.hide() self.layoutMain.addLayout(self.layoutH) self.setLayout(self.layoutMain) def make_reduced_lines_text(self): #get the current line space available availableHeight = self.geometry().height() #hide any existing qlabels for x in self.qlabels: x.hide() reducedText = "" maxLines = int(availableHeight/24) splitText = self.fullText.split("\n") #number of lines for the box lenSplitText = len(splitText) if splitText == [""]: reducedText = "Almost done!" elif splitText == ["DONE"]: reducedText = "" elif lenSplitText < maxLines: #all the text fits, no need to adjust line count reducedText = self.fullText else: #text lines don't fit, resize if self.top: reducedText = "\n".join(splitText[:maxLines-1]) + "\nmore...." else: start = lenSplitText - maxLines + 2 #extra line space for the ellipsis reducedText = "...\n" + "\n".join(splitText[start:]) for i, txt in enumerate(reducedText.split("\n")): if i < self.widgetCount: self.qlabels[i].setText(txt) self.qlabels[i].show() def setFullText(self, textInput): self.fullText = textInput self.make_reduced_lines_text() def resizeEvent(self, event): self.make_reduced_lines_text()
I'm running Windows10 with Python v3.10.11 and PyQt6 v6.7.0.
wrote on 18 Jun 2024, 06:40 last edited by@gfinleyg said in Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread:
I'm open to other ideas for moving things around or creating and deleting QLabels instead of hide/show, but this is the class code that came closest to working:
What's the motivation for this change? It sounds like a significant pessimization.
-
wrote on 18 Jun 2024, 06:51 last edited by gfinleyg
@jeremy_k I tried some other solutions that created the QLabel objects on the fly based on the number of lines rather than making 100 of them and hide/showing them selectively, that path seems to make more sense to me, but it also encountered the same crash earlier. It's only 57 lines of code anyway :)
-
@jeremy_k I tried some other solutions that created the QLabel objects on the fly based on the number of lines rather than making 100 of them and hide/showing them selectively, that path seems to make more sense to me, but it also encountered the same crash earlier. It's only 57 lines of code anyway :)
wrote on 18 Jun 2024, 07:51 last edited by@gfinleyg said in Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread:
@jeremy_k I tried some other solutions that created the QLabel objects on the fly based on the number of lines rather than making 100 of them and hide/showing them selectively, that path seems to make more sense to me, but it also encountered the same crash earlier. It's only 57 lines of code anyway :)
It's not the creation and management of labels that I'm wondering about, but the decision to use more than one label (or QTextEdit/QPlainTextEdit/QTextBrowser) at all.
Lines of code isn't a good measure of runtime efficiency.
while true: pass
is only 1 line, but I'm still waiting for it to complete... -
wrote on 18 Jun 2024, 08:00 last edited by
@jeremy_k I'm planning to set each QLabel's background color based on what was in the text. These won't be updated frequently while the code is running so I don't think the overhead will be that bad. I can always switch to the one QLabel with shortened text that I was using before if it turns out to be too cumbersome.
-
@jeremy_k I'm planning to set each QLabel's background color based on what was in the text. These won't be updated frequently while the code is running so I don't think the overhead will be that bad. I can always switch to the one QLabel with shortened text that I was using before if it turns out to be too cumbersome.
wrote on 18 Jun 2024, 08:07 last edited by@gfinleyg said in Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread:
@jeremy_k I'm planning to set each QLabel's background color based on what was in the text.
This sounds like a use for rich text (aka html). The syntax highlighter example may be of help.
-
Thanks for the quick response jsulm. I'll check out some other examples and see if I can figure out an easy way to interact with it using signals/slots.
Any ideas on the other question I had or is that info not easily exposed?
"QObject::setParent: Cannot set parent, new parent is in a different thread" error. Is there a way to see what components this error is related to exactly?@gfinleyg said in Debugging inconsistent QObject::setParent: Cannot set parent, new parent is in a different thread:
"QObject::setParent: Cannot set parent, new parent is in a different thread" error
Don't modify UI from other threads and you will not have this error...
-
wrote on 18 Jun 2024, 09:00 last edited by
Yep, I got it working by adding some signal handling. I suppose if I run into another vague error I can ask about this again. Thanks!
-
1/11