0

I am trying to make an application and when the user clicks on the homepage it runs a thread with a While loop that updates certain things.

(MainWindow(QMainWindow))

def home_page_thread(self): # Home Page Thread
        while True:
            self.ui.label_home_title.setStyleSheet(f"color: rgb({random.randint(0, 255)}, {random.randint(0, 255)}, {random.randint(0, 255)});")
            
            time_now = datetime.now()
            time_now = time_now.strftime("%m:%m:%y  %H:%M:%S")
            
            self.ui.label_home_time.setText(time_now)  #  (QLabel)
            self.ui.text_info.setPlainText("Hello")    # <----- THIS IS THE ERROR   (QTextEdit)

            if KILL_THREADS:
                return
            elif self.viewing != "HOME":
                return

            time.sleep(1)

The thread would be started from a child class of class MainWindow(QMainWindow) (MainWindow imports the application from ui_main.py which is made in QtDesigner.

Relevant Code leading up to the Thread...

(MainWindow(QMainWindow))

MainUIFunctions.ui_definitions(self)  # This calls the UI Functions class which would start the thread.

If home button is clicked...

(MainUIFunctions(MainWindow))

self.ui.button_home.clicked.connect(lambda: MainUIFunctions.change_page(self, "HOME"))   # This calls a method within MainUIFunction which will be below that would switch to the Home Page and start the thread...

And the part that starts the thread...

(MainUIFunctions(MainWindow))

def change_page(self, page): # Changes Viewing Page
    if page == "HOME":
                self.ui.widget_content.setCurrentWidget(self.ui.home_page)
                self.ui.button_home.setStyleSheet("""\
                QPushButton {
                    border-radius: 14px;
                    border: 2px solid rgb(84, 88, 98);
                    background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(122, 138, 166, 255), stop:1 rgba(49, 59, 72, 255));
                }
                """
                )

                self.home_thread = threading.Thread(target=self.home_page_thread)
                self.home_thread.start()

I am getting an error when the code is ran and have located the error to this: self.ui.text_info.setPlainText("Hello") (QTextEdit)

ERROR:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x21176a622b0), parent's thread is QThread(0x211760c17b0), current thread is QThread(0x21176b9f520)

Does anyone know how to fix this?

I am using import threading

Kevin A.
  • 99
  • 2
  • 2
  • 10
  • Remember this: no access (including creation or modification) to GUI elements should **ever** happen outside the main Qt thread. This is valid for almost *any* ui based framework. – musicamante Jan 07 '21 at 13:44
  • But how would I make a rainbow text and constantly update a textbox without the UI Freezing? – Kevin A. Jan 07 '21 at 14:04
  • What do you mean by "rainbow text"? In any case, if you want to do some time-based action (animation, or object update at time intervals), threading is certainly *not* the right choice, nor use any blocking function or loop such as `time.sleep`. You should look for [QTimer](https://doc.qt.io/qt-5/qtimer.html) or the [animation framework](https://doc.qt.io/qt-5/animation-overview.html) instead. – musicamante Jan 07 '21 at 14:10
  • Basically what I want to do is if the User clicks on the HOME BUTTON then it would 1. Take them to the home button and 2. Start the process of a updating loop which would update the font color randomly of a label, update the text of another label and update the text of a Text Edit with a pause of 1 second before each update and to stop when the user switches to another page that is not HOME. To do this without making the program stop working, there would have to be a Thread. It works to do everything BUT update the Text of the TextEdit? – Kevin A. Jan 07 '21 at 15:27
  • As said, you **cannot** do it with threads: it isn't safe, it's unreliable and trying to do it because "it seems to work" is considered bad practice. The fact that it "works" for everything else but for the text edit is ininfluential, it only works as result of a combination of "lucky" factors, but you cannot rely on that. "To do this without making the program stop working, there would have to be a Thread.": no, you only need to use QTimer. Create one as an instance attribute, connect its `timeout` signal to the function that does what you need, then use `start()` or `stop()` when you need. – musicamante Jan 07 '21 at 15:48
  • Thanks I did it with a timer and it works great! I used a timer before to update a progressbar but forgot it was an option. – Kevin A. Jan 07 '21 at 16:44

0 Answers0