Qt: How to capture mouse movement in QVideoWidget? - qt

I tried this but this doesn't track the mouse movement unless a button is pressed:
from PySide6 import QtWidgets as qtw
from PySide6 import QtMultimediaWidgets as qtmw
app = qtw.QApplication()
vw = qtmw.QVideoWidget()
vw.setMouseTracking(True)
vw.mouseMoveEvent = lambda *x: print(1)
vw.show()
app.exec()
On other widgets, I would setMouseTracking(True) for the .viewport(), but it doesn't look like QVideoWidget has a viewport.

Related

Qt: QGraphicsVideoItem not expanding to largest possible size

I'm trying to load a 720p video with a QGraphicsVideoItem in a QGraphicsView, but the output is no where near the size. How do I get it to stretch to the maximum size possible (based on window size)?
MRE:
from PySide6 import QtCore as qtc
from PySide6 import QtWidgets as qtw
from PySide6 import QtMultimedia as qtm
from PySide6 import QtMultimediaWidgets as qtmw
app = qtw.QApplication()
view = qtw.QGraphicsView()
scene = qtw.QGraphicsScene()
video_item = qtmw.QGraphicsVideoItem()
scene.addItem(video_item)
view.setScene(scene)
view.fitInView(video_item, qtc.Qt.AspectRatioMode.KeepAspectRatio)
media_player = qtm.QMediaPlayer()
media_player.setVideoOutput(video_item)
media_player.setSource("video_file")
media_player.mediaStatusChanged.connect(media_player.play)
view.show()
app.exec()
This is what it looks like in a 960/1080-ish window:

Qt: Can't create floating widget with QVideoWidget as parent?

I'm trying to create a floating, layout-less widget but it doesn't seem to work with a QVideoWidget as it's parent?
Working MRE:
from PySide6 import QtWidgets as qtw
app = qtw.QApplication()
w1 = qtw.QWidget()
w2 = qtw.QWidget(w1)
w2.setStyleSheet("background-color: red")
w1.show()
w2.show()
app.exec()
Not working MRE:
from PySide6 import QtMultimediaWidgets as qtmw
from PySide6 import QtWidgets as qtw
app = qtw.QApplication()
w1 = qtmw.QVideoWidget()
w2 = qtw.QWidget(w1)
w2.setStyleSheet("background-color: red")
w1.show()
w2.show()
app.exec()
The code is supposed to overlay a red QWidget over the QWidget/QVideoWidget but the red QWidget is shown only when the parent is a QWidget, and not when it's a QVideoWidget, why could that be?

How to define the icon of a Dock in pyqtgraph?

