Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
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.
Hi and thank you so much for your response
What do you mean? How should I modify my code? Can you give me an example?
What is your worker class ?
Here you have the documentation about the signals and slots concept.
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.
mkonst03 last edited by mkonst03
@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 ? ;-)