如何在if & 下调用mousePressEvent pyqt中的paintEvent还有什么?

发布于 2025-01-11 02:31:21 字数 3474 浏览 1 评论 0原文

在 PyQt5 中,我正在开发一个基于传感器的 GUI,其中我绘制了一个切换电源关闭/打开按钮,其中我想添加一个功能,其中我切换电源按钮,并且我的桌面 GUI 应在该切换上关闭。就像我们在 gui 的关闭 [X] 按钮中所做的那样。

这是toggle.py代码并在main.py代码上调用i

main.py


class MainWindow(QMainWindow):

def __init__(self):
    super().__init__()
    # main dialog box
    self.turning_Icon = None
    self.setWindowTitle("Hatchery System")
    self.setStyleSheet("background-color: #2c313c;")
    self.setFixedWidth(1400)
    self.setFixedHeight(950)
    self.setWindowFlags(Qt.FramelessWindowHint)

    # Create Container and Layout
    self.container = QFrame(self)
    self.container.move(100, 50)
    self.container.resize(100, 50)
    self.container.setStyleSheet("background-color: #2c313c;")
    self.container.layout = QVBoxLayout()
    
    # toggle_power_button
    self.toggle = PyToggle()
    self.toggle.setStyleSheet("background-color: white")
    self.toggle.move(50, 50)
    self.container.layout.addWidget(self.toggle, Qt.AlignCenter, Qt.AlignCenter)
    self.container.setLayout(self.container.layout)

toggle.py代码:


import pylab as p
从 PyQt5.QtCore 导入 *
从 PyQt5.QtGui 导入 *
from PyQt5.QtWidgets import *

class PyToggle(QCheckBox):

def __init__(
        self,
        width=60,
        # height=50,
        bg_color="#777",
        circle_color="#fff",
        active_color="#00BCff"
        # active_color="red"

):
    QCheckBox.__init__(self)

    self.setFixedSize(width, 28)
    # self.setFixedSize(height, 40)
    self.setCursor(Qt.PointingHandCursor)

    # colors
    self._bg_color = bg_color
    self._circle_color = circle_color
    self._active_color = active_color

    # connect state changed
    self.stateChanged.connect(self.debug)

def debug(self):
    print(f"status: {self.isChecked()}")

def hitButton(self, pos: QPoint):
    return self.contentsRect().contains(pos)

def paintEvent(self, e):
    # SET painter
    p = QPainter(self)
    p.setRenderHint(QPainter.Antialiasing)
    p.setPen(Qt.NoPen)

    rect = QRect(0, 0, self.width(), self.height())

    p.setBrush(QColor(self._bg_color))
    p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)
    p.end()

def paintEvent(self, e):
    # SET painter
    p = QPainter(self)
    p.setRenderHint(QPainter.Antialiasing)

    # SET as No PEN
    p.setPen(Qt.NoPen)

    # draw rect
    rect = QRect(0, 0, self.width(), self.height())

    if not self.isChecked():
        # draw BG
        p.setBrush(QColor(self._bg_color))
        p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height()/2, self.height()/2)

        p.setBrush(QColor(self._circle_color))
        p.drawEllipse(3, 3, 22, 22)
        p.mousePressEvent = self.clickLine
    else:
        p.setBrush(QColor(self._active_color))
        p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)

        p.setBrush(QColor(self._circle_color))
        p.drawEllipse(self.width() - 26, 3, 22, 22)

def clickLine(self, mouseEvent):
    p.clicked.connect(self.close)

这里在 if 条件下我调用 mousePressEvent 但它不起作用

输出:
输入图片此处描述
输入图片此处描述
取消选中它关闭我的桌面 GUI 应该关闭。

In PyQt5, I am developing a sensors based GUI where i draw a toggle power off/on button in which i want to add a functionality where i toggle the power button and my desktop gui should be closed on that toggle. like we do in close [X] button of the gui.

here is the toggle.py code and call i on my main.py code

main.py


class MainWindow(QMainWindow):

def __init__(self):
    super().__init__()
    # main dialog box
    self.turning_Icon = None
    self.setWindowTitle("Hatchery System")
    self.setStyleSheet("background-color: #2c313c;")
    self.setFixedWidth(1400)
    self.setFixedHeight(950)
    self.setWindowFlags(Qt.FramelessWindowHint)

    # Create Container and Layout
    self.container = QFrame(self)
    self.container.move(100, 50)
    self.container.resize(100, 50)
    self.container.setStyleSheet("background-color: #2c313c;")
    self.container.layout = QVBoxLayout()
    
    # toggle_power_button
    self.toggle = PyToggle()
    self.toggle.setStyleSheet("background-color: white")
    self.toggle.move(50, 50)
    self.container.layout.addWidget(self.toggle, Qt.AlignCenter, Qt.AlignCenter)
    self.container.setLayout(self.container.layout)

toggle.py code:


import pylab as p
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class PyToggle(QCheckBox):

