Arhn - архитектура программирования

PyQt QPushButton оставить событие при нажатии QPushButton

Я хочу кнопку. Я пытаюсь создать конечный автомат, поэтому он будет использоваться в классе QState.

Если курсор мыши наведен, кнопка меняет свой цвет.

Если левая кнопка мыши отпущена на кнопке, она должна работать.

Если левая кнопка мыши нажата на кнопке, но отпущена снаружи кнопки (перетащите курсор наружу при нажатии), кнопка не должна работать. (чтобы пользователи могли отменить пропущенный щелчок, перетащив его.)

Вот мой код, но он не работает. Когда я перетаскиваю курсор наружу и отпускаю кнопку мыши, кнопка работает.

Я проверил несколько вещей, и теперь я понимаю кое-что.

  1. Пока кнопка мыши нажата, QPushButton.enterEvent и QPushButton.leaveEvent не работают.

  2. Когда курсор покидает QPushButton при нажатой кнопке, создается впечатление, что QPushButton.released излучает сигнал.

Как сделать эту кнопку?

class MyButton(QtWidgets.QPushButton):
    selected = QtCore.pyqtSignal(bool)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMouseTracking(True)
        self.is_hover = False

    def enterEvent(self, event):
        self.setStyleSheet\
            ("color: black; border-style: solid;\
                border-width: 2px; border-color: white;\
                    background-color: rgba(250,0,0,1);")            
        self.is_hover = True
        print('is_hover = True')

    def leaveEvent(self, event):
        self.setStyleSheet\
            ("color: white; border-style: solid;\
                border-width: 2px; border-color: white;\
                    background-color: rgba(250,50,150,0.5);")
        self.is_hover = False
        print('is_hover = False')

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            if self.is_hover:
                self.selected.emit(True)
            else:
                return
        else:            
            return
22.09.2020

  • Почему вы не можете использовать сигнал clicked() и избежать всего * событие переопределяет? Если вы хотите установить таблицы стилей для состояний наведения, используйте селектор :hover в глобальном css кнопки. 22.09.2020
  • @musicamante спасибо, clicked() работает. У меня было неправильное понимание clicked(). Я думал, что clicked() сразу же излучает сигнал при нажатии кнопки. Раньше я не изучал PyQt и python, поэтому ищу функции, которые помогают достичь моей цели. 22.09.2020
  • @musicamante спасибо за ':hover', я пытался, но это не сработало. Я не знаю почему. «enterEvent» и «leaveEvent» работают хорошо, поэтому я буду использовать их. 22.09.2020

Ответы:


1

Подклассы и переопределение методов должны выполняться только тогда, когда класс не предоставляет то, что вам нужно, и это не ваш случай.

Сигнал clicked делает именно то, что вы описываете: сигнал испускается, когда пользователь нажимает левую кнопку мыши и отпускает ее, пока курсор находится внутри кнопки (и когда click() или animateClick() вызываются программно, но суть не в этом).

Если вы хотите также изменить внешний вид при наведении кнопки, вы должны использовать :hover псевдосостояние. Обратите внимание, что для правильного использования селекторов таблиц стилей вы не можете использовать простой синтаксис таблицы стилей, как вы это делали, но класс должен быть указан точно так же, как это происходит в стандартном CSS.

    self.button = QPushButton()
    self.button.setStyleSheet('''
        QPushButton {
            color: white;
            border: 2px solid white;
            background-color: rgba(250, 50, 150, 128);
        }

        QPushButton:hover {
            background-color: rgba(250, 0, 0, 255);
        }
    ''')
    self.button.clicked.connect(self.someFunction)

Некоторые соображения:

  • синтаксис rgb() и rgba() принимает целые числа от 0 до 255 или проценты, поэтому используемые вами альфа-значения (0,5 и 1) не будут работать должным образом, поскольку они будут считаться практически прозрачными (0 и 1 соответственно), поскольку непроцентные значения всегда находятся в диапазоне 0-255;
  • псевдосостояния могут быть связаны, поэтому вы также можете установить спецификацию таблицы стилей для оба :hover и :pressed
  • поскольку внешний вид кнопки всегда должен отражать ее состояние (самое главное, независимо от того, нажата она или нет), вы должны как минимум добавить селектор класса для состояния :pressed; также рекомендуется использовать стиль границы inset и outset (вместо solid); обратите внимание, что он хорошо работает только с более темными цветами, поэтому, если вы хотите беловатую рамку, используйте следующее:
    self.button.setStyleSheet('''
        QPushButton {
            color: white;
            border: 2px outset lightGray;
            background-color: rgba(250, 50, 150, 128);
        }
        QPushButton:pressed {
            border-style: inset;
        }
        QPushButton:hover {
            background-color: rgba(250, 0, 0, 255);
        }
        QPushButton:hover:pressed {
            /* since no background was set for pressed, hover state takes
            precedence, so we need to specify the "default" color again here */
            background-color: rgba(250, 50, 150, 128);
        }
    ''')
  • setMouseTracking() полезен только тогда, когда вам нужно отслеживать движения мыши, когда кнопка мыши не нажата и перехватывается mouseMoveEvent() (который вы не реализовано), который обычно всегда вызывается для движений мыши после нажатия кнопки мыши;
  • события ввода и вывода принимаются только тогда, когда кнопка мыши не нажата: как только виджет (любой виджет) получает и принимает mousePressEvent(), этот виджет становится захватчиком мыши (см. mouseGrabber() и grabMouse()), и все движения мыши будут приниматься только этим виджетом: никаких событий входа/выхода/наведения не будет. любым другим виджетом, пока кнопка мыши не будет отпущена;
  • хотя я могу понять ваше утверждение (я ищу функции, которые помогают достичь моей цели), вы должны учитывать, что Qt — это огромный фреймворк, который разрабатывался в течение 25 лет: все его классы уже предоставляют большинство часто используемых интерфейсов и функций, поэтому вместо того, чтобы искать то, что вам нужно для каждого отдельного случая, лучше обратиться к документации по классу, который вы используете, и изучить его; учтите, что вы также должны всегда делать то же самое для всех унаследованных классов используемого вами класса: в вашем случае не просто ищите QPushButton, а читайте документы о QAbstractButton и QWidget.
22.09.2020
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..