0

I am looking for a way to do cross-platform notification, here is some code from Cross-platform desktop notifier in Python , with some modification to make it runable:

# uiToast.py
from PySide import QtCore, QtGui
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.resize(547, 96)
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        MainWindow.setPalette(palette)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.display = QtGui.QTextBrowser(self.centralwidget)
        self.display.setGeometry(QtCore.QRect(0, 0, 551, 101))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 170, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        self.display.setPalette(palette)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.display.setFont(font)
        MainWindow.setCentralWidget(self.centralwidget)


#!/usr/bin/env python3
import sys, time
from PySide import QtCore, QtGui
import uiToast

window = None   # global

# Usage: Toast('Message')
class Toast(QtGui.QMainWindow):
    def __init__(self, msg):
        global window               # some space outside the local stack
        window = self               # save pointer till killed to avoid GC
        QtGui.QMainWindow.__init__(self)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.ui = uiToast.Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.display.setText(msg)

        self.toastThread = ToastThread()    # start thread to remove display
        self.connect(self.toastThread, QtCore.SIGNAL("finished()"), self.toastDone)
        self.toastThread.start()
        self.show()

    def toastDone(self):
        global window
        window = None               # kill pointer to window object to close it and GC

class ToastThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        time.sleep(2.0)             # wait and die



if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    program = Toast("hi")
    program.show()
    sys.exit(app.exec_())

The problem is the pop up window, which is supposed to disappear in 2 seconds, is hanging forever.

Community
  • 1
  • 1
qed
  • 22,298
  • 21
  • 125
  • 196

1 Answers1

1

The window isn't "hanging" - it's just that the code that attempts to close the window is pure nonsense.

Setting window to None will not delete the object, because it was assigned to the name program when it was created, and that reference will continue to exist after the toastDone method is called.

What you should do instead is just connect the thread's finished signal to the window's close slot. Try something like this:

class Toast(QtGui.QMainWindow):
    def __init__(self, msg):
        QtGui.QMainWindow.__init__(self)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.ui = uiToast.Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.display.setText(msg)
        self.toastThread = ToastThread()
        self.toastThread.finished.connect(self.close)
        self.toastThread.start()

class ToastThread(QtCore.QThread):
    def run(self):
        time.sleep(2.0)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336