I am writing a slot method for the signal of scrolling down a scrollbar in QPlainTextEdit.
I only found this signalQPlainTextEdit.verticalScrollBar().valueChanged.
I tested this signal and it returned the position number when scrolls to a new position.
My purpose is that when the scrollbar move down and trigger the slot method. But in that signal when move up it also triggeres the slot.
I read the document but I couldn't find other signals.
A possible solution is to save the previous position and compare with the new position using sliderPosition property:
from PyQt5.QtWidgets import QApplication, QPlainTextEdit
class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.last_position = self.verticalScrollBar().sliderPosition()
self.verticalScrollBar().sliderMoved.connect(self.handle_value_changed)
def handle_value_changed(self, position):
if position > self.last_position:
print("down")
else:
print("up")
self.last_position = position
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = PlainTextEdit()
w.show()
sys.exit(app.exec_())
Another possible option is to implement a use of the mousePressEvent and mouseMoveEvent events of the QScrollBar:
from PyQt5.QtCore import QPoint, Qt
from PyQt5.QtWidgets import QApplication, QPlainTextEdit, QScrollBar
class ScrollBar(QScrollBar):
last_pos = QPoint()
def mousePressEvent(self, event):
self.last_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
if event.pos().y() > self.last_pos.y():
print("down")
else:
print("up")
self.last_pos = event.pos()
class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.vertical_scrollbar = ScrollBar(Qt.Vertical)
self.setVerticalScrollBar(self.vertical_scrollbar)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = PlainTextEdit()
w.show()
sys.exit(app.exec_())
OR:
from PyQt5.QtCore import QEvent, QPoint
from PyQt5.QtWidgets import QApplication, QPlainTextEdit
class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.last_pos = QPoint()
self.verticalScrollBar().installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.verticalScrollBar():
if event.type() == QEvent.MouseButtonPress:
self.last_pos = event.pos()
elif event.type() == QEvent.MouseMove:
if event.pos().y() > self.last_pos.y():
print("down")
else:
print("up")
self.last_pos = event.pos()
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = PlainTextEdit()
w.show()
sys.exit(app.exec_())
Related
My goal is to detect when a user hovers or stops hovering over a frame, but whenever I try to detect that with an eventFilter, there are just no events that get run that show that. The event IDs for hoverEnter, hoverLeave, and hoverMouseMove are 127, 128, and 129, but if you run the code, you'll see that they just don't come up. Here is the code that fails:
import sys
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout()
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.innerLayout = QHBoxLayout(self.frame)
self.label = QLabel(self.frame)
self.label.setText("Example Frame")
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.setLayout(self.outerLayout)
def eventFilter(self, obj, event):
if event.type() == 127:
print("hovered")
elif event.type() == 128:
print("no longer hovered")
elif event.type() == 129:
print("hover move event")
print(event.type())
return True
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.installEventFilter(window)
window.show()
sys.exit(app.exec())
My end goal here is to be able to detect when a QFrame is clicked. I was thinking I would try to do that by checking for mouse clicks, and if the mouse is hovering over the frame, trigger the function.
First of all it should be noted that clicked is not an event but a signal. The button clicked signal is emitted when the button receives the MouseButtonRelease event.
In this answer I will show at least the following methods to implement the clicked signal in the QFrame.
Override mouseReleaseEvent
import sys
from PyQt6.QtCore import pyqtSignal, pyqtSlot
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class Frame(QFrame):
clicked = pyqtSignal()
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
self.clicked.emit()
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = Frame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.clicked.connect(self.handle_clicked)
#pyqtSlot()
def handle_clicked(self):
print("frame clicked")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
Use a eventFilter:
import sys
from PyQt6.QtCore import QEvent
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.installEventFilter(self)
# for move mouse
# self.frame.setMouseTracking(True)
def eventFilter(self, obj, event):
if obj is self.frame:
if event.type() == QEvent.Type.MouseButtonPress:
print("press")
# for move mouse
# elif event.type() == QEvent.Type.MouseMove:
# print("move")
elif event.type() == QEvent.Type.MouseButtonRelease:
print("released")
return super().eventFilter(obj, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
Plus
A big part of the error of the O attempt is that by doing window.installEventFilter(window) it is only listening for events from the window itself and not from the QFrame. The solution is to send the QFrame events to the class window.frame.installEventFilter(window).
On the other hand, do not use numerical codes but the enumerations since they are more readable.
On the other hand, for the mouse event, the Qt::WA_Hover attribute must be enabled(Read the docs for more information)
import sys
from PyQt6.QtCore import QEvent, Qt
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.setAttribute(Qt.WidgetAttribute.WA_Hover)
self.frame.installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.frame:
if event.type() == QEvent.Type.HoverEnter:
print("enter")
elif event.type() == QEvent.Type.HoverMove:
print("move")
elif event.type() == QEvent.Type.HoverLeave:
print("leave")
return super().eventFilter(obj, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
I have this snippet that simulate the closing of a window calling a custom QDialog:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QPushButton, QVBoxLayout, QHBoxLayout, QLabel
from PyQt5.QtCore import Qt
class ExitDialog(QDialog):
"""TODO"""
def __init__(self):
super().__init__()
self.buttonSi = QPushButton("Yes")
self.buttonSi.clicked.connect(self.si_clicked)
self.buttonNo = QPushButton("No")
self.buttonNo.clicked.connect(self.no_clicked)
self.buttonNonUscire = QPushButton("Do not exit")
self.buttonNonUscire.clicked.connect(self.non_uscire_clicked)
self.text = QLabel("Do you want to save changes before exit?")
self.text.setAlignment(Qt.AlignCenter)
hbox1 = QHBoxLayout()
hbox1.addWidget(self.text)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.buttonSi)
hbox2.addWidget(self.buttonNo)
hbox2.addWidget(self.buttonNonUscire)
self.layout = QVBoxLayout()
self.layout.addLayout(hbox1)
self.layout.addLayout(hbox2)
self.setLayout(self.layout)
self.value_choosed = None
def keyPressEvent(self, event):
if event.key == Qt.Key_Escape:
event.ignore()
def get_choosed_value(self):
return self.value_choosed
def si_clicked(self):
self.value_choosed = 0
self.close()
def no_clicked(self):
self.value_choosed = 1
self.close()
def non_uscire_clicked(self):
self.value_choosed = 2
self.close()
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(400,300,400,200)
vbox = QVBoxLayout()
btn = QPushButton("Exit")
btn.clicked.connect(self.btn_clicked)
vbox.addWidget(btn)
self.setLayout(vbox)
def btn_clicked(self):
self.close()
def closeEvent(self, event):
dialog = ExitDialog()
dialog.exec_()
choice = dialog.get_choosed_value()
if choice == 0:
event.accept()
elif choice == 1:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
a = QApplication(["TODO"])
w = Window()
w.show()
sys.exit(a.exec_())
I notice that when I use the 'x' button of the main window or the key combination ALT+F4 for activate the ExitDialog, it's position is on different screen coordinates with respect of using the btn Exit.I'm on Ubuntu 18.04.5, window manager: GNOME Shell.
How is this possible?
Well I actually solved by adding a QTimer at the end of __init__.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QDesktopWidget
from PyQt5.QtCore import Qt, QTimer
class ExitDialog(QDialog):
"""TODO"""
def __init__(self):
super().__init__()
self.buttonSi = QPushButton("Yes")
self.buttonSi.clicked.connect(self.si_clicked)
self.buttonNo = QPushButton("No")
self.buttonNo.clicked.connect(self.no_clicked)
self.buttonNonUscire = QPushButton("Do not exit")
self.buttonNonUscire.clicked.connect(self.non_uscire_clicked)
self.text = QLabel("Do you want to save changes before exit?")
self.text.setAlignment(Qt.AlignCenter)
hbox1 = QHBoxLayout()
hbox1.addWidget(self.text)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.buttonSi)
hbox2.addWidget(self.buttonNo)
hbox2.addWidget(self.buttonNonUscire)
self.layout = QVBoxLayout()
self.layout.addLayout(hbox1)
self.layout.addLayout(hbox2)
self.setLayout(self.layout)
self.value_choosed = None
self.timer = QTimer()
self.timer.timeout.connect(self.setPos)
self.timer.start(1)
def setPos(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) // 2, (screen.height() - size.height()) // 2)
self.timer.stop()
def keyPressEvent(self, event):
if event.key == Qt.Key_Escape:
event.ignore()
def get_choosed_value(self):
return self.value_choosed
def si_clicked(self):
self.value_choosed = 0
self.close()
def no_clicked(self):
self.value_choosed = 1
self.close()
def non_uscire_clicked(self):
self.value_choosed = 2
self.close()
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(400,300,400,200)
vbox = QVBoxLayout()
btn = QPushButton("Exit")
btn.clicked.connect(self.btn_clicked)
vbox.addWidget(btn)
self.setLayout(vbox)
def btn_clicked(self):
self.close()
def closeEvent(self, event):
dialog = ExitDialog()
dialog.exec_()
choice = dialog.get_choosed_value()
if choice == 0:
event.accept()
elif choice == 1:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
a = QApplication(["TODO"])
w = Window()
w.show()
sys.exit(a.exec_())
Don't know if there is way to directly interact with the system's window manager.
I'm making a custom QTreeView with QFileSystem model, and I have a MouseMoveEvent set up to print the path of the item that is hovered over.
I'm way down the rabbit hole and doing all kinds of weird things to make this work.
Here is the latest minimal reproducible code:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.resize(500, 300)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.myList = CustomTreeWidget()
self.myList.model.setRootPath("/Volumes/Home/User/Desktop/testsrc")
self.myList.setObjectName("/Volumes/Home/User/Desktop/testsrc")
self.layout.addWidget(self.myList)
class CustomTreeWidget(QTreeView):
def __init__(self):
super().__init__()
self.model = QFileSystemModel()
self.model.setFilter(QDir.NoDotAndDotDot | QDir.Files)
self.setModel(self.model)
self.setAlternatingRowColors(True)
self.setDragDropMode(QAbstractItemView.DragDrop)
self.setIndentation(0)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.setMouseTracking(True)
self.model.directoryLoaded.connect(self._runwhenloaded)
def _runwhenloaded(self):
self.setRootIndex(self.model.index(self.objectName()))
self.model.setRootPath(self.objectName())
def mouseMoveEvent(self, event):
prev = ""
if self.selectedIndexes():
prev = self.selectedIndexes()[0]
x = event.x()
y = event.y()
self.setSelection(QRect(x, y, 1, 1), QItemSelectionModel.ClearAndSelect)
self.setCurrentIndex(self.selectedIndexes()[0])
print(self.model.filePath(self.currentIndex()))
if prev:
self.setCurrentIndex(prev)
# pos = QCursor.pos()
# indexat = self.indexAt(pos).row() # why -1?
# print(indexat) # why -1?
# print(self.indexAt(pos).row())
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Obviously this example is not proper at all, as it destroys multiple selections and scrolls to the previously selected item whenever the mouse moves, and just a hack in general.
I've gone through many iterations and read everything I could put my hands on but I can't figure it out.
The closest answer seems to be HERE, but it's in C and I don't understand it.
So the question is: How to print the file path when the mouse hovers over an item in this QTreeView?
A possible solution is to create an event filter that tracks the hover events and, according to that information, emits a signal that has the QModelIndex:
import sys
from PyQt5.QtCore import (
pyqtSignal,
pyqtSlot,
Qt,
QDir,
QEvent,
QModelIndex,
QObject,
QPersistentModelIndex,
QStandardPaths,
)
from PyQt5.QtWidgets import (
QAbstractItemView,
QApplication,
QFileSystemModel,
QMainWindow,
QTreeView,
)
from PyQt5 import sip
class HoverViewHelper(QObject):
hovered = pyqtSignal(QModelIndex)
def __init__(self, view):
super().__init__(view)
self._current_index = QPersistentModelIndex()
if not isinstance(view, QAbstractItemView):
raise TypeError(f"The {view} must be of type QAbstractItemView")
self._view = view
self.view.viewport().setAttribute(Qt.WA_Hover)
self.view.viewport().installEventFilter(self)
#property
def view(self):
return self._view
def eventFilter(self, obj, event):
if sip.isdeleted(self.view):
return True
if self.view.viewport() is obj:
if event.type() in (QEvent.HoverMove, QEvent.HoverEnter):
p = event.pos()
index = self.view.indexAt(p)
self._update_index(index)
elif event.type() == QEvent.HoverLeave:
if self._current_index.isValid():
self._update_index(QModelIndex())
return super().eventFilter(obj, event)
def _update_index(self, index):
pindex = QPersistentModelIndex(index)
if pindex != self._current_index:
self._current_index = pindex
self.hovered.emit(QModelIndex(self._current_index))
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.model = QFileSystemModel()
self.model.setRootPath(QDir.rootPath())
self.view = QTreeView()
self.view.setModel(self.model)
path = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation)
self.view.setRootIndex(self.model.index(path))
self.setCentralWidget(self.view)
helper = HoverViewHelper(self.view)
helper.hovered.connect(self.handle_hovered)
#pyqtSlot(QModelIndex)
def handle_hovered(self, index):
if not index.isValid():
return
path = self.model.filePath(index)
print(f"path: {path}")
def main():
app = QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
app.exec_()
if __name__ == "__main__":
main()
My problem start when i try some options to pair this two scripts but it only ends with TypeError: init() missing 1 required positional argument: 'parent'
Even my friend try to help but it end with similar errors becouse he have skills in C++
import sys
from PyQt5.QtWidgets import QTabWidget, QWidget, QToolButton, QTabBar, QApplication
class Project_Tabs(QTabWidget):
def __init__(self):
QTabWidget.__init__(self)
self.tabCloseRequested.connect(lambda index: tabs.removeTab(index))
self.setTabsClosable(True)
self._build_tabs()
def _build_tabs(self):
self.insertTab(0, QWidget(), "Project 0" )
# create the "new tab" tab with button
self.insertTab(1, QWidget(),'')
nb = self.new_btn = QToolButton()
nb.setText('+') # you could set an icon instead of text
nb.setAutoRaise(True)
nb.clicked.connect(self.new_tab)
self.tabBar().setTabButton(1, QTabBar.RightSide, nb)
def new_tab(self):
index = self.count() - 1
self.insertTab(index, QWidget(), "Project %d" % index)
self.setCurrentIndex(index)
if __name__ == '__main__':
app = QApplication(sys.argv)
tabs = Project_Tabs()
tabs.show()
app.exec_()
and
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtWidgets import QTabBar, QTabWidget, QApplication, QLineEdit, QWidget
class EditableTabBar(QTabBar):
def __init__(self, parent):
QTabBar.__init__(self, parent)
self._editor = QLineEdit(self)
self._editor.setWindowFlags(Qt.Popup)
self._editor.setFocusProxy(self)
self._editor.editingFinished.connect(self.handleEditingFinished)
self._editor.installEventFilter(self)
def eventFilter(self, widget, event):
if ((event.type() == QEvent.MouseButtonPress and not self._editor.geometry().contains(event.globalPos())) or (event.type() == QEvent.KeyPress and event.key() == Qt.Key_Escape)):
self._editor.hide()
return True
return QTabBar.eventFilter(self, widget, event)
def mouseDoubleClickEvent(self, event):
index = self.tabAt(event.pos())
if index >= 0:
self.editTab(index)
def editTab(self, index):
rect = self.tabRect(index)
self._editor.setFixedSize(rect.size())
self._editor.move(self.parent().mapToGlobal(rect.topLeft()))
self._editor.setText(self.tabText(index))
if not self._editor.isVisible():
self._editor.show()
def handleEditingFinished(self):
index = self.currentIndex()
if index >= 0:
self._editor.hide()
self.setTabText(index, self._editor.text())
class Window(QTabWidget):
def __init__(self):
QTabWidget.__init__(self)
self.setTabBar(EditableTabBar(self))
self.addTab(QWidget(self), 'Tab One')
self.addTab(QWidget(self), 'Tab Two')
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
All i try end with error:
TypeError: init() missing 1 required positional argument: 'parent'
As not to indicate the complete error message or the code that produces it, it is impossible to objectively indicate the cause of the error but I presume that you think that joining functionality is only joining code but unfortunately it is not true.
In the following code I show the union of both functionalities:
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtWidgets import (
QTabBar,
QTabWidget,
QApplication,
QLineEdit,
QWidget,
QToolButton,
)
class EditableTabBar(QTabBar):
def __init__(self, parent):
QTabBar.__init__(self, parent)
self._editor = QLineEdit(self)
self._editor.setWindowFlags(Qt.Popup)
self._editor.setFocusProxy(self)
self._editor.editingFinished.connect(self.handleEditingFinished)
self._editor.installEventFilter(self)
def eventFilter(self, widget, event):
if (
event.type() == QEvent.MouseButtonPress
and not self._editor.geometry().contains(event.globalPos())
) or (event.type() == QEvent.KeyPress and event.key() == Qt.Key_Escape):
self._editor.hide()
return True
return QTabBar.eventFilter(self, widget, event)
def mouseDoubleClickEvent(self, event):
index = self.tabAt(event.pos())
if index >= 0:
self.editTab(index)
def editTab(self, index):
rect = self.tabRect(index)
self._editor.setFixedSize(rect.size())
self._editor.move(self.parent().mapToGlobal(rect.topLeft()))
self._editor.setText(self.tabText(index))
if not self._editor.isVisible():
self._editor.show()
def handleEditingFinished(self):
index = self.currentIndex()
if index >= 0:
self._editor.hide()
self.setTabText(index, self._editor.text())
class Window(QTabWidget):
def __init__(self):
QTabWidget.__init__(self)
self.setTabBar(EditableTabBar(self))
self.setTabsClosable(True)
self.tabCloseRequested.connect(self.removeTab)
self.addTab(QWidget(self), "Tab One")
self.addTab(QWidget(self), "Tab Two")
count = self.count()
nb = QToolButton(text="+", autoRaise=True)
nb.clicked.connect(self.new_tab)
self.insertTab(count, QWidget(), "")
self.tabBar().setTabButton(count, QTabBar.RightSide, nb)
def new_tab(self):
index = self.count() - 1
self.insertTab(index, QWidget(), "Tab %d" % index)
self.setCurrentIndex(index)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
I want that if I move my mouse over the label with text stop on it then it should change the value of a variable Stop to True so that I may pause/stop my program.
I have looked the code at
Mouseover event filter for a PyQT Label
and tried to run it, but nothing is being shown up.
The code is:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
import sys
class mouseoverEvent(QtCore.QObject):
def __init__(self, parent):
super(mouseoverEvent, self).__init__(parent)
self.initUI()
def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.MouseMove:
print( "mousemove!")
return True
else:
return False
def initUI(self):
self.filter = mouseoverEvent(self)
self.label.installEventFilter(self.filter)
self.lbl=QLabel(self)
self.lbl.setText(self,"hellojjj")
self.setGeometry(1000, 30, 300, 100)
self.setWindowTitle('QLineEdit')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = mouseoverEvent()
sys.exit(app.exec_())
If you've already imported
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
there is no need to
from PyQt5 import *
Once you've imported QtCore, you no longer need to call its functions/classes with 'QtCore.QEvent', Just using QEvent is fine
I believe the question you linked to used PyQt4. In PyQt5, the initialization procedure for the class changed
The code below should work.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class mouseoverEvent(QWidget):
def __init__(self):
super().__init__()
self.stop = False # your 'stop' variable
self.initUI()
def initUI(self):
self.lbl=QLabel(self)
self.lbl.setText("Hover over me to stop the program")
self.lbl.installEventFilter(self)
self.setGeometry(1000, 30, 300, 100)
self.setWindowTitle('QLineEdit')
self.show()
def eventFilter(self, object, event):
if event.type() == QEvent.Enter:
print("Mouse is over the label")
self.stop = True
print('program stop is', self.stop)
return True
elif event.type() == QEvent.Leave:
print("Mouse is not over the label")
self.stop = False
print('program stop is', self.stop)
return False
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = mouseoverEvent()
sys.exit(app.exec_())
if you only want the stop to activate over a label with certain text change your eventFilter function to:
def eventFilter(self, object, event):
if hasattr(object, 'text'): #check to see if the object has text, otherwise if you hover over something without text, PyQt will return an error
if object.text() == "Hover over me to stop the program":
if event.type() == QEvent.Enter:
print("Mouse is over the label")
self.stop = True
print('program stop is', self.stop)
return True
elif event.type() == QEvent.Leave:
print("Mouse is not over the label")
self.stop = False
print('program stop is', self.stop)
return False
Remember that Python is very flexible, so there is no need to subclass QLabel.
For example:
def enter(event):
print("Enter")
def leave(label):
print("Leave")
label = QLabel("Hello")
label.leaveEvent = leave
label.enterEvent = enter
Or you can use lambdas:
label = QLabel("Hello")
label.leaveEvent = lambda e: print("Leave")
label.enterEvent = lambda e: print("Enter")
Please find the reference:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Label(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
def enterEvent(self, event):
print("hovered")
def leaveEvent(self, event):
print("left")