Qt: A better way to fullscreen/revert QGraphicsView and QVideoWidget? - qt

I am trying to implement fullscreen and revert functions to my multimedia viewer program, following this thread (and some other similar threads), I've reached a conclusion similar to the following MRE (the actual block of code performing/reverting the fullscreen is the elif event.key() == qtc.Qt.Key.Key_F... block inside keyPressEvent of class Stack):
from __future__ import annotations
from PySide6 import QtCore as qtc
from PySide6 import QtGui as qtg
from PySide6 import QtMultimedia as qtm
from PySide6 import QtMultimediaWidgets as qtmw
from PySide6 import QtWidgets as qtw
image_path = ""
video_path = ""
class Stack(qtw.QStackedWidget):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._full_screen_widget = None
def keyPressEvent(self, event: qtg.QKeyEvent) -> None:
if event.key() == qtc.Qt.Key.Key_N:
if not self._full_screen_widget:
if self.currentWidget() == video:
self.currentWidget().stop()
self.currentWidget().setSource("")
self.setCurrentWidget(graphics)
elif self.currentWidget() == graphics:
video.play()
self.setCurrentWidget(video)
elif (
event.key() == qtc.Qt.Key.Key_F
and event.modifiers() == qtc.Qt.KeyboardModifier.NoModifier
):
if self._full_screen_widget:
self._full_screen_widget.showNormal()
self._full_screen_widget.setWindowFlags(
self._full_screen_widget._backup_window_flags
)
self._full_screen_widget.setParent(self)
self.addWidget(self._full_screen_widget)
self.setCurrentWidget(self._full_screen_widget)
self._full_screen_widget.setFocus(qtc.Qt.FocusReason.OtherFocusReason)
self._full_screen_widget = None
else:
self._full_screen_widget = self.currentWidget()
self.removeWidget(self._full_screen_widget)
self._full_screen_widget.setWindowFlag(qtc.Qt.WindowType.Window)
self._full_screen_widget.showFullScreen()
else:
super().keyPressEvent(event)
return
event.accept()
return
class Graphics(qtw.QGraphicsView):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._backup_window_flags = self.windowFlags()
self._scene = qtw.QGraphicsScene()
self._pixmap_item = qtw.QGraphicsPixmapItem()
self._pixmap_item.setPixmap(qtg.QPixmap(image_path))
self._scene.addItem(self._pixmap_item)
self.setScene(self._scene)
def keyPressEvent(self, event: qtg.QKeyEvent):
if event.key() == qtc.Qt.Key.Key_F:
qtc.QCoreApplication.sendEvent(stack, event)
event.accept()
return
super().keyPressEvent(event)
return
class Video(qtmw.QVideoWidget):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._backup_window_flags = self.windowFlags()
loop = qtc.QEventLoop()
self._media_player = qtm.QMediaPlayer()
self._media_player.mediaStatusChanged.connect(loop.exit)
self._media_player.setVideoOutput(self)
self._media_player.setSource(video_path)
loop.exec()
def play(self):
self._media_player.play()
def stop(self):
self._media_player.stop()
def setSource(self, source: str):
self._media_player.setSource(source)
def keyPressEvent(self, event: qtg.QKeyEvent):
if event.key() == qtc.Qt.Key.Key_F:
qtc.QCoreApplication.sendEvent(stack, event)
event.accept()
return
super().keyPressEvent(event)
return
app = qtw.QApplication()
mw = qtw.QMainWindow()
stack = Stack(parent=mw)
graphics = Graphics(parent=stack)
video = Video(parent=stack)
mw.setCentralWidget(stack)
stack.addWidget(graphics)
stack.addWidget(video)
stack.setCurrentWidget(graphics)
mw.show()
app.exec()
As for why I don't just fullscreen the main window, instead of individual elements, is because the actual program's GUI has other elements to it. Hence, the main window fullscreen would contain elements other than the graphics/video widgets.

Related

QWebEngineView crashes without error output