def __init__(
        self,
        width=60,
        # height=50,
        bg_color="#777",
        circle_color="#fff",
        active_color="#00BCff"
        # active_color="red"

):
    QCheckBox.__init__(self)

    self.setFixedSize(width, 28)
    # self.setFixedSize(height, 40)
    self.setCursor(Qt.PointingHandCursor)

    # colors
    self._bg_color = bg_color
    self._circle_color = circle_color
    self._active_color = active_color

    # connect state changed
    self.stateChanged.connect(self.debug)

def debug(self):
    print(f"status: {self.isChecked()}")

def hitButton(self, pos: QPoint):
    return self.contentsRect().contains(pos)

def paintEvent(self, e):
    # SET painter
    p = QPainter(self)
    p.setRenderHint(QPainter.Antialiasing)
    p.setPen(Qt.NoPen)

    rect = QRect(0, 0, self.width(), self.height())

    p.setBrush(QColor(self._bg_color))
    p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)
    p.end()

def paintEvent(self, e):
    # SET painter
    p = QPainter(self)
    p.setRenderHint(QPainter.Antialiasing)

    # SET as No PEN
    p.setPen(Qt.NoPen)

    # draw rect
    rect = QRect(0, 0, self.width(), self.height())

    if not self.isChecked():
        # draw BG
        p.setBrush(QColor(self._bg_color))
        p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height()/2, self.height()/2)

        p.setBrush(QColor(self._circle_color))
        p.drawEllipse(3, 3, 22, 22)
        p.mousePressEvent = self.clickLine
    else:
        p.setBrush(QColor(self._active_color))
        p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)

        p.setBrush(QColor(self._circle_color))
        p.drawEllipse(self.width() - 26, 3, 22, 22)

def clickLine(self, mouseEvent):
    p.clicked.connect(self.close)

here in if condition i call mousePressEvent but its not working

Output:
enter image description here
enter image description here
on unchecked it off my desktop gui should be close.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

中性美 2025-01-18 02:31:21

由于要求仅在再次取消选中该复选框时才关闭窗口,因此解决方案是连接到仅在这种情况下关闭的函数。请注意,您不应将 stateChanged 信号用于双状态复选框,因为它返回 Qt.CheckState 枚举,有 3 个状态。请改用toggled 信号。

        self.toggled.connect(self.checkForClose)

    def checkForClose(self, state):
        if not state:
            self.close()

关于您的尝试的重要说明。

首先,绘图函数永远不应该尝试做与绘图不直接相关的事情。这很重要,因为这些函数被频繁调用,可能每秒调用数十次,在某些情况下甚至每次将鼠标移到小部件上方时。

最重要的是,您覆盖的方法只是连接了 clicked 信号,这是错误的,原因有两个:

  1. 您的覆盖除了连接信号之外不执行任何其他操作,并且因为 QCheckBox 需要按顺序处理鼠标事件为了正确地改变它的状态(并最终发出点击信号),你会阻止所有这些 - 并且信号永远不会被发出,因为它永远不会被检查/取消检查;
  2. 每次按下任何鼠标按钮,信号就会连接;由于上述原因,它根本不会有任何结果,但这在概念上仍然是错误的,因为连接函数总是会被调用与连接到信号一样多的次数:你连接它两次吗?该函数将被调用两次;假设将发出信号(使用键盘仍然可能发生),则相关函数将被调用与用户尝试单击它的次数一样多。

另一个需要记住的重要方面是 PyQt 对函数使用引用缓存;第一次使用默认实现调用虚拟函数后,覆盖实例属性将不起作用。

假设您想做相反的事情(当状态为 True 时连接信号),它不会起作用,因为那时默认的 mousePressEvent 处理程序已经是调用,覆盖根本没有任何效果。

Since the requirement is to close the window only when the check box is unchecked again, the solution is to connect to a function that will only close in that case. Note that you should not use the stateChanged signal for dual state check boxes, as it returns a Qt.CheckState enum, which has 3 states. Use the toggled signal instead.

        self.toggled.connect(self.checkForClose)

    def checkForClose(self, state):
        if not state:
            self.close()

An important note about your attempt.

First of all, a paint function should never try to do something that is not directly related to drawing. This is important as those functions are called very often, potentially dozens of times each second, and in some cases even every time the mouse is moved above the widget.

Most importantly, your overwritten method just connects the clicked signal, which is wrong for two reasons:

  1. your override doesn't do anything else except for connecting the signal, and since QCheckBox needs to handle mouse events in order to properly change its state (and eventually emit the clicked signal), you're preventing all of that - and the signal will never be emitted because it never gets checked/unchecked;
  2. every time any mouse button will be pressed, the signal would be connected; for the above reason, it will have no result at all, but this is still conceptually wrong, as a connected function will always be called as many times as it has been connected to the signal: you connect it twice? the function will be called twice; assuming that the signal would be emitted (which could still happen using keyboard), the related function will be called as many times as the user has attempted to click it.

Another important aspect to remember is that PyQt uses reference caching for functions; after the first time a virtual function is called with the default implementation, overwriting the instance attribute will have no effect.

Supposing you wanted to do the opposite (connect the signal when the state is True), it wouldn't have worked because at that time the default mousePressEvent handler would have been already called, and the overwriting would have had no effect at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文