Форум сайта python.su
Доброго времени суток!
Использую python 3.5 + pyQT5
Создаю окно, внутри него лейблы.
Как мне на лейблы повесить события ховер( и клик заодно)
Например на InfoSover
Если прописываю просто внутри класса
def enterEvent(self, QEvent):
то он срабатывает на все окно, а мне надо конкретно к определенному лейлу/баттону/любому элементу применить
from PyQt5.QtWidgets import * from PyQt5 import QtCore from functions.main_funcs import getScreen import configparser class ProfileForm(QWidget): # Объявляем позицию окна для последущей записи PF_wx = 0 PF_wy = 0 def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool) # окно без рамок и заголовка, не отображается на панели задач self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # прозрачный бек окна self.setFixedSize(330, 220) # InfoS BG info_s = QLabel(self) info_s.setStyleSheet("background-repeat: none; background-image: url(.data/img/infoS.png); background-position:0 0;") info_s.setFixedSize(303, 220) info_s.move(0, 0) # user avatar avatar = QLabel(self) avatar.setStyleSheet("background-repeat: none; background-image: url(.data/img/avatarDemo.png); background-position:center center; border-radius:50px; border: 1px solid transparent;") avatar.setFixedSize(103, 103) avatar.move(67, 50) # gate6 BG gate6 = QLabel(self) gate6.setStyleSheet("background-repeat: none; background-image: url(.data/img/gate6.png); background-position:0 0;") gate6.setFixedSize(180, 90) gate6.move(145, 42) # InfoSover infosover = QLabel(self) infosover.setStyleSheet("cursor:pointer; background: transparent; background-repeat: none; background-image: url(.data/img/over.png); background-position:0 0;") infosover.setFixedSize(112, 112) infosover.move(62, 47) # Получаем данные о расположении окна и зписываем в конфиг положение окна если его нет config = configparser.ConfigParser() config.read('config.ini') profile_xy_x = 0 profile_xy_y = 0 try: profile_xy_x = int(config.get('profileXY','x')) profile_xy_y = int(config.get('profileXY', 'y')) except configparser.NoSectionError: config.add_section('profileXY') config.set('profileXY', 'x', '0') config.set('profileXY', 'y', '0') with open('config.ini', 'w') as configfile: config.write(configfile) finally: self.move(profile_xy_x, profile_xy_y) # показываем окно self.show() # Возможность перемещения окна def mousePressEvent(self, event): self.offset = event.pos() def mouseMoveEvent(self, event): global PF_wx, PF_wy x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() w_x = x - x_w w_y = y - y_w # Вычисляем размеры экрана и не даем окну выходить за его пределы if (w_x < 0): w_x = 0 if (w_y < 0): w_y = 0 screen = getScreen() screen_w = screen[0] screen_h = screen[1] win_w = self.width() win_h = self.height() if (w_x > (screen_w - win_w)): w_x = screen_w - win_w if (w_y > (screen_h - win_h)): w_y = screen_h - win_h PF_wx = w_x PF_wy = w_y # двигаем окно по позиции self.move(w_x, w_y) def mouseReleaseEvent(self, event): global PF_wx, PF_wy # Записываем в конфиг положение окна после перетаскивания config = configparser.ConfigParser() config.read('config.ini') config.set('profileXY', 'x', str(PF_wx)) config.set('profileXY', 'y', str(PF_wy)) with open('config.ini', 'w') as configfile: config.write(configfile) def close(self): self.hide() qApp.quit()
from PyQt5.QtWidgets import * from PyQt5 import QtCore from PyQt5.QtCore import pyqtSignal from functions.main_funcs import getScreen import configparser class HoverButton(QPushButton): mouseHover = pyqtSignal(bool) def __init__(self, parent=None): QPushButton.__init__(self, parent) self.setMouseTracking(True) def enterEvent(self, event): self.mouseHover.emit(True) global infosover infosover.setStyleSheet("cursor:pointer; background: transparent; background-repeat: none; background-image: url(.data/img/over.png); background-position:0 0;") def leaveEvent(self, event): self.mouseHover.emit(False) infosover.setStyleSheet("cursor:pointer; background: transparent;") class ProfileForm(QWidget): # Объявляем позицию окна для последущей записи PF_wx = 0 PF_wy = 0 infosover = 0 def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool) # окно без рамок и заголовка, не отображается на панели задач self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # прозрачный бек окна self.setFixedSize(330, 220) # InfoS BG info_s = QLabel(self) info_s.setStyleSheet("background-repeat: none; background-image: url(.data/img/infoS.png); background-position:0 0;") info_s.setFixedSize(303, 220) info_s.move(0, 0) # user avatar avatar = QLabel(self) avatar.setStyleSheet("background-repeat: none; background-image: url(.data/img/avatarDemo.png); background-position:center center; border-radius:50px; border: 1px solid transparent;") avatar.setFixedSize(103, 103) avatar.move(67, 50) # gate6 BG gate6 = QLabel(self) gate6.setStyleSheet("background-repeat: none; background-image: url(.data/img/gate6.png); background-position:0 0;") gate6.setFixedSize(180, 90) gate6.move(145, 42) # InfoSover global infosover infosover = HoverButton(self) infosover.clicked.connect(self.close) infosover.mouseHover.connect(self.hover) infosover.setStyleSheet("background: transparent;") infosover.setFixedSize(112, 112) infosover.move(63, 45) # Получаем данные о расположении окна и зписываем в конфиг положение окна если его нет config = configparser.ConfigParser() config.read('config.ini') profile_xy_x = 0 profile_xy_y = 0 try: profile_xy_x = int(config.get('profileXY','x')) profile_xy_y = int(config.get('profileXY', 'y')) except configparser.NoSectionError: config.add_section('profileXY') config.set('profileXY', 'x', '0') config.set('profileXY', 'y', '0') with open('config.ini', 'w') as configfile: config.write(configfile) finally: self.move(profile_xy_x, profile_xy_y) # показываем окно self.show() def hover(self): pass # Возможность перемещения окна def mousePressEvent(self, event): self.offset = event.pos() def mouseMoveEvent(self, event): global PF_wx, PF_wy x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() w_x = x - x_w w_y = y - y_w # Вычисляем размеры экрана и не даем окну выходить за его пределы if (w_x < 0): w_x = 0 if (w_y < 0): w_y = 0 screen = getScreen() screen_w = screen[0] screen_h = screen[1] win_w = self.width() win_h = self.height() if (w_x > (screen_w - win_w)): w_x = screen_w - win_w if (w_y > (screen_h - win_h)): w_y = screen_h - win_h PF_wx = w_x PF_wy = w_y # двигаем окно по позиции self.move(w_x, w_y) def mouseReleaseEvent(self, event): global PF_wx, PF_wy # Записываем в конфиг положение окна после перетаскивания config = configparser.ConfigParser() config.read('config.ini') config.set('profileXY', 'x', str(PF_wx)) config.set('profileXY', 'y', str(PF_wy)) with open('config.ini', 'w') as configfile: config.write(configfile) def close(self): self.hide() qApp.quit()
Офлайн
Edith1. Создать свой класс наследник и переопределить нужные ивенты.. Собственно вы частично реализвали это.. только накой вам там глобалс? Тем более внутри класса. Если уж нужно чтото хранить, храните как атрибут класса self.PF_wx и self.PF_wy и обращаетсь к ним соответвенно. Кроме того у любого виджета есть pos () , х() и y() которые содержат координаты виджета относительно родителя. так жк есть mapToGlobal() и mapFromGlobal(), может пригодиться.
Если прописываю просто внутри класса
def enterEvent(self, QEvent):
то он срабатывает на все окно, а мне надо конкретно к определенному лейлу/баттону/любому элементу применить
Edith
2) Как можно сменить курсор у лейбла/баттона?
cursor = QCursor(Qt.WaitCursor) widget.setCursor(cursor)
[code python][/code]
Отредактировано PEHDOM (Июнь 2, 2017 22:57:07)
Офлайн
PEHDOM
2. установить eventFilter для дочерних обьектов anyWidget.installEventFilter(otherWdget), и переопределить eventFilter() у otherWdget, тогда дочерние обьекты будут все ивенты направлять в otherWdget , а вы сможете уже в нем фильтровать, если обьект такойто и ивент такойто то делаем тото….
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from functions.main_funcs import getScreen import configparser class Filter(QObject): def __init__(self): super(QObject, self).__init__() def eventFilter(self, obj, event): print(event.type()) return False class ProfileForm(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool) # окно без рамок и заголовка, не отображается на панели задач self.setAttribute(Qt.WA_TranslucentBackground) # прозрачный бек окна self.setFixedSize(330, 220) self.filter = Filter() # Объявляем позицию окна для последущей записи self.PF_wx = 0 self.PF_wy = 0 # InfoS BG self.info_s = QLabel(self) self.info_s.setStyleSheet("background-repeat: none; background-image: url(.data/img/infoS.png); background-position:0 0;") self.info_s.setFixedSize(303, 220) self.info_s.move(0, 0) # user avatar self.avatar = QLabel(self) self.avatar.setStyleSheet("background-repeat: none; background-image: url(.data/img/avatarDemo.png); background-position:center center; border-radius:50px; border: 1px solid transparent;") self.avatar.setFixedSize(103, 103) self.avatar.move(67, 50) # gate6 BG self.gate6 = QLabel(self) self.gate6.setStyleSheet("background-repeat: none; background-image: url(.data/img/gate6.png); background-position:0 0;") self.gate6.setFixedSize(180, 90) self.gate6.move(145, 42) # InfoSover self.infosover = QLabel(self) self.infosover.setStyleSheet("cursor:pointer; background: transparent; background-repeat: none; background-image: url(.data/img/over.png); background-position:0 0;") self.infosover.setFixedSize(112, 112) self.infosover.move(62, 47) self.infosover.setCursor(Qt.PointingHandCursor) self.infosover.installEventFilter(self.filter) # Получаем данные о расположении окна и зписываем в конфиг положение окна если его нет config = configparser.ConfigParser() config.read('config.ini') profile_xy_x = 0 profile_xy_y = 0 try: profile_xy_x = int(config.get('profileXY','x')) profile_xy_y = int(config.get('profileXY', 'y')) except configparser.NoSectionError: config.add_section('profileXY') config.set('profileXY', 'x', '0') config.set('profileXY', 'y', '0') with open('config.ini', 'w') as configfile: config.write(configfile) finally: self.move(profile_xy_x, profile_xy_y) # показываем окно self.show() # Возможность перемещения окна def mousePressEvent(self, event): self.offset = event.pos() def mouseMoveEvent(self, event): x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() w_x = x - x_w w_y = y - y_w # Вычисляем размеры экрана и не даем окну выходить за его пределы if (w_x < 0): w_x = 0 if (w_y < 0): w_y = 0 screen = getScreen() screen_w = screen[0] screen_h = screen[1] win_w = self.width() win_h = self.height() if (w_x > (screen_w - win_w)): w_x = screen_w - win_w if (w_y > (screen_h - win_h)): w_y = screen_h - win_h self.PF_wx = w_x self.PF_wy = w_y # двигаем окно по позиции self.move(w_x, w_y) def mouseReleaseEvent(self, event): # Записываем в конфиг положение окна после перетаскивания config = configparser.ConfigParser() config.read('config.ini') config.set('profileXY', 'x', str(self.PF_wx)) config.set('profileXY', 'y', str(self.PF_wy)) with open('config.ini', 'w') as configfile: config.write(configfile) def close(self): self.hide() qApp.quit()
def eventFilter(self, obj, event): print(event.type()) return False
def eventFilter(self, obj, event): if event.type() == 11: callback1() elif event.type() == 10: callback2()
self.infosover.installEventFilter(self.filter)
infosover.hover(function(){ // dosomething on mouseIn }, function(){ // dosomething on mouseOut });
Отредактировано Edith (Июнь 3, 2017 10:33:15)
Офлайн
self.infosover.installEventFilter(self.filter(myFunc1, myFunc2, myFunc3)) оно не так работает.
в installEventFilter вы просто указывате таргет на обьект котороый будет фильтровать ваши иветны.
Не обязательно создавать отдельный класс для этого, это может быть любой обьект наследник QObject.
В иветфильтре у вас есть два параметра, ивент и обьек котороый послал ивент. вот собственно там оно все и фильтруеться по приципу:
def eventFilter(self, obj, event): if event.type() == 11: # Если мышь покинула область фиджета if obj.objectName() == 'gate6': # И если этот виджет с именем gate6 callback1() # выполнить callback1() elif event.type() == 10: # Если мышь над виджетом if obj.objectName() == 'infosover': # И если этот виджет c именем infosover callback2() # выполнить callback2() elif type(obj) == QPushButton: # Если это любая кнопка obj.setIcon(icon) # Изменить иконку кнопки на icon
self.infosover = QLabel(self) self.infosover.setObjectName('infosover')
[code python][/code]
Отредактировано PEHDOM (Июнь 3, 2017 11:29:34)
Офлайн
PEHDOMСпасибо огромное! Теперь все понятно как работает.
self.infosover.installEventFilter(self.filter(myFunc1, myFunc2, myFunc3)) оно не так работает.в installEventFilter вы просто указывате таргет на обьект котороый будет фильтровать ваши иветны. Не обязательно создавать отдельный класс для этого, это может быть любой обьект наследник QObject. D иветфильтре у вас есть два параметра, ивент и обьек котороый послал ивент. вот собственно там оно все и фильтруеться по приципу:
Офлайн