In pyqtgraph, Docks can be torn out of the DockArea by dragging or double clicking. The popups use a default icon. I would like to define my own icon. In the code below I set the application window. The same code has no effect on the dock, though there is no error message.
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout
from pyqtgraph.dockarea import Dock, DockArea
from PyQt5.QtGui import QIcon
class Foo(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowIcon(QIcon('direction'))
lay = QVBoxLayout(self)
da = DockArea()
d = Dock("Dock")
d.setWindowIcon(QIcon('direction')) # no effect
da.addDock(d)
lay.addWidget(da)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
I looked in the source code of Dock and DockArea of pyqtgraph and found out I had to overwrite floatDock function.
I created a function
def floatDockPatched(self, dock):
"""Removes *dock* from this DockArea and places it in a new window."""
area = self.addTempArea()
area.win.resize(dock.size())
area.win.setWindowIcon(QIcon("res/haip.png"))
area.win.setWindowTitle(dock.label.text())
area.moveDock(dock, 'top', None)
and assigned it to the class as overwrite
DockArea.floatDock = floatDockPatched

Qt: Understanding QScrollArea::widgetResizable property

I am experimenting with Qt 5 QScrollArea (in Python and PyQt, but I believe the question applies just as well in C++ Qt).
The Qt documentation for QScrollArea::widgetResizable says that "If this property is set to false (the default), the scroll area honors the size of its widget." By "its widget", I assume it means the widget being viewed in the scroll area.
However, in the program below I show an image label inside the scroll area, but the scroll area does not seem to "honor the size of its widget", because the image is partly hidden from the start.
The documentation also says "Regardless of this property, you can programmatically resize the widget using widget()->resize(), and the scroll area will automatically adjust itself to the new size." However, I do invoke resize for the viewed widget, but nothing happens.
The documentation also says "If this property is set to true, the scroll area will automatically resize the widget in order to avoid scroll bars where they can be avoided, or to take advantage of extra space." However, I don't see any resizing, even though if the widget were resized then it would be possible to avoid the scroll bars.
This is what I see whether I set the property to True or False, and whether I invoke widget().resize() or not:
Clearly I must be missing something quite fundamental here; what is it?
Edit: the main purpose of the question is understanding how widgetResizable works and what it does. Fitting the image into the window is a secondary goal.
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QImage, QPalette, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QScrollArea
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
image = QImage("happyguy.png")
imageLabel = QLabel()
imageLabel.setPixmap(QPixmap.fromImage(image))
scrollArea = QScrollArea()
scrollArea.setBackgroundRole(QPalette.Dark)
scrollArea.setWidget(imageLabel)
scrollArea.setWidgetResizable(True)
scrollArea.widget().resize(QSize(10, 10))
self.setCentralWidget(scrollArea)
app = QApplication([])
w = MainWindow()
w.show()
app.exec_()
And here's the happyguy.pgn file:
scrollArea.setWidgetResizable(True) give the resize control of imageLabel to scrollArea. So the next line scrollArea.widget().resize(QSize(10, 10)) will be overrode by system.
A solution worked on windows (resize main window to fit image size).
from PyQt5.QtGui import QImage, QPalette, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QScrollArea, QFrame
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
image = QImage("happyguy.png")
imageLabel = QLabel()
imageLabel.setPixmap(QPixmap.fromImage(image))
scrollArea = QScrollArea()
scrollArea.setFrameShape(QFrame.NoFrame)
scrollArea.setBackgroundRole(QPalette.Dark)
scrollArea.setWidget(imageLabel)
self.setCentralWidget(scrollArea)
self.resize(image.size())
app = QApplication([])
w = MainWindow()
w.show()
app.exec_()
Or use QScrollArea.setMinimumSize
from PyQt5.QtGui import QImage, QPalette, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QScrollArea, QFrame
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
image = QImage("happyguy.png")
imageLabel = QLabel()
imageLabel.setPixmap(QPixmap.fromImage(image))
scrollArea = QScrollArea()
scrollArea.setFrameShape(QFrame.NoFrame)
scrollArea.setBackgroundRole(QPalette.Dark)
scrollArea.setWidget(imageLabel)
scrollArea.setMinimumSize(image.size())
self.setCentralWidget(scrollArea)
app = QApplication([])
w = MainWindow()
w.show()
app.exec_()
Resizable IS NOT Scrollable ...

How to keep the shortcuts of a hidden widget in PyQt5?

I have a menu bar with a shortcut associated to it. I want to hide the menu bar but in that case the associated shortcut will be disabled. Here is an example:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.InitWindow()
def InitWindow(self):
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("&File")
mainMenu.hide() # comment it and the shortcut 'q' will work
quitItem = QAction("Quit", self)
quitItem.setShortcut("Q")
quitItem.triggered.connect(self.close)
fileMenu.addAction(quitItem)
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(App.exec())
If you put the line mainMenu.hide() in a comment, i.e. if the menu bar is shown, then the app. will quit with the shortcut 'q'. How could I keep the shortcuts of a hidden widget?
In the app. I want to add full-screen support, and in that case I want to hide the menu bar, but also, I want to keep the shortcuts in full-screen mode.
I found a working solution. The idea is the following: the main window has a shortcut ('q' in the example), and the menu bar also has this shortcut. To avoid conflict, disable the window's shortcut if the menu bar is present. If the menu bar is hidden, enable the window's shortcut.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QShortcut
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.shortcutQuit = QShortcut(QKeySequence("q"), self)
self.shortcutQuit.activated.connect(self.close)
self.shortcutQuit.setEnabled(False) # disable it if the menu bar is visible
self.InitWindow()
def InitWindow(self):
self.mainMenu = self.menuBar()
fileMenu = self.mainMenu.addMenu("&File")
hideItem = QAction("Hide Menu Bar", self)
hideItem.setShortcut("h")
hideItem.triggered.connect(self.my_hide)
quitItem = QAction("Quit", self)
quitItem.setShortcut("Q")
quitItem.triggered.connect(self.close)
fileMenu.addAction(hideItem)
fileMenu.addAction(quitItem)
def my_hide(self):
self.mainMenu.hide()
self.shortcutQuit.setEnabled(True)
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(App.exec())

Resources