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())
Related
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_())
Here's my setup:
I have a eventFilter on my QTableWidget to handle both mousePress and mouseRelease events.
I also have a custom class for the QPushButton to handle mousePress and mouseRelease events.
However when I trigger the mousePress event by clicking and holding on the button, the QTableWidget doesn't see the event.
Just in case here's the code for both the custom QPushButton class and QTableWidget eventFilter.
class Button(QPushButton):
key = None
def __init__(self, title, parent):
super().__init__(title, parent)
def mousePressEvent(self, e):
super().mousePressEvent(e)
if e.button() == Qt.LeftButton:
print('press')
class TableWidget(QTableWidget):
def __init__(self, rows, columns, parent=None):
QTableWidget.__init__(self, rows, columns, parent)
self._last_index = QPersistentModelIndex()
self.viewport().installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.MouseButtonRelease:
print("mouse release")
return QTableWidget.eventFilter(self, source, event)
What I'm hoping to see is when I press the custom button and then release mouse, that it will print "mouse release" in the console.
This doesn't happen.
But it does print it successfully when I click anywhere in the table except the button.
Let me know in the comments if you want me to add any extra information.
Explanation:
As I already pointed out in this post: The handling of mouse events between the widgets goes from children to parents, that is, if the child does not accept the event (it does not use it) then it will pass the event to the parent.. That can be verified using the following example:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QPushButton,
QTableWidget,
QTableWidgetItem,
QVBoxLayout,
QWidget,
)
class TableWidget(QTableWidget):
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
print("released")
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tablewidget = TableWidget(4, 4)
container = QWidget()
lay = QVBoxLayout(container)
lay.addWidget(QLabel("QLabel", alignment=Qt.AlignCenter))
lay.addWidget(QPushButton("QPushButton"))
container.setFixedSize(container.sizeHint())
item = QTableWidgetItem()
self.tablewidget.setItem(0, 0, item)
item.setSizeHint(container.sizeHint())
self.tablewidget.setCellWidget(0, 0, container)
self.tablewidget.resizeRowsToContents()
self.tablewidget.resizeColumnsToContents()
lay = QVBoxLayout(self)
lay.addWidget(self.tablewidget)
def main():
import sys
app = QApplication(sys.argv)
widget = Widget()
widget.resize(640, 480)
widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
If the QPushButton is pressed then the mouseReleaseEvent method of the QTableWidget will not be invoked because the QPushButton consumes it, unlike when the QLabel is pressed since it does not consume it and the QTableWidget does.
Solution:
As I pointed out in the other post, a possible solution is to use an eventfilter to the QWindow and to be able to filter by verifying that the click is given on a cell.
from PyQt5.QtCore import (
pyqtSignal,
QEvent,
QObject,
QPoint,
Qt,
)
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QPushButton,
QTableWidget,
QTableWidgetItem,
QVBoxLayout,
QWidget,
)
class MouseObserver(QObject):
pressed = pyqtSignal(QPoint, QPoint)
released = pyqtSignal(QPoint, QPoint)
moved = pyqtSignal(QPoint, QPoint)
def __init__(self, window):
super().__init__(window)
self._window = window
self.window.installEventFilter(self)
#property
def window(self):
return self._window
def eventFilter(self, obj, event):
if self.window is obj:
if event.type() == QEvent.MouseButtonPress:
self.pressed.emit(event.pos(), event.globalPos())
elif event.type() == QEvent.MouseMove:
self.moved.emit(event.pos(), event.globalPos())
elif event.type() == QEvent.MouseButtonRelease:
self.released.emit(event.pos(), event.globalPos())
return super().eventFilter(obj, event)
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tablewidget = QTableWidget(4, 4)
container = QWidget()
lay = QVBoxLayout(container)
lay.addWidget(QLabel("QLabel", alignment=Qt.AlignCenter))
lay.addWidget(QPushButton("QPushButton"))
container.setFixedSize(container.sizeHint())
item = QTableWidgetItem()
self.tablewidget.setItem(0, 0, item)
item.setSizeHint(container.sizeHint())
self.tablewidget.setCellWidget(0, 0, container)
self.tablewidget.resizeRowsToContents()
self.tablewidget.resizeColumnsToContents()
lay = QVBoxLayout(self)
lay.addWidget(self.tablewidget)
def handle_window_released(self, window_pos, global_pos):
lp = self.tablewidget.viewport().mapFromGlobal(global_pos)
ix = self.tablewidget.indexAt(lp)
if ix.isValid():
print(ix.row(), ix.column())
def main():
import sys
app = QApplication(sys.argv)
widget = Widget()
widget.resize(640, 480)
widget.show()
mouse_observer = MouseObserver(widget.windowHandle())
mouse_observer.released.connect(widget.handle_window_released)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
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 want to implement behaviour of a popup-window exactly like default volume controller in windows 10. One click on icon, window opens or closes; if window is opened, clicking outside it will close the window. How can i implement this?
Before, i found that it is possible for the widget to override the methods for pressing and releasing the mouse keys, but here it was not found, or it was poorly searched. Help me please.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout, \
QWidget, QSystemTrayIcon, QStyle, qApp
import PyQt5.QtCore
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setMinimumSize(PyQt5.QtCore.QSize(600, 130))
self.setMaximumSize(PyQt5.QtCore.QSize(600, 130))
self.setWindowFlags(PyQt5.QtCore.Qt.Popup)
screen_geometry = QApplication.desktop().availableGeometry()
screen_size = (screen_geometry.width(), screen_geometry.height())
win_size = (self.frameSize().width(), self.frameSize().height())
x = screen_size[0] - win_size[0]
y = screen_size[1] - win_size[1]
self.move(x, y)
self.setWindowOpacity(0.85)
self.setWindowTitle("System Tray Application")
central_widget = QWidget(self)
self.setCentralWidget(central_widget)
grid_layout = QGridLayout(central_widget)
grid_layout.addWidget(QLabel("Application, which can minimize to tray",
self), 0, 0)
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(self.
style().standardIcon(QStyle.SP_ComputerIcon))
self.tray_icon.activated.connect(self.trigger)
self.tray_icon.show()
self.setGeometry(500, 570, 600, 130)
self.fl = False
def trigger(self, reason):
if reason == QSystemTrayIcon.MiddleClick:
qApp.quit()
elif reason == QSystemTrayIcon.Trigger:
if not self.fl:
self.show()
else:
self.hide()
self.fl = not self.fl
elif reason == 1:
self.fl = False
# def mouseReleaseEvent(self, event):
# self.hide()
# self.fl = False
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec())
If you want to toggle visibility then you must use the setVisible() and isVisible() methods:
import sys
from PyQt5.QtWidgets import (
QApplication,
QGridLayout,
QLabel,
QMainWindow,
QStyle,
QSystemTrayIcon,
QWidget,
)
from PyQt5.QtCore import Qt, QSize
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setFixedSize(600, 130)
self.setWindowFlag(Qt.Popup)
self.setWindowOpacity(0.85)
self.setWindowTitle("System Tray Application")
central_widget = QWidget()
self.setCentralWidget(central_widget)
grid_layout = QGridLayout(central_widget)
grid_layout.addWidget(QLabel("Application, which can minimize to tray"), 0, 0)
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
self.tray_icon.activated.connect(self.trigger)
self.tray_icon.show()
self.setGeometry(
QStyle.alignedRect(
Qt.LeftToRight,
Qt.AlignBottom | Qt.AlignRight,
self.window().size(),
QApplication.desktop().availableGeometry(),
)
)
def trigger(self, reason):
if reason == QSystemTrayIcon.MiddleClick:
QApplication.quit()
elif reason == QSystemTrayIcon.Trigger:
self.setVisible(not self.isVisible())
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec())
This is what my example looks like:
The text area is a QPlainTextEdit() object because I want the text to wrap to the second line. I think this is the best widget choice.
The user will only enter a maximum number of 90 characters in this box so I don't need a large text area.
I want to disable the key press Enter (carriage return). I got it to work but it seems hacky and I don't think it would work cross-platform (ex: Mac).
Surely, there's got to be a better way to prevent a carriage return key event in a QPlainTextEdit object?
My Current Solution Explained
Below, you can see I'm checking if an IndexError occurs because the last_value throws an IndexError when there's nothing in the QPlainTextEdit box. Then, I'm getting the last character and asking if it's equal to a new line. If it is, I'm re-setting the text without that new line and moving the cursor to the end.
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
Full Code Minimal Working Example:
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
from PyQt5.QtGui import QTextCursor
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.grid = QGridLayout()
self.label = QLabel('Description Line 1')
self.grid.addWidget(self.label, 0, 0)
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.field.textChanged.connect(self.some_event)
#TODO how to disable enter/return key events in this field?
self.grid.addWidget(self.field, 1, 0)
self.button = QPushButton('Some Button')
self.grid.addWidget(self.button)
self.centralWidget = QWidget()
self.centralWidget.setLayout(self.grid)
self.setCentralWidget(self.centralWidget)
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
One option is to override the keyPressEvent method of the QPlainTextEdit:
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class PlainTextEdit(QPlainTextEdit):
def keyPressEvent(self, event):
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return
super().keyPressEvent(event)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = PlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
Another option that implements the same logic is to use an eventFilter().
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.field.installEventFilter(self)
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
def eventFilter(self, obj, event):
if obj is self.field and event.type() == QEvent.KeyPress:
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return True
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())