Trouble with Focus out Event - python

I am trying to reduce the height of the App when the MainWindow gets out of focus, but with the code below nothing like that happens.
class MyApp(QMainWindow):
def __init__(self):
super(MyApp, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.installEventFilter(self)
time_frame_values = [i/30 for i in range(30)]
self.timeFrame = map(lambda x: x**0.5, time_frame_values)
def eventFilter(self, widget, event):
if event.type() == QEvent.FocusOut:
self.on_focus_out()
print("Focus Out!")
return False
def on_focus_out(self):
print("Focus Out!!")
for i in reversed(self.timeFrame):
self.move(QPoint(ScreenSizeObject.width()-self.width()-10, ScreenSizeObject.height()-self.original_height-(i*300)))
self.ui.textDisplay.resize(QSize(self.ui.textDisplay.width(), self.ui.textDisplay.height() + (i * 15)))
time.sleep(0.01)
Here self.on_focus_out() will do the transition effect.
EXPECTATION: When I click anywhere out of the mainwindow I want the self.on_focus_out() to run.
REALITY: No TRANSITION EFFECT takes place, not even the print('Focus Out!') prints a character.
Thanks for your effort!!

For the desired behavior you are looking for,
change the QEvent.FocusOut to QEvent.WindowDeactivate and the problem is Solved!
Rewriting the Correct Code,
class MyApp(QMainWindow):
def __init__(self):
super(MyApp, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.installEventFilter(self)
time_frame_values = [i/30 for i in range(30)]
self.timeFrame = map(lambda x: x**0.5, time_frame_values)
def eventFilter(self, widget, event):
if event.type() == QEvent.WindowDeactivate:
self.on_focus_out()
print("Focus Out!")
return False
def on_focus_out(self):
print("Focus Out!!")
for i in reversed(self.timeFrame):
self.move(QPoint(ScreenSizeObject.width()-self.width()-10, ScreenSizeObject.height()-self.original_height-(i*300)))
self.ui.textDisplay.resize(QSize(self.ui.textDisplay.width(), self.ui.textDisplay.height() + (i * 15)))
time.sleep(0.01)

Related

How to avoid mouse events being eaten by QGraphicsView

I want mouse events to reach the appropriate QGraphicsItem but they get no further than the QGraphicsView.
I have reduced my code to 41 lines, commented out event handlers but to no avail. It is either handled by QGraphicsView if that has a handler or, if not, is not caught at all.
I'm sure I'm missing something obvious but I can't see it.
from PyQt5.QtWidgets import *
class MyFrame(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setScene(QGraphicsScene())
self.scene().addItem(Group())
def mouseReleaseEvent(self, event):
print('in QGraphicsView')
return QGraphicsView.mouseReleaseEvent(self, event)
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
item = MyEllipse(0, 0, 20, 20)
self.addToGroup(item)
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
return QGraphicsItemGroup.mouseReleaseEvent(self, event)
class MyEllipse(QGraphicsEllipseItem):
def mouseReleaseEvent(self, event):
print('in QGraphicsEllipseItem')
return QGraphicsEllipseItem.mouseReleaseEvent(self, event)
if __name__ == '__main__':
app = QApplication([])
f = MyFrame()
f.show()
app.exec_()
mouseReleaseEvent is called if and only if the event that the mousePressEvent handles is accepted, so with the following code the event will arrive at QGraphicsItemGroup:
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
item = MyEllipse(0, 0, 20, 20)
self.addToGroup(item)
def mousePressEvent(self, event):
QGraphicsItemGroup.mousePressEvent(self, event)
event.accept()
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
QGraphicsItemGroup.mouseReleaseEvent(self, event)
But as #ekhumoro points out, the QGraphicsItemGroup acts as a single element so events are not transported to the items they handle.
If you want to detect when the item is pressed you can use the following method:
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
self._item = MyEllipse(0, 0, 20, 20)
self.addToGroup(self._item)
def mousePressEvent(self, event):
QGraphicsItemGroup.mousePressEvent(self, event)
event.accept()
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
if self._item.mapToParent(self._item.boundingRect()).containsPoint(event.pos(), Qt.OddEvenFill):
print("_item")
QGraphicsItemGroup.mouseReleaseEvent(self, event)

Pyqt5 - Back to hidden MainWindows

I'm making a program to specify a specific area using pyqt5.
If I click on the capture button, I will hide the MainWindow and display a screen to specify the area. I want to clear the screen and return to the mainwindow by pressing the esc key. But MainWindow does not show again. How should I work it?
form_class = uic.loadUiType("prototype.ui")[0]
class MainWindow(QtWidgets.QMainWindow, form_class) :
def __init__(self):
super().__init__()
self.setupUi(self)
self.Capture_Button.clicked.connect(self.Capture_Btn_clicked)
self.CaptureWindow = CaptureWidget()
self.CaptureWindow.hide()
def Capture_Btn_clicked(self) :
self.hide()
self.CaptureWindow.close()
self.CaptureWindow.__init__()
self.CaptureWindow.show()
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
def enterEvent(self, QEvent):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.setWindowOpacity(1)
This is the class that specifies the area (some of the code is omitted).
class CaptureWidget(QtWidgets.QDialog):
def __init__(self):
super().__init__()
root = tk.Tk()
self.setupUi(self)
def setupUi(self) :
self.screen_width = root.winfo_screenwidth()
self.screen_height = root.winfo_screenheight()
self.setGeometry(0, 0, self.screen_width, self.screen_height)
self.setWindowTitle(' ')
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.setWindowOpacity(0.3)
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
self.setWindowFlags(QtCore.Qt.FramelessWindowHint|QtCore.Qt.WindowStaysOnTopHint)
print('Capture the screen...')
self.is_set_region = False
self.is_mouse_click = False
self.show()
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Escape:
print('esc')
self.close()
elif key == Qt.Key_F1:
self.close()
self.__init__()
First of all, instead of overwriting the keyPressEvent method, it is easier to use QShortcut. On the other hand for this case it is better to create a signal that indicates when the escape key is pressed connecting it to the show method.
from PyQt5 import QtCore, QtGui, QtWidgets, uic
class CaptureWidget(QtWidgets.QDialog):
escape_pressed = QtCore.pyqtSignal()
def __init__(self):
super().__init__()
self.setupUi()
def setupUi(self):
self.setWindowOpacity(0.3)
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
shorcut_scaped = QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self)
shorcut_scaped.activated.connect(self.escape_pressed)
shorcut_scaped.activated.connect(self.close)
shorcut = QtWidgets.QShortcut(QtCore.Qt.Key_F1, self)
shorcut.activated.connect(self.close)
form_class, _ = uic.loadUiType("prototype.ui")
class MainWindow(QtWidgets.QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.Capture_Button.clicked.connect(self.Capture_Btn_clicked)
self.CaptureWindow = CaptureWidget()
self.CaptureWindow.escape_pressed.connect(self.show)
#QtCore.pyqtSlot()
def Capture_Btn_clicked(self):
self.hide()
self.CaptureWindow.showFullScreen()
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
def enterEvent(self, QEvent):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.setWindowOpacity(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Calling function from another class doesn't work properly

this example
helped me a lot in understanding of how does the events work.
But I have another problem. After an event when I want to call a function of a main class it seems like it was starting from Filter class and, unfortunately I'm not able to fetch the content from Designer-made file.
class Filter(QtCore.QObject):
def eventFilter(self, widget, event):
if event.type() == QtCore.QEvent.FocusOut:
print 'focus out'
print widget.objectName()
if widget.objectName() == 'edit_notes':
StartQT4().object_edit_notes('edit_notes')
return False
else:
return False
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self._filter = Filter()
self.ui.edit_notes.installEventFilter(self._filter)
def object_edit_notes(self, w):
self.__init__()
something = self.ui.edit_notes.toPlainText()
something = unicode(something).encode('utf-8')
print something
return False
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
Attribute .something prints nothing. I tried to call identical function with the signal method button clicked() and it works fine.
Can you help me with this?
You don't need a separate class for the event-filter. Any object which inherits QObject or QWidget will do, which includes QMainWindow.
So move the event-filter into your StartQT4 class, like this:
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# filter the events through self
self.ui.edit_notes.installEventFilter(self)
def object_edit_notes(self, w):
# this will convert a QString to a python unicode object
something = unicode(self.ui.edit_notes.toPlainText())
print something
def eventFilter(self, widget, event):
if (event.type() == QtCore.QEvent.FocusOut and
widget is self.ui.edit_notes):
print 'focus out'
self.object_edit_notes('edit_notes')
return False
return QMainWindow.eventFilter(self, widget, event)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())

python segmentation fault

i want to display a message in pop-up window in python ...so i wrote this code...please check
import sys
from PyQt4.Qt import *
class MyPopup(QWidget):
def __init__(self):
print "6"
QWidget.__init__(self)
class MainWindow(QMainWindow):
def __init__(self, *args):
print "4"
QMainWindow.__init__(self, *args)
self.cw = QWidget(self)
self.setCentralWidget(self.cw)
self.btn1 = QPushButton("Start Chat", self.cw)
self.btn1.setGeometry(QRect(50, 30, 100, 30))
self.connect(self.btn1, SIGNAL("clicked()"), self.doit)
self.w = None
def doit(self):
print "5"
print "Opening a new popup window..."
self.w = MyPopup()
self.w.setGeometry(QRect(0, 0, 400, 200))
self.w.show()
class App(QApplication):
def __init__(self, *args):
print "3"
QApplication.__init__(self, *args)
self.main = MainWindow()
#self.connect(self, SIGNAL("lastWindowClosed()"), self.byebye )
self.main.show()
#def byebye( self ):
#self.exit(0)
for i in range(1, 5):
if __name__ == "__main__":
print "1"
global app
app = App(sys.argv)
app.exec_()
#main(sys.argv)
else:
print "over"
Here first loop its working but from second loop i m getting segmentation fault...guys please help me..
There is supposed to be just one QApplication object in an application. I guess your problem is that you attempt to create several in a loop.
If you want your user to close the main window four times before it actually closes, you can add an event handler:
class MainWindow(QMainWindow):
def __init__(self, *args):
...
self.counter = 1
def closeEvent(self, event):
print "closeEvent", self.counter
self.counter += 1
if self.counter < 5:
event.ignore()
else:
event.accept()

pyQt Hover event with Svg image

I've been working on this for some time now and I can't figure out what I'm doing wrong. I hope someone here can help.
I'm trying to get hover events to work when I mouse over an Svg item that's in a QGraphicsScene. Here's the code that I've been playing with.
#!/usr/bin/python
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtSvg import *
class Main(QWidget):
def __init__(self):
super(Main, self).__init__()
hbox = QHBoxLayout()
self.setLayout(hbox)
self.view = MyView(self)
self.scene = QGraphicsScene()
self.view.setScene(self.scene)
hbox.addWidget(self.view)
class MyView(QGraphicsView):
def __init__(self, parent):
super(MyView, self).__init__(parent)
self.parent = parent
def mousePressEvent(self, event):
super(MyView, self).mousePressEvent(event)
test = MySvg()
self.parent.scene.addItem(test.image)
class MySvg(QGraphicsSvgItem):
def __init__(self):
super(MySvg, self).__init__()
self.image = QGraphicsSvgItem('ubuntu.svg')
self.image.setFlags(QGraphicsItem.ItemIsSelectable|
QGraphicsItem.ItemIsMovable)
self.setAcceptsHoverEvents(True)
def hoverEnterEvent(self, event):
print 'Enter'
def hoverLeaveEvent(self, event):
print 'Leave'
def hoverMoveEvent(self, event):
print 'Moving'
def runMain():
app = QApplication(sys.argv)
ex = Main()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
runMain()
Hope someone can help.
You are monitoring hover events for MySvg but you are adding another QGraphicsSvgItem to the view that is just an instance (MySvg.image) in MySvg. Your MySvg is not even in the view. Try like this:
#!/usr/bin/python
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtSvg import *
class Main(QWidget):
def __init__(self):
super(Main, self).__init__()
hbox = QHBoxLayout()
self.setLayout(hbox)
self.view = MyView(self)
self.scene = QGraphicsScene()
self.view.setScene(self.scene)
hbox.addWidget(self.view)
class MyView(QGraphicsView):
def __init__(self, parent):
super(MyView, self).__init__(parent)
self.parent = parent
def mousePressEvent(self, event):
super(MyView, self).mousePressEvent(event)
test = MySvg()
self.parent.scene.addItem(test)
class MySvg(QGraphicsSvgItem):
def __init__(self):
super(MySvg, self).__init__('ubuntu.svg')
self.setFlags(QGraphicsItem.ItemIsSelectable|
QGraphicsItem.ItemIsMovable)
self.setAcceptsHoverEvents(True)
def hoverEnterEvent(self, event):
print 'Enter'
def hoverLeaveEvent(self, event):
print 'Leave'
def hoverMoveEvent(self, event):
print 'Moving'
def runMain():
app = QApplication(sys.argv)
ex = Main()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
runMain()

Categories

Resources