4

I am trying to do a warning message box that disappears automatically after few seconds. I have done this code:

def warning(self):
   messagebox = QtGui.QMessageBox(self)
   messagebox.setWindowTitle("wait")
   messagebox.setText("wait (closing automatically in {0} secondes.)".format(3))
   messagebox.setStandardButtons(messagebox.NoButton)
   self.timer2 = QtCore.QTimer()
   self.time_to_wait = 3
   def close_messagebox(e):
      e.accept()
      self.timer2.stop()
      self.time_to_wait = 3
   def decompte():
      messagebox.setText("wait (closing automatically in {0} secondes.)".format(self.time_to_wait))
      if self.time_to_wait <= 0:
         messagebox.closeEvent = close_messagebox
         messagebox.close()
      self.time_to_wait -= 1
   self.connect(self.timer2,QtCore.SIGNAL("timeout()"),decompte)
   self.timer2.start(1000)
   messagebox.exec_()

It works actually fine, for the automatic closing part. My problem is that when someone try to close it manually before the few seconds, by clicking on the x button of the window, the message box never closes. the "time to wait" goes negative, the message box shows "closing automatically in -4 seconds" for example, and it will never close.

Any idea how I could avoid that ? Regards

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
p.deman
  • 584
  • 2
  • 10
  • 24

2 Answers2

8

Try with my solution, I have created a new type of QMessageBox with your requirements

import sys
from PyQt4 import QtCore
from PyQt4 import QtGui


class TimerMessageBox(QtGui.QMessageBox):
    def __init__(self, timeout=3, parent=None):
        super(TimerMessageBox, self).__init__(parent)
        self.setWindowTitle("wait")
        self.time_to_wait = timeout
        self.setText("wait (closing automatically in {0} secondes.)".format(timeout))
        self.setStandardButtons(QtGui.QMessageBox.NoButton)
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.changeContent)
        self.timer.start()

    def changeContent(self):
        self.setText("wait (closing automatically in {0} secondes.)".format(self.time_to_wait))
        self.time_to_wait -= 1
        if self.time_to_wait <= 0:
            self.close()

    def closeEvent(self, event):
        self.timer.stop()
        event.accept()


class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        btn = QtGui.QPushButton('Button', self)
        btn.resize(btn.sizeHint())
        btn.move(50, 50)
        self.setWindowTitle('Example')
        btn.clicked.connect(self.warning)

    def warning(self):
        messagebox = TimerMessageBox(5, self)
        messagebox.exec_()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 1
    There's an off-by one error in your counter. You should move `self.time_to_wait -= 1` to the end of `changeContent`. Then remove the `setText` call in `__init__` and call `self.changeContent()` before starting the timer. (PS: it would also be nicer if you used [new-style signal and slot syntax](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html)). – ekhumoro Dec 02 '16 at 17:54
  • @ekhumoro this is pyqt4, new-style signal and slots syntax is only for pyqt5 – eyllanesc Dec 02 '16 at 18:01
  • No, they are also in PyQt4. The link I gave is for the PyQt4 docs. – ekhumoro Dec 02 '16 at 18:16
  • @ekhumoro Update the answer – eyllanesc Dec 02 '16 at 19:03
  • Great! But the most important part was the off-by-one error. Your code starts by waiting **two** seconds before changing the text to "4", and then finally stops on "2", rather than "1". – ekhumoro Dec 02 '16 at 19:31
  • @ekhumoro check my solution – eyllanesc Dec 03 '16 at 03:17
  • I already checked it and it has the error I described in my last comment. I also showed how to fix it in my first comment. – ekhumoro Dec 03 '16 at 16:50
  • Thanks ! (sorry for the delay ...) it's working perfectly. thanks again !! – p.deman Jan 17 '17 at 09:35
4

Using PyQt5

from PyQt5.QtCore import QTimer
time_milliseconds = 1000

QTimer.singleShot(time_milliseconds, lambda : messageBox.done(0))
Henrique R
  • 94
  • 7