The page loads, I enter something in the search and the application freezes dead. You can have time to click on some link, but then everything freezes and crashes. There is no error message.
The most interesting thing is that it used to work, and then after some point it stopped (the code did NOT change)
my code:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
class TabWidget(QTabWidget):
def __init__(self, *args, **kwargs):
QTabWidget.__init__(self, *args, **kwargs)
url = QUrl("https://google.com")
view = HtmlView(self)
view.load(url)
ix = self.addTab(view, "loading ...")
class HtmlView(QWebEngineView):
def __init__(self, *args, **kwargs):
QWebEngineView.__init__(self, *args, **kwargs)
self.tab = self.parent()
def createWindow(self, windowType):
if windowType == QWebEnginePage.WebBrowserTab:
webView = HtmlView(self.tab)
ix = self.tab.addTab(webView, "loading ...")
self.tab.setCurrentIndex(ix)
return webView
return QWebEngineView.createWindow(self, windowType)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = TabWidget()
main.show()
sys.exit(app.exec_())
I checked the drivers, reinstalled PyQt, but it doesn't help

X button does not fire the closeEvent

I'm trying to use the closeEvent function when the user press X on main window but Python never fired closeEvent function.
I read many posts about this issue but eventually I was not succeeded to resolve this.
Any ideas why?
Here is the code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QAction, QMessageBox, QMenu, QWidget
class Ui_MainWindow(object):
def __init__(self):
super(Ui_MainWindow, self).__init__()
print("Initialization succeeded")
def closeEvent(self, event):
print("closeEvent has been called")
userResult = QMessageBox.question(None, "Quit", "Do you want to close the program?", QMessageBox.Yes,
QMessageBox.No)
if userResult == QMessageBox.Yes:
event.accept()
else:
event.ignore()
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1920, 1080)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("Milvus UI", "Milvus UI"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

Why Draw line in QGraphicScene not show but add button worked in pyqt

when i add pushbutton dynamically to the QGraphicScene with a pic its work but when i use QPainter to draw a line or rectangle not show.
code:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import QIcon,QPixmap,QPainter,QPainterPath,QBrush,QColor,QPen
class Scene(QtWidgets.QGraphicsScene):
def __init__(self, *args, **kwargs):
super(Scene, self).__init__(*args, **kwargs)
self.path_item = self.addPath(QtGui.QPainterPath())
self.start_point = QtCore.QPointF()
self.end_point = QtCore.QPointF()
def mousePressEvent(self, event):
self.start_point = event.scenePos()
self.end_point = self.start_point
self.update_path()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton:
self.end_point = event.scenePos()
self.update_path()
super(Scene, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self.end_point = event.scenePos()
self.update_path()
super(Scene, self).mouseReleaseEvent(event)
def update_path(self):
if not self.start_point.isNull() and not self.end_point.isNull():
path = QtGui.QPainterPath()
path.moveTo(self.start_point)
path.lineTo(self.end_point)
self.path_item.setPath(path)
def main():
app = QtWidgets.QApplication(sys.argv)
view = QtWidgets.QGraphicsView()
view.setRenderHint(QtGui.QPainter.Antialiasing)
view.setMouseTracking(True)
pix = QPixmap('assets/data.png')
mainpic = QtWidgets.QGraphicsPixmapItem(pix)
scene = Scene()
scene.addItem(mainpic)
view.setScene(scene)
view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I think my problem in mouse event but if i disable pic in GraphicsScene draw line correctly worked.

Capture mouse position outside QMainWindow (without click)

I tried:
self.installEventFilter(self)
and:
desktop= QApplication.desktop()
desktop.installEventFilter(self)
With:
def eventFilter(self, source, event):
if event.type() == QEvent.MouseMove:
print(event.pos())
return QMainWindow.eventFilter(self, source, event)
In QMainWindow object but nothing conclusive.
Do you have any idea?
Mouse events are initially handled by the window-manager, which then passes them on to whatever window is in that region of the screen. So if there are no Qt windows in that region, you won't get any events (including mouse events).
However, it is still possible to track the cursor position via polling:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
cursorMove = QtCore.pyqtSignal(object)
def __init__(self):
super(Window, self).__init__()
self.cursorMove.connect(self.handleCursorMove)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(50)
self.timer.timeout.connect(self.pollCursor)
self.timer.start()
self.cursor = None
def pollCursor(self):
pos = QtGui.QCursor.pos()
if pos != self.cursor:
self.cursor = pos
self.cursorMove.emit(pos)
def handleCursorMove(self, pos):
print(pos)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 500, 200, 200)
window.show()
sys.exit(app.exec_())

PySide moving QGraphicsPixmapItem jumps to upper left corner of scene

I am writing an application that allows a user to place images on a QGraphicsScene (contained within a QGraphicsView) by clicking on a blank area and then move them about using mousemoveevent. The images are created using a subclassed QGraphicsPixmapItem.
Here's the problem: The very first attempt at moving an item works as expected. However, for all subsequent moves the selected item immediately jumps to the upper left corner of the scene. Here is the code:
import sys
from PySide import QtGui,QtCore
class TestPixmapItem(QtGui.QGraphicsPixmapItem):
def __init__(self, imagename, position, parent=None):
QtGui.QGraphicsPixmapItem.__init__(self, parent)
px = QtGui.QPixmap(imagename)
self.setPixmap(px)
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
# set position
self.setPos(position.x(),position.y())
def mouseReleaseEvent(self,e):
self.setSelected(False)
def mouseMoveEvent(self, e):
QtGui.QGraphicsPixmapItem.mouseMoveEvent(self, e)
class GfxScene(QtGui.QGraphicsScene):
def __init__(self, parent=None):
#build parent user interface
super(GfxScene, self).__init__(parent)
def mousePressEvent(self, e):
if(self.itemAt(e.scenePos().x(),e.scenePos().y()) == None):
pixmapItem = TestPixmapItem('test.png',e.scenePos())
self.addItem(pixmapItem)
else:
QtGui.QGraphicsScene.mousePressEvent(self,e);
class MainForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
scene = GfxScene(self)
scene.setSceneRect(QtCore.QRect(0, 0, 800, 800))
view = QtGui.QGraphicsView()
view.setScene(scene)
view.setSceneRect(scene.sceneRect())
#view.setGeometry(QtCore.QRect(0, 0, 800, 800))
self.setCentralWidget(view)
def main():
#This function means this was run directly, not called from another python file.
app = QtGui.QApplication.instance()
if app == None:
app = QtGui.QApplication(sys.argv)
myapp = MainForm()
myapp.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Any help would be appreciated!
You should call the QtGui.QGraphicsPixmapItem.mouseReleaseEvent(self, e) when you override the mouse release event, see : http://goo.gl/ChSYP
import sys
from PySide import QtGui,QtCore
class TestPixmapItem(QtGui.QGraphicsPixmapItem):
def __init__(self, imagename, position, parent=None):
QtGui.QGraphicsPixmapItem.__init__(self, parent)
px = QtGui.QPixmap(imagename)
self.setPixmap(px)
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
# set position
self.setPos(position.x(),position.y())
def mouseReleaseEvent(self,e):
self.setSelected(False)
QtGui.QGraphicsPixmapItem.mouseReleaseEvent(self, e) // here calling the event
def mouseMoveEvent(self, e):
QtGui.QGraphicsPixmapItem.mouseMoveEvent(self, e)
class GfxScene(QtGui.QGraphicsScene):
def __init__(self, parent=None):
#build parent user interface
super(GfxScene, self).__init__(parent)
def mousePressEvent(self, e):
if(self.itemAt(e.scenePos().x(),e.scenePos().y()) == None):
pixmapItem = TestPixmapItem('test.png',e.scenePos())
self.addItem(pixmapItem)
else:
QtGui.QGraphicsScene.mousePressEvent(self,e);
class MainForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
scene = GfxScene(self)
scene.setSceneRect(QtCore.QRect(0, 0, 800, 800))
view = QtGui.QGraphicsView()
view.setScene(scene)
view.setSceneRect(scene.sceneRect())
#view.setGeometry(QtCore.QRect(0, 0, 800, 800))
self.setCentralWidget(view)
def main():
#This function means this was run directly, not called from another python file.
app = QtGui.QApplication.instance()
if app == None:
app = QtGui.QApplication(sys.argv)
myapp = MainForm()
myapp.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Resources