mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-02-01 23:59:10 +00:00
ui: tweak media player style and behavior (#1025)
* ui: tweak media player style and behavior * ui: change player overlay to gradient * ui: add slight outline to player bar * feat: realtime playback seeking * fix(ui): click to jump to unbuffered media * chore: organize imports * refactor: remove unused code
This commit is contained in:
committed by
GitHub
parent
78e29a9a69
commit
c235d4f727
@@ -4,9 +4,12 @@
|
||||
|
||||
from typing import override
|
||||
|
||||
import structlog
|
||||
from PySide6.QtGui import QMouseEvent
|
||||
from PySide6.QtWidgets import QSlider, QStyle, QStyleOptionSlider
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class QClickSlider(QSlider):
|
||||
"""Custom QSlider wrapper.
|
||||
@@ -35,9 +38,14 @@ class QClickSlider(QSlider):
|
||||
was_slider_clicked = handle_rect.contains(int(ev.position().x()), int(ev.position().y()))
|
||||
|
||||
if not was_slider_clicked:
|
||||
self.setSliderDown(True)
|
||||
self.setValue(
|
||||
QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), ev.x(), self.width())
|
||||
)
|
||||
self.mouse_pressed = True
|
||||
|
||||
super().mousePressEvent(ev)
|
||||
|
||||
@override
|
||||
def mouseReleaseEvent(self, ev: QMouseEvent) -> None:
|
||||
self.setSliderDown(False)
|
||||
return super().mouseReleaseEvent(ev)
|
||||
|
||||
@@ -95,8 +95,6 @@ class PreviewThumbView(QWidget):
|
||||
self.__media_player_video_changed_callback
|
||||
)
|
||||
|
||||
self.__mp_max_size = QSize(*self.__img_button_size)
|
||||
|
||||
self.__media_player_page = QWidget()
|
||||
self.__stacked_page_setup(self.__media_player_page, self.__media_player)
|
||||
|
||||
@@ -131,7 +129,6 @@ class PreviewThumbView(QWidget):
|
||||
self, _timestamp: float, img: QPixmap, _size: QSize, _path: Path
|
||||
) -> None:
|
||||
self.__button_wrapper.setIcon(img)
|
||||
self.__mp_max_size = img.size()
|
||||
|
||||
def __thumb_renderer_updated_ratio_callback(self, ratio: float) -> None:
|
||||
self.__image_ratio = ratio
|
||||
@@ -174,25 +171,8 @@ class PreviewThumbView(QWidget):
|
||||
self.__preview_gif.setMaximumSize(adj_size)
|
||||
self.__preview_gif.setMinimumSize(adj_size)
|
||||
|
||||
if not self.__media_player.player.hasVideo():
|
||||
# ensure we do not exceed the thumbnail size
|
||||
mp_width = (
|
||||
adj_size.width()
|
||||
if adj_size.width() < self.__mp_max_size.width()
|
||||
else self.__mp_max_size.width()
|
||||
)
|
||||
mp_height = (
|
||||
adj_size.height()
|
||||
if adj_size.height() < self.__mp_max_size.height()
|
||||
else self.__mp_max_size.height()
|
||||
)
|
||||
mp_size = QSize(mp_width, mp_height)
|
||||
self.__media_player.setMinimumSize(mp_size)
|
||||
self.__media_player.setMaximumSize(mp_size)
|
||||
else:
|
||||
# have video, so just resize as normal
|
||||
self.__media_player.setMaximumSize(adj_size)
|
||||
self.__media_player.setMinimumSize(adj_size)
|
||||
self.__media_player.setMaximumSize(adj_size)
|
||||
self.__media_player.setMinimumSize(adj_size)
|
||||
|
||||
proxy_style = RoundedPixmapStyle(radius=8)
|
||||
self.__preview_gif.setStyle(proxy_style)
|
||||
|
||||
@@ -7,20 +7,31 @@ from pathlib import Path
|
||||
from time import gmtime
|
||||
from typing import override
|
||||
|
||||
import structlog
|
||||
from PIL import Image, ImageDraw
|
||||
from PySide6.QtCore import QEvent, QObject, QRectF, QSize, Qt, QUrl, QVariantAnimation
|
||||
from PySide6.QtGui import QAction, QBitmap, QBrush, QColor, QPen, QRegion, QResizeEvent
|
||||
from PySide6.QtGui import (
|
||||
QAction,
|
||||
QBitmap,
|
||||
QBrush,
|
||||
QColor,
|
||||
QLinearGradient,
|
||||
QMouseEvent,
|
||||
QPen,
|
||||
QRegion,
|
||||
QResizeEvent,
|
||||
)
|
||||
from PySide6.QtMultimedia import QAudioOutput, QMediaDevices, QMediaPlayer
|
||||
from PySide6.QtMultimediaWidgets import QGraphicsVideoItem
|
||||
from PySide6.QtSvgWidgets import QSvgWidget
|
||||
from PySide6.QtWidgets import (
|
||||
QGraphicsScene,
|
||||
QGraphicsView,
|
||||
QGridLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QSizePolicy,
|
||||
QSlider,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
@@ -30,6 +41,8 @@ from tagstudio.qt.translations import Translations
|
||||
if typing.TYPE_CHECKING:
|
||||
from tagstudio.qt.ts_qt import QtDriver
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class MediaPlayer(QGraphicsView):
|
||||
"""A basic media player widget.
|
||||
@@ -46,70 +59,41 @@ class MediaPlayer(QGraphicsView):
|
||||
slider_style = """
|
||||
QSlider {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QSlider::groove:horizontal {
|
||||
border: 1px solid #999999;
|
||||
height: 2px;
|
||||
margin: 2px 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal {
|
||||
background: #6ea0ff;
|
||||
border: 1px solid #5c5c5c;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: -6px 0;
|
||||
border-radius: 6px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
QSlider::add-page:horizontal {
|
||||
background: #3f4144;
|
||||
height: 2px;
|
||||
margin: 2px 0;
|
||||
border-radius: 2px;
|
||||
background: #65000000;
|
||||
border-radius: 3px;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #65444444;
|
||||
}
|
||||
|
||||
QSlider::sub-page:horizontal {
|
||||
background: #6ea0ff;
|
||||
height: 2px;
|
||||
margin: 2px 0;
|
||||
border-radius: 2px;
|
||||
background: #88FFFFFF;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QSlider::groove:vertical {
|
||||
border: 1px solid #999999;
|
||||
width: 2px;
|
||||
margin: 0 2px;
|
||||
border-radius: 2px;
|
||||
QSlider::groove:horizontal {
|
||||
background: transparent;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
QSlider::handle:vertical {
|
||||
background: #6ea0ff;
|
||||
border: 1px solid #5c5c5c;
|
||||
QSlider::handle:horizontal {
|
||||
background: #FFFFFF;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0 -6px;
|
||||
margin: -3px 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QSlider::add-page:vertical {
|
||||
background: #6ea0ff;
|
||||
width: 2px;
|
||||
margin: 0 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QSlider::sup-page:vertical {
|
||||
background: #3f4144;
|
||||
width: 2px;
|
||||
margin: 0 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
"""
|
||||
|
||||
# setup the scene
|
||||
fixed_policy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
|
||||
retain_policy = QSizePolicy()
|
||||
retain_policy.setRetainSizeWhenHidden(True)
|
||||
self.filepath: Path | None = None
|
||||
|
||||
# Graphics Scene
|
||||
self.installEventFilter(self)
|
||||
self.setScene(QGraphicsScene(self))
|
||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
@@ -121,6 +105,7 @@ class MediaPlayer(QGraphicsView):
|
||||
border: none;
|
||||
}
|
||||
""")
|
||||
self.setObjectName("mediaPlayer")
|
||||
self.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
self.video_preview = VideoPreview()
|
||||
@@ -129,67 +114,60 @@ class MediaPlayer(QGraphicsView):
|
||||
self.video_preview.setAcceptedMouseButtons(Qt.MouseButton.LeftButton)
|
||||
self.video_preview.installEventFilter(self)
|
||||
|
||||
# animation
|
||||
self.animation = QVariantAnimation(self)
|
||||
self.animation.valueChanged.connect(lambda value: self.set_tint_opacity(value))
|
||||
|
||||
# Set up the tint.
|
||||
self.tint = self.scene().addRect(
|
||||
0,
|
||||
0,
|
||||
self.size().width(),
|
||||
self.size().height(),
|
||||
12,
|
||||
QPen(QColor(0, 0, 0, 0)),
|
||||
QBrush(QColor(0, 0, 0, 0)),
|
||||
)
|
||||
|
||||
# setup the player
|
||||
self.filepath: Path | None = None
|
||||
# Player
|
||||
self.player = QMediaPlayer()
|
||||
self.player.setAudioOutput(QAudioOutput(QMediaDevices().defaultAudioOutput(), self.player))
|
||||
self.is_paused = (
|
||||
False # Q MediaPlayer.PlaybackState shows StoppedState when changing tracks
|
||||
)
|
||||
|
||||
# Used to keep track of play state.
|
||||
# It would be nice if we could use QMediaPlayer.PlaybackState,
|
||||
# but this will always show StoppedState when changing
|
||||
# tracks. Therefore, we wouldn't know if the previous
|
||||
# state was paused or playing
|
||||
self.is_paused = False
|
||||
|
||||
# Subscribe to player events from MediaPlayer
|
||||
self.player.positionChanged.connect(self.player_position_changed)
|
||||
self.player.mediaStatusChanged.connect(self.media_status_changed)
|
||||
self.player.playingChanged.connect(self.playing_changed)
|
||||
self.player.hasVideoChanged.connect(self.has_video_changed)
|
||||
self.player.audioOutput().mutedChanged.connect(self.muted_changed)
|
||||
|
||||
# Media controls
|
||||
self.master_controls = QWidget()
|
||||
master_layout = QGridLayout(self.master_controls)
|
||||
master_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.master_controls.setStyleSheet("background: transparent;")
|
||||
self.master_controls.setMinimumHeight(75)
|
||||
# Media Controls
|
||||
self.controls = QWidget()
|
||||
self.controls.setObjectName("controls")
|
||||
root_layout = QVBoxLayout(self.controls)
|
||||
root_layout.setContentsMargins(6, 0, 6, 0)
|
||||
root_layout.setSpacing(6)
|
||||
self.controls.setStyleSheet("background: transparent;")
|
||||
self.controls.setMinimumHeight(48)
|
||||
|
||||
self.pslider = QClickSlider()
|
||||
self.pslider.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
self.pslider.setTickPosition(QSlider.TickPosition.NoTicks)
|
||||
self.pslider.setSingleStep(1)
|
||||
self.pslider.setOrientation(Qt.Orientation.Horizontal)
|
||||
self.pslider.setStyleSheet(slider_style)
|
||||
self.pslider.sliderReleased.connect(self.slider_released)
|
||||
self.pslider.valueChanged.connect(self.slider_value_changed)
|
||||
self.pslider.hide()
|
||||
self.timeline_slider = QClickSlider()
|
||||
self.timeline_slider.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
self.timeline_slider.setTickPosition(QSlider.TickPosition.NoTicks)
|
||||
self.timeline_slider.setSingleStep(1)
|
||||
self.timeline_slider.setOrientation(Qt.Orientation.Horizontal)
|
||||
self.timeline_slider.setStyleSheet(slider_style)
|
||||
self.timeline_slider.sliderReleased.connect(self.slider_released)
|
||||
self.timeline_slider.valueChanged.connect(self.slider_value_changed)
|
||||
self.timeline_slider.hide()
|
||||
self.timeline_slider.setFixedHeight(12)
|
||||
|
||||
master_layout.addWidget(self.pslider, 0, 0, 0, 2)
|
||||
master_layout.setAlignment(self.pslider, Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
fixed_policy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
|
||||
root_layout.addWidget(self.timeline_slider)
|
||||
root_layout.setAlignment(self.timeline_slider, Qt.AlignmentFlag.AlignBottom)
|
||||
|
||||
self.sub_controls = QWidget()
|
||||
self.sub_controls.setMouseTracking(True)
|
||||
self.sub_controls.installEventFilter(self)
|
||||
sub_layout = QHBoxLayout(self.sub_controls)
|
||||
sub_layout.setContentsMargins(0, 0, 0, 0)
|
||||
sub_layout.setContentsMargins(0, 0, 0, 6)
|
||||
self.sub_controls.setStyleSheet("background: transparent;")
|
||||
self.sub_controls.setMinimumHeight(16)
|
||||
|
||||
self.play_pause = QSvgWidget()
|
||||
self.play_pause.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
@@ -218,9 +196,6 @@ class MediaPlayer(QGraphicsView):
|
||||
sub_layout.addWidget(self.mute_unmute)
|
||||
sub_layout.setAlignment(self.mute_unmute, Qt.AlignmentFlag.AlignLeft)
|
||||
|
||||
retain_policy = QSizePolicy()
|
||||
retain_policy.setRetainSizeWhenHidden(True)
|
||||
|
||||
self.volume_slider = QClickSlider()
|
||||
self.volume_slider.setOrientation(Qt.Orientation.Horizontal)
|
||||
self.volume_slider.setValue(int(self.player.audioOutput().volume() * 100))
|
||||
@@ -228,24 +203,20 @@ class MediaPlayer(QGraphicsView):
|
||||
self.volume_slider.setStyleSheet(slider_style)
|
||||
self.volume_slider.setSizePolicy(retain_policy)
|
||||
self.volume_slider.hide()
|
||||
self.volume_slider.setMinimumWidth(32)
|
||||
|
||||
sub_layout.addWidget(self.volume_slider)
|
||||
sub_layout.setAlignment(self.volume_slider, Qt.AlignmentFlag.AlignLeft)
|
||||
|
||||
# Adding a stretch here ensures the rest of the widgets
|
||||
# in the sub_layout will not stretch to fill the remaining
|
||||
# space.
|
||||
sub_layout.addStretch()
|
||||
|
||||
master_layout.addWidget(self.sub_controls, 1, 0)
|
||||
|
||||
self.position_label = QLabel("0:00")
|
||||
self.position_label.setStyleSheet("color: #ffffff;")
|
||||
master_layout.addWidget(self.position_label, 1, 1)
|
||||
master_layout.setAlignment(self.position_label, Qt.AlignmentFlag.AlignRight)
|
||||
self.position_label.setStyleSheet("color: white;")
|
||||
sub_layout.addWidget(self.position_label)
|
||||
root_layout.setAlignment(self.position_label, Qt.AlignmentFlag.AlignRight)
|
||||
self.position_label.hide()
|
||||
|
||||
self.scene().addWidget(self.master_controls)
|
||||
root_layout.addWidget(self.sub_controls)
|
||||
self.scene().addWidget(self.controls)
|
||||
|
||||
self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
|
||||
autoplay_action = QAction(Translations["media_player.autoplay"], self)
|
||||
@@ -263,7 +234,6 @@ class MediaPlayer(QGraphicsView):
|
||||
self.loop = loop_action
|
||||
self.toggle_loop()
|
||||
|
||||
# start the player muted
|
||||
self.player.audioOutput().setMuted(True)
|
||||
|
||||
def set_video_output(self, video: QGraphicsVideoItem):
|
||||
@@ -277,7 +247,6 @@ class MediaPlayer(QGraphicsView):
|
||||
def toggle_loop(self) -> None:
|
||||
self.driver.settings.loop = self.loop.isChecked()
|
||||
self.driver.settings.save()
|
||||
|
||||
self.player.setLoops(-1 if self.driver.settings.loop else 1)
|
||||
|
||||
def apply_rounded_corners(self) -> None:
|
||||
@@ -307,26 +276,31 @@ class MediaPlayer(QGraphicsView):
|
||||
Args:
|
||||
opacity(int): The opacity value, from 0-255.
|
||||
"""
|
||||
self.tint.setBrush(QBrush(QColor(0, 0, 0, opacity)))
|
||||
gradient = QLinearGradient(0, 0, 0, self.height())
|
||||
gradient.setColorAt(0.8, QColor(0, 0, 0, 0))
|
||||
gradient.setColorAt(1, QColor(0, 0, 0, opacity))
|
||||
self.tint.setBrush(QBrush(gradient))
|
||||
|
||||
@override
|
||||
def underMouse(self) -> bool: # noqa: N802
|
||||
self.animation.setStartValue(self.tint.brush().color().alpha())
|
||||
self.animation.setEndValue(100)
|
||||
self.animation.setDuration(250)
|
||||
self.animation.setStartValue(0)
|
||||
self.animation.setEndValue(160)
|
||||
self.animation.setDuration(125)
|
||||
self.animation.start()
|
||||
self.pslider.show()
|
||||
self.timeline_slider.show()
|
||||
self.play_pause.show()
|
||||
self.mute_unmute.show()
|
||||
self.position_label.show()
|
||||
|
||||
return super().underMouse()
|
||||
|
||||
@override
|
||||
def releaseMouse(self) -> None: # noqa: N802
|
||||
self.animation.setStartValue(self.tint.brush().color().alpha())
|
||||
self.animation.setStartValue(160)
|
||||
self.animation.setEndValue(0)
|
||||
self.animation.setDuration(500)
|
||||
self.animation.setDuration(125)
|
||||
self.animation.start()
|
||||
self.pslider.hide()
|
||||
self.timeline_slider.hide()
|
||||
self.play_pause.hide()
|
||||
self.mute_unmute.hide()
|
||||
self.volume_slider.hide()
|
||||
@@ -334,6 +308,14 @@ class MediaPlayer(QGraphicsView):
|
||||
|
||||
return super().releaseMouse()
|
||||
|
||||
@override
|
||||
def mousePressEvent(self, event: QMouseEvent) -> None:
|
||||
# Pause media if background is clicked, with buffer around controls
|
||||
buffer: int = 6
|
||||
if event.y() < (self.height() - self.controls.height() - buffer):
|
||||
self.toggle_play()
|
||||
return super().mousePressEvent(event)
|
||||
|
||||
@override
|
||||
def eventFilter(self, arg__1: QObject, arg__2: QEvent) -> bool:
|
||||
"""Manage events for the media player."""
|
||||
@@ -345,8 +327,6 @@ class MediaPlayer(QGraphicsView):
|
||||
self.toggle_play()
|
||||
elif arg__1 == self.mute_unmute:
|
||||
self.toggle_mute()
|
||||
else:
|
||||
self.toggle_play()
|
||||
elif arg__2.type() is QEvent.Type.Enter:
|
||||
if arg__1 == self or arg__1 == self.video_preview:
|
||||
self.underMouse()
|
||||
@@ -369,9 +349,7 @@ class MediaPlayer(QGraphicsView):
|
||||
ms: Time in ms
|
||||
|
||||
Returns:
|
||||
A formatted time:
|
||||
|
||||
"1:43"
|
||||
A formatted time: "1:43"
|
||||
|
||||
The formatted time will only include the hour if
|
||||
the provided time is at least 60 minutes.
|
||||
@@ -441,23 +419,27 @@ class MediaPlayer(QGraphicsView):
|
||||
self.mute_unmute.load(icon)
|
||||
|
||||
def slider_value_changed(self, value: int) -> None:
|
||||
if self.timeline_slider.isSliderDown():
|
||||
self.player.setPosition(value)
|
||||
self.player.setPlaybackRate(0.0001)
|
||||
|
||||
current = self.format_time(value)
|
||||
duration = self.format_time(self.player.duration())
|
||||
self.position_label.setText(f"{current} / {duration}")
|
||||
|
||||
def slider_released(self) -> None:
|
||||
was_playing = self.player.isPlaying()
|
||||
self.player.setPosition(self.pslider.value())
|
||||
self.player.setPosition(self.timeline_slider.value())
|
||||
self.player.setPlaybackRate(1) # Restore from slider_value_changed()
|
||||
|
||||
# Setting position causes the player to start playing again.
|
||||
# We should reset back to initial state.
|
||||
# Setting position causes the player to start playing again
|
||||
if not was_playing:
|
||||
self.player.pause()
|
||||
|
||||
def player_position_changed(self, position: int) -> None:
|
||||
if not self.pslider.isSliderDown():
|
||||
# User isn't using the slider, so update position in widgets.
|
||||
self.pslider.setValue(position)
|
||||
if not self.timeline_slider.isSliderDown():
|
||||
# User isn't using the slider, so update position in widgets
|
||||
self.timeline_slider.setValue(position)
|
||||
current = self.format_time(self.player.position())
|
||||
duration = self.format_time(self.player.duration())
|
||||
self.position_label.setText(f"{current} / {duration}")
|
||||
@@ -465,8 +447,8 @@ class MediaPlayer(QGraphicsView):
|
||||
def media_status_changed(self, status: QMediaPlayer.MediaStatus) -> None:
|
||||
# We can only set the slider duration once we know the size of the media
|
||||
if status == QMediaPlayer.MediaStatus.LoadedMedia and self.filepath is not None:
|
||||
self.pslider.setMinimum(0)
|
||||
self.pslider.setMaximum(self.player.duration())
|
||||
self.timeline_slider.setMinimum(0)
|
||||
self.timeline_slider.setMaximum(self.player.duration())
|
||||
|
||||
current = self.format_time(self.player.position())
|
||||
duration = self.format_time(self.player.duration())
|
||||
@@ -475,24 +457,15 @@ class MediaPlayer(QGraphicsView):
|
||||
def _update_controls(self, size: QSize) -> None:
|
||||
self.scene().setSceneRect(0, 0, size.width(), size.height())
|
||||
|
||||
# occupy entire scene width
|
||||
self.master_controls.setMinimumWidth(size.width())
|
||||
self.master_controls.setMaximumWidth(size.width())
|
||||
# Occupy entire scene width
|
||||
self.controls.setMinimumWidth(size.width())
|
||||
self.controls.setMaximumWidth(size.width())
|
||||
|
||||
self.master_controls.move(0, int(self.scene().height() - self.master_controls.height()))
|
||||
self.controls.move(0, int(self.scene().height() - self.controls.height()))
|
||||
|
||||
ps_w = self.master_controls.width() - 5
|
||||
self.pslider.setMinimumWidth(ps_w)
|
||||
self.pslider.setMaximumWidth(ps_w)
|
||||
|
||||
# Changing the orientation of the volume slider to
|
||||
# make it easier to use in smaller sizes.
|
||||
orientation = self.volume_slider.orientation()
|
||||
if size.width() <= 175 and orientation is Qt.Orientation.Horizontal:
|
||||
self.volume_slider.setOrientation(Qt.Orientation.Vertical)
|
||||
self.volume_slider.setMaximumHeight(30)
|
||||
elif size.width() > 175 and orientation is Qt.Orientation.Vertical:
|
||||
self.volume_slider.setOrientation(Qt.Orientation.Horizontal)
|
||||
ps_w = self.controls.width() - 5
|
||||
self.timeline_slider.setMinimumWidth(ps_w)
|
||||
self.timeline_slider.setMaximumWidth(ps_w)
|
||||
|
||||
if self.video_preview:
|
||||
self.video_preview.setSize(self.size())
|
||||
@@ -514,12 +487,3 @@ class VideoPreview(QGraphicsVideoItem):
|
||||
@override
|
||||
def boundingRect(self):
|
||||
return QRectF(0, 0, self.size().width(), self.size().height())
|
||||
|
||||
@override
|
||||
def paint(self, painter, option, widget=None) -> None:
|
||||
# painter.brush().setColor(QColor(0, 0, 0, 255))
|
||||
# You can set any shape you want here.
|
||||
# RoundedRect is the standard rectangle with rounded corners.
|
||||
# With 2nd and 3rd parameter you can tweak the curve until you get what you expect
|
||||
|
||||
super().paint(painter, option, widget)
|
||||
|
||||
Reference in New Issue
Block a user