My aim to deactivate the checkbox, if my textbox is empty. So I try with the following code if I clear my entire textbox by the way of "select all characters" using Ctrl+A and delete it. But in my code, the first part only worked, that is Ctrl+A, If I press the Delete key that is the second part of my code is not worked, How to rectify?
if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_A :
print("I am inside of Cntrl+A")
if event.key() == Qt.Key_Delete:
print("i Am inside of key_delete")
self.checkbox.setChecked(False)
self.checkstatus = 0
return True
Minimal reproducible Code
import os
from PyQt5.QtWidgets import QCheckBox,QLineEdit,QWidget,QApplication,QVBoxLayout
from PyQt5.QtCore import QEvent,Qt
class CtrlaDel(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Key Press Event")
self.le = QLineEdit()
self.cb = QCheckBox()
self.cb.setChecked(True)
self.vbox = QVBoxLayout(self)
self.vbox.addWidget(self.le)
self.vbox.addWidget(self.cb)
self.le.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.KeyPress and source is self.le:
print("ddddsdsdsdsdsdsds")
if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete and source is self.le:
print("ddd")
if len(self.le.text()) <= 1:
self.cb.setChecked(False)
if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_A:
print("I am inside of Ctrl+A")
if event.key() == Qt.Key_Delete:
print("I am Inside of Delete")
self.cb.setChecked(False)
self.checkstatus = 0
return True
return super(CtrlaDel, self).eventFilter(source, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
mainwindow = CtrlaDel()
mainwindow.show()
sys.exit(app.exec_())
I do not see the need to use an eventFilter, the solution is that every time the text is changed verify that if it is an empty text then set the checkbox to false and for this the textChanged signal can be used
from PyQt5.QtWidgets import QCheckBox, QLineEdit, QWidget, QApplication, QVBoxLayout
class CtrlaDel(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Key Press Event")
self.le = QLineEdit()
self.cb = QCheckBox()
self.cb.setChecked(True)
vbox = QVBoxLayout(self)
vbox.addWidget(self.le)
vbox.addWidget(self.cb)
self.le.textChanged.connect(self.handle_text_changed)
self.handle_text_changed()
def handle_text_changed(self):
if not self.le.text():
self.cb.setChecked(False)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
mainwindow = CtrlaDel()
mainwindow.show()
sys.exit(app.exec_())
Related
I want to check whether the pressed key items are found in my list or not. If it is found, then print it in a QLabel Text or print. Here is my code:
import sys
from PyQt5.QtWidgets import QWidget,QApplication
class MyMenu(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Sample")
self.list = ['W','Alt+K','Alt+R','Ctrl+Alt+A', 'Ctrl+P','Ctrl+Alt+Shift+Q']
def keyPressEvent(self, event):
print(event.key())
if event.key() in self.list:
print("Item Found in list")
def main():
app = QApplication(sys.argv)
ex = MyMenu()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
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_())
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())
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_())
This question already has an answer here:
How to capture the Key_tab event
(1 answer)
Closed 4 years ago.
With the code below, every key prints something in the terminal except for the tab key. The tab key still works though, I'm able to tab between line edits. I just can capture the event.
# i'm using PyQt5==5.11.3 and 32 bit python 3.7.1
from PyQt5.QtWidgets import QLineEdit, QLabel, QWidget, QVBoxLayout, QApplication
import sys
class Main(QWidget):
def __init__(self):
super().__init__()
label = QLabel('event')
input1 = Input()
input2 = Input()
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(input1)
layout.addWidget(input2)
self.setLayout(layout)
self.show()
class Input(QLineEdit):
def __init__(self):
super().__init__()
def keyPressEvent(self, event):
# why doesn't tab print anything
print(event.key())
if __name__ == "__main__":
app = QApplication(sys.argv)
wid = Main()
sys.exit(app.exec_())
You can intercept tke Tab pressed event using the event method from QLineEdit. You process your event, then you pass it to the QLineEdit.event() method.
Something like that:
import sys
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtWidgets import QLineEdit, QLabel, QWidget, QVBoxLayout, QApplication
class Main(QWidget):
def __init__(self):
super().__init__()
label = QLabel('event')
input1 = Input()
input2 = Input()
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(input1)
layout.addWidget(input2)
self.setLayout(layout)
self.show()
class Input(QLineEdit):
def __init__(self):
super().__init__()
def keyPressEvent(self, event):
print(event.key())
def event(self,event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.tabFollow()
return QLineEdit.event(self,event)
def tabFollow(self):
print("tab-key pressed!")
if __name__ == "__main__":
app = QApplication(sys.argv)
wid = Main()
sys.exit(app.exec_())