I can rename tab label programmatically.
With QInputDialog I can get new label text and set tab widget label.
But, I hope for a more user-friendly solution like double-clicking on label and get editing on the tab itself.
A QListWidgetItem with editable flag can show me the way, but I can't find the solution for tab label.
There are no built-in methods for achieving this. However, you could use a simple popup line-edit and position it over the tab. Here's a basic demo script:
PyQt5:
import sys
from PyQt5 import QtCore, QtWidgets
class TabBar(QtWidgets.QTabBar):
def __init__(self, parent):
super().__init__(parent)
self._editor = QtWidgets.QLineEdit(self)
self._editor.setWindowFlags(QtCore.Qt.Popup)
self._editor.setFocusProxy(self)
self._editor.editingFinished.connect(self.handleEditingFinished)
self._editor.installEventFilter(self)
def eventFilter(self, widget, event):
if ((event.type() == QtCore.QEvent.MouseButtonPress and
not self._editor.geometry().contains(event.globalPos())) or
(event.type() == QtCore.QEvent.KeyPress and
event.key() == QtCore.Qt.Key_Escape)):
self._editor.hide()
return True
return super().eventFilter(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(QtWidgets.QTabWidget):
def __init__(self):
super().__init__()
self.setTabBar(TabBar(self))
self.addTab(QtWidgets.QWidget(self), 'Tab One')
self.addTab(QtWidgets.QWidget(self), 'Tab Two')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Test')
window.setGeometry(600, 100, 200, 100)
window.show()
sys.exit(app.exec_())
PyQt4:
from PyQt4 import QtGui, QtCore
class TabBar(QtGui.QTabBar):
def __init__(self, parent):
QtGui.QTabBar.__init__(self, parent)
self._editor = QtGui.QLineEdit(self)
self._editor.setWindowFlags(QtCore.Qt.Popup)
self._editor.setFocusProxy(self)
self._editor.editingFinished.connect(self.handleEditingFinished)
self._editor.installEventFilter(self)
def eventFilter(self, widget, event):
if ((event.type() == QtCore.QEvent.MouseButtonPress and
not self._editor.geometry().contains(event.globalPos())) or
(event.type() == QtCore.QEvent.KeyPress and
event.key() == QtCore.Qt.Key_Escape)):
self._editor.hide()
return True
return QtGui.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(QtGui.QTabWidget):
def __init__(self):
QtGui.QTabWidget.__init__(self)
self.setTabBar(TabBar(self))
self.addTab(QtGui.QWidget(self), 'Tab One')
self.addTab(QtGui.QWidget(self), 'Tab Two')
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Test')
window.setGeometry(600, 100, 200, 100)
window.show()
sys.exit(app.exec_())
Update to the answer left by ekhumoro :
In PyQt5, the code now looks like this :
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_())
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_())
I have a Qt widget that looks like this:
class launchiiwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.textbox = QtWidgets.QTextEdit(self)
self.textbox.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.textbox.setAlignment(QtCore.Qt.AlignCenter)
self.textbox.setFixedSize(QtCore.QSize(600, 100))
self.textbox.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.textbox.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
layout.addWidget(self.textbox)
font = self.textbox.font()
font.setPointSize(80)
self.textbox.setFont(font)
self.listwidget = QtWidgets.QListWidget(self)
self.listwidget.addItem("Red")
self.listwidget.addItem("Blue")
layout.addWidget(self.listwidget)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget = launchiiwidget()
widget.setWindowFlags(QtCore.Qt.FramelessWindowHint)
widget.resize(600, 200)
widget.show()
sys.exit(app.exec())
How can I make it so when the "return" or "right arrow key" is pressed, focus moves from wherever it is currently to the first item in listwidget? This should also work while being focused inside of textbox, without triggering a newline.
Note: items get dynamically added to listwidget.
A possible solution could be to use QShorcut but because the OP requires "without triggering a newline". So in this case the solution is to implement an eventfilter to the QWindow:
import sys
from PyQt6 import QtCore, QtGui, QtWidgets
class KeyHelper(QtCore.QObject):
pressed = QtCore.pyqtSignal()
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 event.type() == QtCore.QEvent.Type.KeyPress:
if event.key() in (
QtCore.Qt.Key.Key_Return,
QtCore.Qt.Key.Key_Enter,
QtCore.Qt.Key.Key_Right,
):
self.pressed.emit()
return True
return super().eventFilter(obj, event)
class Launchiiwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.textbox = QtWidgets.QTextEdit()
self.textbox.setLineWrapMode(QtWidgets.QTextEdit.LineWrapMode.NoWrap)
self.textbox.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.textbox.setFixedSize(QtCore.QSize(600, 100))
self.textbox.setVerticalScrollBarPolicy(
QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
self.textbox.setHorizontalScrollBarPolicy(
QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
font = self.textbox.font()
font.setPointSize(80)
self.textbox.setFont(font)
self.listwidget = QtWidgets.QListWidget()
self.listwidget.addItem("Red")
self.listwidget.addItem("Blue")
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.textbox)
layout.addWidget(self.listwidget)
def update_focus(self):
self.listwidget.setFocus()
index = self.listwidget.model().index(0, 0)
if index.isValid():
self.listwidget.setCurrentIndex(index)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget = Launchiiwidget()
widget.setWindowFlags(QtCore.Qt.WindowType.FramelessWindowHint)
widget.resize(600, 200)
widget.show()
key_helper = KeyHelper(widget.windowHandle())
key_helper.pressed.connect(widget.update_focus)
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_())
I have the same problem from this topic: QRubberBand move when I resize window, after a few try I realized that solution from this topic doesn't apply on QGraphics View. Why my selection move, arout QgraphicsView when I resize window.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# from PyQt4 import QtCore, QtWidgets
class ResizableRubberBand(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(ResizableRubberBand, self).__init__(parent)
self.draggable = False
self.mousePressPos = None
self.mouseMovePos = None
self._band = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
self._band.setGeometry(550, 550, 550, 550)
self._band.show()
self.show()
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.RightButton:
self.mousePressPos = event.globalPos() # global
self.mouseMovePos = event.globalPos() - self.pos() # local
self.draggable = True
elif event.button() == QtCore.Qt.LeftButton:
self.position = QtCore.QPoint(event.pos())
self.upper_left = self.position
self.lower_right = self.position
self.mode = "drag_lower_right"
self._band.show()
def mouseMoveEvent(self, event):
if self.draggable and event.buttons() & QtCore.Qt.RightButton:
globalPos = event.globalPos()
print(globalPos)
diff = globalPos - self.mouseMovePos
self.move(diff)
self.mouseMovePos = globalPos - self.pos()
elif self._band.isVisible():
# visible selection
if self.mode is "drag_lower_right":
self.lower_right = QtCore.QPoint(event.pos())
# print(str(self.lower_right))
elif self.mode is "drag_upper_left":
self.upper_left = QtCore.QPoint(event.pos())
# print(str(self.upper_left))
# update geometry
self._band.setGeometry(QtCore.QRect(self.upper_left, self.lower_right).normalized())
def mouseReleaseEvent(self, event):
self.draggable = False
my main class:
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.band = ResizableRubberBand()
scene = QtWidgets.QGraphicsScene(self)
photo = QtGui.QPixmap('image.jpg')
scene.addPixmap(photo)
self.band.setScene(scene)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.band)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(800, 100, 600, 500)
window.show()
sys.exit(app.exec_())
before resize:
after resize:
The problem is caused because the coordinate system of the image is not the same as that of the QRubberBand. So the solution is that you both share the same coordinate system and for this we add the QRubberBand to the scene.
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self.m_rubberBand = QtWidgets.QRubberBand(
QtWidgets.QRubberBand.Rectangle
)
self.m_rubberBand.setGeometry(QtCore.QRect(-1, -1, 2, 2))
self.m_rubberBand.hide()
item = self.scene().addWidget(self.m_rubberBand)
item.setZValue(1)
self.m_draggable = False
self.m_origin = QtCore.QPoint()
def mousePressEvent(self, event):
self.m_origin = self.mapToScene(event.pos()).toPoint()
self.m_rubberBand.setGeometry(
QtCore.QRect(self.m_origin, QtCore.QSize())
)
self.m_rubberBand.show()
self.m_draggable = True
super(GraphicsView, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.m_draggable:
end_pos = self.mapToScene(event.pos()).toPoint()
self.m_rubberBand.setGeometry(
QtCore.QRect(self.m_origin, end_pos).normalized()
)
self.m_rubberBand.show()
def mouseReleaseEvent(self, event):
end_pos = self.mapToScene(event.pos()).toPoint()
self.m_rubberBand.setGeometry(
QtCore.QRect(self.m_origin, end_pos).normalized()
)
self.m_draggable = False
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
photo = QtGui.QPixmap("image.jpg")
w.scene().addPixmap(photo)
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
I am using an overlay with a QPaintEvent to draw over other widgets. I still need the widgets underneath to register mouse events. When I call raise() with the WA_TransparentForMouseEvents flag, I gain control of the widgets again, but of course, lose the paintevent as it's no longer registering any mouse events. What are my options here?
class Overlay(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Overlay, self).__init__(parent)
self.hotBox = parent
self.resize(self.hotBox.width, self.hotBox.height)
def paintEvent(self, event):
#args: [QEvent]
if any ([self.hotBox.name=="main", self.hotBox.name=="viewport"]):
self.raise_()
self.setWindowFlags(QtCore.Qt.WA_TransparentForMouseEvents)
#Initialize painter
painter = QtGui.QPainter(self)
pen = QtGui.QPen(QtGui.QColor(115, 115, 115), 3, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
painter.setPen(pen)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setBrush(QtGui.QColor(115, 115, 115))
painter.drawEllipse(self.hotBox.point, 5, 5)
#perform paint
if self.hotBox.mousePosition:
mouseX = self.hotBox.mousePosition.x()
mouseY = self.hotBox.mousePosition.y()
line = QtCore.QLine(mouseX, mouseY, self.hotBox.point.x(), self.hotBox.point.y())
painter.drawLine(line)
painter.drawEllipse(mouseX-5, mouseY-5, 10, 10)
If you want to create an overlay using the events mouseXXXEvent you must use an eventFilter, for this solution I based on this answer of #KubaOber adding more functionalities:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class Overlay(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Overlay, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
self.start_line, self.end_line = QtCore.QPoint(), QtCore.QPoint()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.fillRect(self.rect(), QtGui.QColor(80, 80, 255, 128))
if not self.start_line.isNull() and not self.end_line.isNull():
painter.drawLine(self.start_line, self.end_line)
def mousePressEvent(self, event):
self.start_line = event.pos()
self.end_line = event.pos()
self.update()
def mouseMoveEvent(self, event):
self.end_line = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.start_line = QtCore.QPoint()
self.end_line = QtCore.QPoint()
class OverlayFactoryFilter(QtCore.QObject):
def __init__(self, parent=None):
super(OverlayFactoryFilter, self).__init__(parent)
self.m_overlay = None
def setWidget(self, w):
w.installEventFilter(self)
if self.m_overlay is None:
self.m_overlay = Overlay()
self.m_overlay.setParent(w)
def eventFilter(self, obj, event):
if not obj.isWidgetType():
return False
if event.type() == QtCore.QEvent.MouseButtonPress:
self.m_overlay.mousePressEvent(event)
elif event.type() == QtCore.QEvent.MouseButtonRelease:
self.m_overlay.mouseReleaseEvent(event)
elif event.type() == QtCore.QEvent.MouseMove:
self.m_overlay.mouseMoveEvent(event)
elif event.type() == QtCore.QEvent.MouseButtonDblClick:
self.m_overlay.mouseDoubleClickEvent(event)
elif event.type() == QtCore.QEvent.Resize:
if self.m_overlay and self.m_overlay.parentWidget() == obj:
self.m_overlay.resize(obj.size())
elif event.type() == QtCore.QEvent.Show:
self.m_overlay.raise_()
return super(OverlayFactoryFilter, self).eventFilter(obj, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
factory = OverlayFactoryFilter()
w = QtWidgets.QWidget()
factory.setWidget(w)
button = QtWidgets.QPushButton("Press me", w)
w.show()
sys.exit(app.exec_())