来自 QWidget 的 PyQt5 通知

Posted

技术标签:

【中文标题】来自 QWidget 的 PyQt5 通知【英文标题】:PyQt5 notification from QWidget 【发布时间】:2017-09-24 11:20:03 【问题描述】:

我想通过 PC 上的手机发送我自己的通知,例如 notify-senf。我做弹出小部件,但我不能删除。当我删除它时,仍然有空的地方。我怎样才能做到这一点? 此代码是示例。

class Notification(QWidget):
    signNotifyClose = QtCore.pyqtSignal(str)

    def __init__(self, parent = None):
        time = datetime.now()
        currentTime = str(time.hour) + ":" + str(time.minute) + "_"
        self.LOG_TAG = currentTime + self.__class__.__name__ + ": "
        super(QWidget, self).__init__(parent)

        self.setWindowFlags(QtCore.Qt.FramelessWindowHint) #убирает заголовок, поверх всех окон (| QtCore.Qt.WindowStaysOnTopHint)
        resolution = QDesktopWidget().screenGeometry(-1)
        screenWidth = resolution.width()
        screenHeight = resolution.height()
        print(self.LOG_TAG + "width: " + str(resolution.width()) + " height: " + str(resolution.height()))
        self.count = 0 # Счетчик уведомлений
        self.timer = 3

        self.vboxMainLayout = QVBoxLayout() # layout contain notifications
        self.move(screenWidth, 0)
        self.setLayout(self.vboxMainLayout)

    def setNotify(self, title, notify):
        count = self.count
        title = QLabel()
        title.setStyleSheet("border: 1px solid #000")
        title.setText(title)
        title.setStyleSheet("font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: bold; padding: 0;")

        text = QLabel()
        text.setText(notify)
        text.setStyleSheet("font-family: 'Roboto', sans-serif; font-size: 12px; font-weight: normal; padding: 0;")

        gridNotify = QGridLayout()
        gridNotify.addWidget(title, 0, 0)
        gridNotify.addWidget(text, 1, 0)

        buttonClose = QPushButton()
        buttonClose.clicked.connect(self.deleteWidgets)
        buttonClose.setIcon(QIcon("res/close1.png"))
        buttonClose.setFlat(False)
        buttonClose.setMaximumWidth(14)
        buttonClose.setMaximumHeight(14)

        gridClose = QGridLayout()
        gridClose.addWidget(buttonClose, 0, 0)

        gridLayoutMain = QGridLayout()
        gridLayoutMain.setColumnStretch(0,1)
        gridLayoutMain.setColumnStretch(0,2)
        gridLayoutMain.setColumnStretch(0,3)
        gridLayoutMain.addLayout(gridClose, 0, 4)
        gridLayoutMain.addLayout(gridNotify, 0, 0)

        self.count += 1

        self.vboxMainLayout.addLayout(gridLayoutMain)
        self.show()
        threading.Timer(2, self.delete, args=(gridLayoutMain,)).start()

    def delete(self, layout):
        for i in reversed(range(layout.count())):
            item = layout.takeAt(i)
            widget = item.widget()
            if widget is not None:
                # widget.deleteLater()
            elif item.layout() is not None:
                print("")
                self.delete(item.layout())

通知

删除后放置

【问题讨论】:

为什么不用close()? 我添加了更多代码。如何关闭一条通知? 据我了解,您想在 2 秒后关闭应用程序并删除所有消息。我是对的? 没有。它的例子。通知应该一一关闭。我可以通过 self.close() 关闭所有通知。 试试我的答案:P 【参考方案1】:

为了简化任务,最好为消息创建一个小部件,如下所示:

class Message(QWidget):
    def __init__(self, title, message, parent=None):
        QWidget.__init__(self, parent)
        self.setLayout(QGridLayout())
        self.titleLabel = QLabel(title, self)
        self.titleLabel.setStyleSheet(
            "font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: bold; padding: 0;")
        self.messageLabel = QLabel(message, self)
        self.messageLabel.setStyleSheet(
            "font-family: 'Roboto', sans-serif; font-size: 12px; font-weight: normal; padding: 0;")
        self.buttonClose = QPushButton(self)
        self.buttonClose.setIcon(QIcon("res/close1.png"))
        self.buttonClose.setFixedSize(14, 14)
        self.layout().addWidget(self.titleLabel, 0, 0)
        self.layout().addWidget(self.messageLabel, 1, 0)
        self.layout().addWidget(self.buttonClose, 0, 1, 2, 1)

当您想先删除消息时,您必须使用布局的removeWidget() 函数将其从布局中删除,然后您必须使用deleteLater() 删除自身及其子窗口小部件。当我们发送信号时,我们可以通过sender() 获得发出它的对象,在我们的例子中它将是按钮,并通过它获得作为消息小部件的父对象。然后更新布局的正确大小,我们使用adjustSize()。即使删除整个小部件也需要一个最小值,因此建议在没有消息时将其关闭。

class Notification(QWidget):
    signNotifyClose = pyqtSignal(str)
    def __init__(self, parent = None):
        time = datetime.now()
        currentTime = str(time.hour) + ":" + str(time.minute) + "_"
        self.LOG_TAG = currentTime + self.__class__.__name__ + ": "
        super(QWidget, self).__init__(parent)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        resolution = QDesktopWidget().screenGeometry(-1)
        screenWidth = resolution.width()
        screenHeight = resolution.height()
        print(self.LOG_TAG + "width: " + str(resolution.width()) + " height: " + str(resolution.height()))
        self.nMessages = 0
        self.mainLayout = QVBoxLayout(self)
        self.move(screenWidth, 0)

    def setNotify(self, title, message):
        m = Message(title, message, self)
        self.mainLayout.addWidget(m)
        m.buttonClose.clicked.connect(self.onClicked)
        self.nMessages += 1
        self.show()

    def onClicked(self):
        self.mainLayout.removeWidget(self.sender().parent())
        self.sender().parent().deleteLater()
        self.nMessages -= 1
        self.adjustSize()
        if self.nMessages == 0:
            self.close()

下面是一个如何使用它的示例,代码如下:

class Example(QWidget):
    counter = 0

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setLayout(QVBoxLayout())
        btn = QPushButton("Send Notify", self)
        self.layout().addWidget(btn)

        self.notification = Notification()
        btn.clicked.connect(self.notify)


    def notify(self):
        self.counter += 1
        self.notification.setNotify("Title".format(self.counter),
                                    "message".format(self.counter))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Example()
    w.show()
    sys.exit(app.exec_())

【讨论】:

谢谢!告诉我,如何使它们在非活动主窗口中可见? 你想如何生成消息? 来自 QMainWindow self.notify = Notification() self.notify.setNotify(title, message) 并收到您写给我的代码 我不懂你,你自己解释清楚 手机接收通知到 PC 上的应用程序。 MainWindow 将其发送到 Notification 类。但是如果这个应用程序的主窗口处于非活动状态,通知在前台不可见 - 我必须关注这个应用程序才能看到通知

以上是关于来自 QWidget 的 PyQt5 通知的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 样式表用于 QWidget 的孩子更改 QWidget

Pyqt5_QWidget

setParent 的 PyQt5 行为以显示没有布局的 QWidget

在小部件 PyQt5 上设置布局后更改布局

PyQt5 QWidget不填充父

PyQt5 - 获取 QWidget 内的像素颜色