0

I am working on a small web crawler project for coursework using PyQt. I am trying to do a very simple thing - when a button is clicked the crawler starts running, I want to disable the button until the run is completed. However, for some reason, the button only gets disabled after the crawler is done and then is immediately re-enabled.

Here is my code:

def run_crawler_btn_clicked(self):
    self.ShowPubsBtn.setEnabled(False)
    self.RunCrawlerBtn.setEnabled(False)
    self.RunCrawlerBtn.setText("Crawling nauka.offnews.bg...")

    BASE_URL = 'https://nauka.offnews.bg'
    crawler = Crawler(BASE_URL)
    crawler.run()

    self.RunCrawlerBtn.setEnabled(True)
    self.ShowPubsBtn.setEnabled(True)
    self.RunCrawlerBtn.setText("Crawl nauka.offnews.bg")

I suspect it is something related to slots and signals, but I couldn't put my finger on it.

I was also looking into QueuedConnection vs Direct Connection, but it should be queued in my case by default.

Any guidance on this issue will be greatly appreciated!

  • it probably has to do with threads and UI responsiveness ... you probably should run the Crawler asynchronously in another thread and re-enable based on a callback, so the main thread can run UI stuff... that will probably vary by platform, but macOS is famous for only being able to mutate UI elements on the main thread. – Grady Player Oct 11 '22 at 14:07
  • show us how you trigger the `run_crawler_btn_clicked` – A. Herlas Oct 11 '22 at 14:26
  • https://stackoverflow.com/questions/33954886/how-to-make-push-button-immediately-disabled – A. Herlas Oct 11 '22 at 14:38
  • It has nothing to do with slots or signals, but with the fact that your `run()` is *blocking* which means that it prevents the Qt event loop to process its events, including updating the widget painting that shows widgets as disabled. For simple cases (very short time of execution, not more than 5-10 seconds), calling `QApplication.processEvents()` right *before* calling the blocking function might suffice, otherwise you should use QThreads and custom signals to enable the buttons again. – musicamante Oct 11 '22 at 17:55
  • If you don't care about blocking the main thread with your `run()` call, you could also schedule it to execute a few milliseconds later using a `QTimer.singleShot`. – Carl HR Oct 12 '22 at 05:05
  • Thank you, all, guys! I will check all of your suggestions! – Michelle-lele Oct 12 '22 at 09:44
  • The function is triggered in the model where the button is defined: self.RunCrawlerBtn.clicked.connect(self.run_crawler_btn_clicked) – Michelle-lele Oct 12 '22 at 09:45
  • Thank you, all! I used QThread and all works as expected now! – Michelle-lele Oct 12 '22 at 11:14

0 Answers0