WebView crashes when setUrl is called inside a thread
-
Hi. I am building an application using pySide2 and I notice a problem that occures:
- Only when the operation is inside a thread
- Only when the operation calls the method setUrl and some other webview methods
The process is the following:
- A client sends signals (1, 2, 3..etc)
- My application handles the signals and matches each number with an appropriate url
- Url should be shown to the screen and wait for a new signal
Question: The application does not work as intended. Instead of showing a new url, the application just terminates without any exception thrown. Why is this happening and how can I fix it? Thanks in advance
Some implementations regarding this issue.
# Execute a new thread that listens to socket worker = Worker(self.server_listen_respond, QUrl('http://www.google.com/')) # Start thread self.threadpool.start(worker) # Thread def server_listen_respond(self): # Thread operations apply here.... # ...After some checks a function is called (Slightly simplified) def change_screen(self): self.ui.lblUrl.setText('Changed to url' + ' google') # On the following expression, the program just terminates self.ui.webView.setUrl(QUrl("http://www.google.com"))
-
Hi and welcome to devnet,
One simple rule to follow:
Do not access GUI elements from a different thread than the GUI thread.Use signals and slots to transfert the data.
-
Below is my working class with the name Worker(QRunnable)
def __init__(self, fn, *args, **kwargs): super(Worker, self).__init__() self.fn = fn self.args = args self.kwargs = kwargs @Slot() def run(self): ''' Initialize the runner function with passed args, kwargs. ''' self.fn(*self.args, **self.kwargs)
When executing the two expressions below, The function server_listen_respond is executed. Inside that function I am trying to change the webview's Url....but it crashes
worker = Worker(self.server_listen_respond, some_init_url) self.threadpool.start(worker)
-
So you are still accessing a GUI element from a different thread ? As I already wrote, you can't do that.
-
@SGaist You asked me for my worker class that's why I sent it to you. I thought it was possible though. How you propose to change my code? Cause I am confused :(
Right now I am trying to follow your advice. I try to implement signals and slots, however I am new to this and it doesn't seem to work.
Edit: Thanks! I actually had made a false connection between signal and slot!
Here is what I did!- Inside QMainWindow
signal_change_movement = Signal(str) def __init__(self): self.signal_change_movement.connect(self.change_url)
- Inside thread
# Inside thread self.signal_change_movement.emit('https://forum.qt.io/')
-
Before diving deeper in that:
- Why do you need that secondary thread ?
- What experience do you have with threading ?
- What experience do you have with signals and slots ?
-
- Because I initialized a socket connection and I want to be able to mess around with the QMainWindow, and at the same time listen for incoming requests & responses
- I did a course in university about parallel programming
- Absolutely none :)
-
-
I highly encourage you to learn the signals and slots paradigm.
-
Qt is an asynchronous framework which means that you may not need an additional thread depending on what you need to process and how you process it.
-
Did they warm you about the nuclear footgun that it can be ? ;-)
-