class YPictureBubble(QLabel): def __init__(self, widget): super().__init__(widget) self.parent_widget = widget self.setScaledContents(True) def setPicture(self, image_name): self.filename = image_name max_width = 300 is_gif = False if image_name[-3:].lower() == 'gif': self.gif = QMovie(image_name) if self.gif.isValid(): is_gif = True self.setMovie(self.gif) self.gif.start() g = self.gif.currentImage() w, h = (g.width(), g.height()) if not is_gif: im = Image.open(image_name) w, h = im.size self.setPixmap(im.toqpixmap()) if w >= h and w > max_width: ratio = max_width / w elif h > w and h > max_width: ratio = max_width / h else: ratio = 1 w, h = int(w * ratio), int(h * ratio) self.resize(w, h)
def _load(self, path: str, keep_zoom: bool): """Load proper displayable QWidget for a path. This reads the image using QImageReader and then emits the appropriate *_loaded signal to tell the image to display a new object. """ try: reader = imagereader.get_reader(path) except ValueError as e: log.error(str(e)) return # SVG if reader.is_vectorgraphic and QtSvg is not None: # Do not store image and only emit with the path as the # VectorGraphic widget needs the path in the constructor api.signals.svg_loaded.emit(path, keep_zoom) self._edit_handler.clear() # Gif elif reader.is_animation: movie = QMovie(path) if not movie.isValid() or movie.frameCount() == 0: log.error("Error reading animation %s: invalid data", path) return api.signals.movie_loaded.emit(movie, keep_zoom) self._edit_handler.clear() # Regular image else: try: pixmap = reader.get_pixmap() except ValueError as e: log.error("%s", e) return self._edit_handler.pixmap = pixmap api.signals.pixmap_loaded.emit(pixmap, keep_zoom) self._path = path
def getQMovie(self): """ Returns: Qmovie object containing the animation. """ if not self.contents == "animation": return None if self.qdata is None and not self.error: root, file = self.path img = QMovie(os.path.join(root, file)) if not img.isValid(): self.error = "failed to load: " + img.lastError() return None img.setScaledSize(QSize(*self.fullsize)) self.qdata = img return self.qdata
def _load(self, path: str, reload_only: bool): """Load proper displayable QWidget for a path. This reads the image using QImageReader and then emits the appropriate *_loaded signal to tell the image to display a new object. """ # Pass file format explicitly as imghdr does a much better job at this than the # file name based approach of QImageReader file_format = files.imghdr.what(path) if file_format is None: log.error("%s is not a valid image", path) return reader = QImageReader(path, file_format.encode("utf-8")) reader.setAutoTransform(True) # Automatically apply exif orientation if not reader.canRead(): log.error("Cannot read image %s", path) return # SVG if file_format == "svg" and QSvgWidget: # Do not store image and only emit with the path as the # VectorGraphic widget needs the path in the constructor self.original = None api.signals.svg_loaded.emit(path, reload_only) self._image_type = ImageType.Svg # Gif elif reader.supportsAnimation(): movie = QMovie(path) if not movie.isValid() or movie.frameCount() == 0: log.error("Error reading animation %s: invalid data", path) return self.original = movie api.signals.movie_loaded.emit(self.current, reload_only) self._image_type = ImageType.Movie # Regular image else: pixmap = QPixmap.fromImageReader(reader) if reader.error(): log.error("Error reading image %s: %s", path, reader.errorString()) return self.original = pixmap api.signals.pixmap_loaded.emit(self.current, reload_only) self._image_type = ImageType.Pixmap self._path = path
class MoviePlayer(QWidget): def __init__(self, parent=None): super(MoviePlayer, self).__init__(parent) self.movie = QMovie(self) self.movie.setCacheMode(QMovie.CacheAll) self.movieLabel = QLabel("No movie loaded") self.movieLabel.setAlignment(Qt.AlignCenter) self.movieLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.movieLabel.setBackgroundRole(QPalette.Dark) self.movieLabel.setAutoFillBackground(True) self.currentMovieDirectory = '' self.createControls() self.createButtons() self.movie.frameChanged.connect(self.updateFrameSlider) self.movie.stateChanged.connect(self.updateButtons) self.fitCheckBox.clicked.connect(self.fitToWindow) self.frameSlider.valueChanged.connect(self.goToFrame) self.speedSpinBox.valueChanged.connect(self.movie.setSpeed) mainLayout = QVBoxLayout() mainLayout.addWidget(self.movieLabel) mainLayout.addLayout(self.controlsLayout) mainLayout.addLayout(self.buttonsLayout) self.setLayout(mainLayout) self.updateFrameSlider() self.updateButtons() self.setWindowTitle("Movie Player") self.resize(400, 400) def open(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open a Movie", self.currentMovieDirectory) if fileName: self.openFile(fileName) def openFile(self, fileName): self.currentMovieDirectory = QFileInfo(fileName).path() self.movie.stop() self.movieLabel.setMovie(self.movie) self.movie.setFileName(fileName) self.movie.start() self.updateFrameSlider() self.updateButtons() def goToFrame(self, frame): self.movie.jumpToFrame(frame) def fitToWindow(self): self.movieLabel.setScaledContents(self.fitCheckBox.isChecked()) def updateFrameSlider(self): hasFrames = (self.movie.currentFrameNumber() >= 0) if hasFrames: if self.movie.frameCount() > 0: self.frameSlider.setMaximum(self.movie.frameCount() - 1) elif self.movie.currentFrameNumber() > self.frameSlider.maximum(): self.frameSlider.setMaximum(self.movie.currentFrameNumber()) self.frameSlider.setValue(self.movie.currentFrameNumber()) else: self.frameSlider.setMaximum(0) self.frameLabel.setEnabled(hasFrames) self.frameSlider.setEnabled(hasFrames) def updateButtons(self): state = self.movie.state() self.playButton.setEnabled(self.movie.isValid() and self.movie.frameCount() != 1 and state == QMovie.NotRunning) self.pauseButton.setEnabled(state != QMovie.NotRunning) self.pauseButton.setChecked(state == QMovie.Paused) self.stopButton.setEnabled(state != QMovie.NotRunning) def createControls(self): self.fitCheckBox = QCheckBox("Fit to Window") self.frameLabel = QLabel("Current frame:") self.frameSlider = QSlider(Qt.Horizontal) self.frameSlider.setTickPosition(QSlider.TicksBelow) self.frameSlider.setTickInterval(10) speedLabel = QLabel("Speed:") self.speedSpinBox = QSpinBox() self.speedSpinBox.setRange(1, 9999) self.speedSpinBox.setValue(100) self.speedSpinBox.setSuffix("%") self.controlsLayout = QGridLayout() self.controlsLayout.addWidget(self.fitCheckBox, 0, 0, 1, 2) self.controlsLayout.addWidget(self.frameLabel, 1, 0) self.controlsLayout.addWidget(self.frameSlider, 1, 1, 1, 2) self.controlsLayout.addWidget(speedLabel, 2, 0) self.controlsLayout.addWidget(self.speedSpinBox, 2, 1) def createButtons(self): iconSize = QSize(36, 36) openButton = QToolButton() openButton.setIcon(self.style().standardIcon( QStyle.SP_DialogOpenButton)) openButton.setIconSize(iconSize) openButton.setToolTip("Open File") openButton.clicked.connect(self.open) self.playButton = QToolButton() self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.setIconSize(iconSize) self.playButton.setToolTip("Play") self.playButton.clicked.connect(self.movie.start) self.pauseButton = QToolButton() self.pauseButton.setCheckable(True) self.pauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.pauseButton.setIconSize(iconSize) self.pauseButton.setToolTip("Pause") self.pauseButton.clicked.connect(self.movie.setPaused) self.stopButton = QToolButton() self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopButton.setIconSize(iconSize) self.stopButton.setToolTip("Stop") self.stopButton.clicked.connect(self.movie.stop) quitButton = QToolButton() quitButton.setIcon(self.style().standardIcon( QStyle.SP_DialogCloseButton)) quitButton.setIconSize(iconSize) quitButton.setToolTip("Quit") quitButton.clicked.connect(self.close) self.buttonsLayout = QHBoxLayout() self.buttonsLayout.addStretch() self.buttonsLayout.addWidget(openButton) self.buttonsLayout.addWidget(self.playButton) self.buttonsLayout.addWidget(self.pauseButton) self.buttonsLayout.addWidget(self.stopButton) self.buttonsLayout.addWidget(quitButton) self.buttonsLayout.addStretch()
class LoginDialog(QDialog): login_signal = pyqtSignal(str) def __init__(self): super().__init__() self.initUI() def initUI(self): self.setFixedSize(350, 250) self.setWindowIcon(QIcon('app.ico')) self.setWindowTitle('登录') self.setWindowFlags(Qt.FramelessWindowHint) self.picLabel = QLabel('', self) self.picLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.picLabel.setGeometry(0, 0, 350, 140) self.movie = QMovie('杜甫.gif') if self.movie.isValid(): self.picLabel.setMovie(self.movie) self.picLabel.setScaledContents(True) self.movie.start() else: self.picLabel.setPixmap(QPixmap('.\CDUT_pic_1.jpeg')) self.pwdEdit = QLineEdit(self) self.pwdEdit.setGeometry(90, 160, 200, 30) self.pwdEdit.setPlaceholderText('请输入密钥') self.pwdEdit.setEchoMode(QLineEdit.Password) self.submitBtn = QPushButton('登录', self) self.submitBtn.setGeometry(106, 210, 60, 30) self.submitBtn.setStyleSheet("QPushButton{color:black}" "QPushButton:hover{color:red}" "QPushButton{background-color:lightgreen}" "QPushButton{border:2px}" "QPushButton{border-radius:15px}" "QPushButton{padding:2px 4px}") self.closeBtn = QPushButton('关闭', self) self.closeBtn.setGeometry(215, 210, 60, 30) self.closeBtn.setStyleSheet("QPushButton{color:black}" "QPushButton:hover{color:red}" "QPushButton{background-color:lightgreen}" "QPushButton{border:2px}" "QPushButton{border-radius:15px}" "QPushButton{padding:2px 4px}") self.submitBtn.clicked.connect(self.submitLogin) self.closeBtn.clicked.connect(self.closeLogin) self.show() def submitLogin(self): self.text = self.pwdEdit.text() if self.text not in LOGIN_PWDS: msgBox = QMessageBox() msgBox.setWindowOpacity(0.8) msgBox.setWindowTitle('错误') msgBox.setWindowIcon(QIcon('app.ico')) msgBox.setIcon(QMessageBox.Critical) msgBox.setText('密钥输入错误!') msgBox.setInformativeText( '请联系QQ:<span style="color: red">1792575431</span>') msgBox.addButton('确定', QMessageBox.AcceptRole) msgBox.exec_() self.pwdEdit.clear() self.login_signal.emit('fail') else: self.login_signal.emit('success') self.close() def closeLogin(self): self.close() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.m_flag = True self.m_Position = event.globalPos() - self.pos() event.accept() def mouseMoveEvent(self, QMouseEvent): if Qt.LeftButton and self.m_flag: self.move(QMouseEvent.globalPos() - self.m_Position) QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): self.m_flag = False
class CAvatar(QWidget): Circle = 0 # 圆圈 Rectangle = 1 # 圆角矩形 SizeLarge = QSize(128, 128) SizeMedium = QSize(64, 64) SizeSmall = QSize(32, 32) StartAngle = 0 # 起始旋转角度 EndAngle = 360 # 结束旋转角度 def __init__(self, *args, shape=0, url='', cacheDir=False, size=QSize(64, 64), animation=False, **kwargs): super(CAvatar, self).__init__(*args, **kwargs) self.url = '' self._angle = 0 # 角度 self.pradius = 0 # 加载进度条半径 self.animation = animation # 是否使用动画 self._movie = None # 动态图 self._pixmap = QPixmap() # 图片对象 self.pixmap = QPixmap() # 被绘制的对象 self.isGif = url.endswith('.gif') # 进度动画定时器 self.loadingTimer = QTimer(self, timeout=self.onLoading) # 旋转动画 self.rotateAnimation = QPropertyAnimation(self, b'angle', self, loopCount=1) self.setShape(shape) self.setCacheDir(cacheDir) self.setSize(size) self.setUrl(url) def paintEvent(self, event): super(CAvatar, self).paintEvent(event) # 画笔 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.HighQualityAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) # 绘制 path = QPainterPath() diameter = min(self.width(), self.height()) if self.shape == self.Circle: radius = int(diameter / 2) elif self.shape == self.Rectangle: radius = 4 halfW = self.width() / 2 halfH = self.height() / 2 painter.translate(halfW, halfH) path.addRoundedRect(QRectF(-halfW, -halfH, diameter, diameter), radius, radius) painter.setClipPath(path) # 如果是动画效果 if self.rotateAnimation.state() == QPropertyAnimation.Running: painter.rotate(self._angle) # 旋转 painter.drawPixmap( QPointF(-self.pixmap.width() / 2, -self.pixmap.height() / 2), self.pixmap) else: painter.drawPixmap(-int(halfW), -int(halfH), self.pixmap) # 如果在加载 if self.loadingTimer.isActive(): diameter = 2 * self.pradius painter.setBrush( QColor(45, 140, 240, (1 - self.pradius / 10) * 255)) painter.setPen(Qt.NoPen) painter.drawRoundedRect( QRectF(-self.pradius, -self.pradius, diameter, diameter), self.pradius, self.pradius) def enterEvent(self, event): """鼠标进入动画 :param event: """ if not (self.animation and not self.isGif): return self.rotateAnimation.stop() cv = self.rotateAnimation.currentValue() or self.StartAngle self.rotateAnimation.setDuration(540 if cv == 0 else int(cv / self.EndAngle * 540)) self.rotateAnimation.setStartValue(cv) self.rotateAnimation.setEndValue(self.EndAngle) self.rotateAnimation.start() def leaveEvent(self, event): """鼠标离开动画 :param event: """ if not (self.animation and not self.isGif): return self.rotateAnimation.stop() cv = self.rotateAnimation.currentValue() or self.EndAngle self.rotateAnimation.setDuration(int(cv / self.EndAngle * 540)) self.rotateAnimation.setStartValue(cv) self.rotateAnimation.setEndValue(self.StartAngle) self.rotateAnimation.start() def onLoading(self): """更新进度动画 """ if self.loadingTimer.isActive(): if self.pradius > 9: self.pradius = 0 self.pradius += 1 else: self.pradius = 0 self.update() def onFinished(self): """图片下载完成 """ self.loadingTimer.stop() self.pradius = 0 reply = self.sender() if self.isGif: self._movie = QMovie(reply, b'gif', self) if self._movie.isValid(): self._movie.frameChanged.connect(self._resizeGifPixmap) self._movie.start() else: data = reply.readAll().data() reply.deleteLater() del reply self._pixmap.loadFromData(data) if self._pixmap.isNull(): self._pixmap = QPixmap(self.size()) self._pixmap.fill(QColor(204, 204, 204)) self._resizePixmap() def onError(self, code): """下载出错了 :param code: """ self._pixmap = QPixmap(self.size()) self._pixmap.fill(QColor(204, 204, 204)) self._resizePixmap() def refresh(self): """强制刷新 """ self._get(self.url) def isLoading(self): """判断是否正在加载 """ return self.loadingTimer.isActive() def setShape(self, shape): """设置形状 :param shape: 0=圆形, 1=圆角矩形 """ self.shape = shape def setUrl(self, url): """设置url,可以是本地路径,也可以是网络地址 :param url: """ self.url = url self._get(url) def setCacheDir(self, cacheDir=''): """设置本地缓存路径 :param cacheDir: """ self.cacheDir = cacheDir self._initNetWork() def setSize(self, size): """设置固定尺寸 :param size: """ if not isinstance(size, QSize): size = self.SizeMedium self.setMinimumSize(size) self.setMaximumSize(size) self._resizePixmap() @pyqtProperty(int) def angle(self): return self._angle @angle.setter def angle(self, value): self._angle = value self.update() def _resizePixmap(self): """缩放图片 """ if not self._pixmap.isNull(): self.pixmap = self._pixmap.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.update() def _resizeGifPixmap(self, _): """缩放动画图片 """ if self._movie: self.pixmap = self._movie.currentPixmap().scaled( self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.update() def _initNetWork(self): """初始化异步网络库 """ if not hasattr(qApp, '_network'): network = QNetworkAccessManager(self.window()) setattr(qApp, '_network', network) # 是否需要设置缓存 if self.cacheDir and not qApp._network.cache(): cache = QNetworkDiskCache(self.window()) cache.setCacheDirectory(self.cacheDir) qApp._network.setCache(cache) def _get(self, url): """设置图片或者请求网络图片 :param url: """ if not url: self.onError('') return if url.startswith('http') and not self.loadingTimer.isActive(): url = QUrl(url) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar') request.setRawHeader(b'Author', b'Irony') request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) if qApp._network.cache(): request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferNetwork) request.setAttribute(QNetworkRequest.CacheSaveControlAttribute, True) reply = qApp._network.get(request) self.pradius = 0 self.loadingTimer.start(50) # 显示进度动画 reply.finished.connect(self.onFinished) reply.error.connect(self.onError) return self.pradius = 0 if os.path.exists(url) and os.path.isfile(url): if self.isGif: self._movie = QMovie(url, parent=self) if self._movie.isValid(): self._movie.frameChanged.connect(self._resizeGifPixmap) self._movie.start() else: self._pixmap = QPixmap(url) self._resizePixmap() else: self.onError('')
class MoviePlayer(QWidget): def __init__(self, parent=None): super(MoviePlayer, self).__init__(parent) self.movie = QMovie(self) self.movie.setCacheMode(QMovie.CacheAll) self.movieLabel = QLabel("No movie loaded") self.movieLabel.setAlignment(Qt.AlignCenter) self.movieLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.movieLabel.setBackgroundRole(QPalette.Dark) self.movieLabel.setAutoFillBackground(True) self.currentMovieDirectory = '' self.createControls() self.createButtons() self.movie.frameChanged.connect(self.updateFrameSlider) self.movie.stateChanged.connect(self.updateButtons) self.fitCheckBox.clicked.connect(self.fitToWindow) self.frameSlider.valueChanged.connect(self.goToFrame) self.speedSpinBox.valueChanged.connect(self.movie.setSpeed) mainLayout = QVBoxLayout() mainLayout.addWidget(self.movieLabel) mainLayout.addLayout(self.controlsLayout) mainLayout.addLayout(self.buttonsLayout) self.setLayout(mainLayout) self.updateFrameSlider() self.updateButtons() self.setWindowTitle("Movie Player") self.resize(400, 400) def open(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open a Movie", self.currentMovieDirectory) if fileName: self.openFile(fileName) def openFile(self, fileName): self.currentMovieDirectory = QFileInfo(fileName).path() self.movie.stop() self.movieLabel.setMovie(self.movie) self.movie.setFileName(fileName) self.movie.start() self.updateFrameSlider(); self.updateButtons(); def goToFrame(self, frame): self.movie.jumpToFrame(frame) def fitToWindow(self): self.movieLabel.setScaledContents(self.fitCheckBox.isChecked()) def updateFrameSlider(self): hasFrames = (self.movie.currentFrameNumber() >= 0) if hasFrames: if self.movie.frameCount() > 0: self.frameSlider.setMaximum(self.movie.frameCount() - 1) elif self.movie.currentFrameNumber() > self.frameSlider.maximum(): self.frameSlider.setMaximum(self.movie.currentFrameNumber()) self.frameSlider.setValue(self.movie.currentFrameNumber()) else: self.frameSlider.setMaximum(0) self.frameLabel.setEnabled(hasFrames) self.frameSlider.setEnabled(hasFrames) def updateButtons(self): state = self.movie.state() self.playButton.setEnabled(self.movie.isValid() and self.movie.frameCount() != 1 and state == QMovie.NotRunning) self.pauseButton.setEnabled(state != QMovie.NotRunning) self.pauseButton.setChecked(state == QMovie.Paused) self.stopButton.setEnabled(state != QMovie.NotRunning) def createControls(self): self.fitCheckBox = QCheckBox("Fit to Window") self.frameLabel = QLabel("Current frame:") self.frameSlider = QSlider(Qt.Horizontal) self.frameSlider.setTickPosition(QSlider.TicksBelow) self.frameSlider.setTickInterval(10) speedLabel = QLabel("Speed:") self.speedSpinBox = QSpinBox() self.speedSpinBox.setRange(1, 9999) self.speedSpinBox.setValue(100) self.speedSpinBox.setSuffix("%") self.controlsLayout = QGridLayout() self.controlsLayout.addWidget(self.fitCheckBox, 0, 0, 1, 2) self.controlsLayout.addWidget(self.frameLabel, 1, 0) self.controlsLayout.addWidget(self.frameSlider, 1, 1, 1, 2) self.controlsLayout.addWidget(speedLabel, 2, 0) self.controlsLayout.addWidget(self.speedSpinBox, 2, 1) def createButtons(self): iconSize = QSize(36, 36) openButton = QToolButton() openButton.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton)) openButton.setIconSize(iconSize) openButton.setToolTip("Open File") openButton.clicked.connect(self.open) self.playButton = QToolButton() self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.setIconSize(iconSize) self.playButton.setToolTip("Play") self.playButton.clicked.connect(self.movie.start) self.pauseButton = QToolButton() self.pauseButton.setCheckable(True) self.pauseButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) self.pauseButton.setIconSize(iconSize) self.pauseButton.setToolTip("Pause") self.pauseButton.clicked.connect(self.movie.setPaused) self.stopButton = QToolButton() self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopButton.setIconSize(iconSize) self.stopButton.setToolTip("Stop") self.stopButton.clicked.connect(self.movie.stop) quitButton = QToolButton() quitButton.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton)) quitButton.setIconSize(iconSize) quitButton.setToolTip("Quit") quitButton.clicked.connect(self.close) self.buttonsLayout = QHBoxLayout() self.buttonsLayout.addStretch() self.buttonsLayout.addWidget(openButton) self.buttonsLayout.addWidget(self.playButton) self.buttonsLayout.addWidget(self.pauseButton) self.buttonsLayout.addWidget(self.stopButton) self.buttonsLayout.addWidget(quitButton) self.buttonsLayout.addStretch()
class SlideshowMediaWindow(QDialog): def __init__(self, parent, area=None, *args, **kwargs): "parent: parent widget" "area: top-left-x(to screen), top-left-y(to screen), width, height" super(SlideshowMediaWindow, self).__init__(parent, *args, **kwargs) self.setWindowTitle("Slideshow External Media Window") sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setSizePolicy(sizePolicy) self.setAttribute(Qt.WA_DeleteOnClose, on=True) self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint) self.setSizeGripEnabled(True) self.layout = QVBoxLayout() self.media_container = QLabel(self) self.media_container.setAttribute(Qt.WA_NativeWindow, on=True) # self.media_container.setFrameShape(QFrame.NoFrame) sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) sizePolicy.setHeightForWidth( self.media_container.sizePolicy().hasHeightForWidth()) self.media_container.setSizePolicy(sizePolicy) self.media_container.setAlignment(Qt.AlignCenter) self.media_container.setStyleSheet("background-color: black;") self.layout.addWidget(self.media_container) self.layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.layout) self.area = area if any(area): self.resize(area[2], area[3]) self.move(area[0], area[1]) else: self.resize(400, 300) self.mouse_pos = [0, 0] self.allow_resize_mouse_press = False self.pic_image = None self.media_container.setScaledContents(False) self.media_container.original_resizeEvent = self.media_container.resizeEvent def media_container_resizeEvent(event): if self.pic_image and isinstance(self.pic_image, QPixmap): if self.pic_image.width() > self.media_container.width() - 2 \ and self.pic_image.height() > self.media_container.height() - 2: target_width = self.media_container.width() - 2 target_height = self.media_container.height() - 2 else: target_width = self.pic_image.width() target_height = self.pic_image.height() scaled_image = self.pic_image.scaled( target_width, target_height, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.FastTransformation) self.media_container.setPixmap(scaled_image) elif self.pic_image and isinstance(self.pic_image, QMovie): if self.pic_image.original_size.width() > self.media_container.width() - 2 \ and self.pic_image.original_size.height() > self.media_container.height() - 2: target_width = self.media_container.width() - 2 target_height = self.media_container.height() - 2 else: target_width = self.pic_image.original_size.width() target_height = self.pic_image.original_size.height() scaled_size = self.pic_image.original_size.scaled( target_width, target_height, Qt.KeepAspectRatio) self.pic_image.setScaledSize(scaled_size) else: self.media_container.original_resizeEvent(event) self.media_container.resizeEvent = media_container_resizeEvent self.show() self.last_media_path = "" self.media_show_completed_notice = None # this should be a function to be called like self.stop_media_show() self.stop_media_show = lambda: None self.gif_completed_notice = threading.Event() def show_video(self, path): self.stop_media_show() self.media_container.clear() # some say the winId change all the time...so... mplayer_extended.setup(int(self.media_container.winId())) self.media_show_completed_notice = mplayer_extended.play(path) logger.debug("ext-media-win showed video: %s" % path) self.last_media_path = path self.stop_media_show = mplayer_extended.stop def show_pic(self, path): self.stop_media_show() self.media_container.clear() if not path.lower().endswith(".gif"): self.pic_image = QPixmap(path) if self.pic_image.width() > self.media_container.width() - 2 \ and self.pic_image.height() > self.media_container.height() - 2: target_width = self.media_container.width() - 2 target_height = self.media_container.height() - 2 else: target_width = self.pic_image.width() target_height = self.pic_image.height() scaled_image = self.pic_image.scaled( target_width, target_height, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.media_container.setPixmap(scaled_image) logger.debug("ext-media-win showed pic: %s" % path) self.stop_media_show = lambda: None self.media_show_completed_notice = None else: self.last_media_path = path self.pic_image = QMovie(path, QByteArray(), self) if not self.pic_image.isValid(): self.media_show_completed_notice = None return self.pic_image.setCacheMode(QMovie.CacheAll) self.pic_image.jumpToNextFrame() self.pic_image.original_size = self.pic_image.currentPixmap().size( ) if self.pic_image.original_size.width() > self.media_container.width() - 2 \ and self.pic_image.original_size.height() > self.media_container.height() - 2: target_width = self.media_container.width() - 2 target_height = self.media_container.height() - 2 else: target_width = self.pic_image.original_size.width() target_height = self.pic_image.original_size.height() scaled_size = self.pic_image.original_size.scaled( target_width, target_height, Qt.KeepAspectRatio) self.pic_image.setScaledSize(scaled_size) self.pic_image.setSpeed(100) self.media_container.setMovie(self.pic_image) self.media_show_completed_notice = self.gif_completed_notice self.media_show_completed_notice.clear() def frameChanged_Handler(frameNumber): if frameNumber >= self.pic_image.frameCount() - 1: self.pic_image.stop() self.media_show_completed_notice.set() self.pic_image.frameChanged.connect(frameChanged_Handler) self.pic_image.start() logger.debug("ext-media-win showed gif: %s" % path) def stop_gif(): try: self.pic_image.stop() self.media_show_completed_notice.set() except Exception: pass self.stop_media_show = stop_gif def contextMenuEvent(self, event): m = QMenu(self) item = m.addAction("Stop Media") item.triggered.connect(self.stop_media_show) item = m.addAction("Exit Media Window") item.triggered.connect(self.close) m.popup(QCursor.pos()) def mousePressEvent(self, event): self.mouse_pos[0] = event.x() self.mouse_pos[1] = event.y() if event.globalX() < self.x() + self.frameGeometry().width() - 20 \ or event.globalY() < self.y() + self.frameGeometry().height() - 20: self.allow_resize_mouse_press = True else: self.allow_resize_mouse_press = True super().mousePressEvent(event) def mouseReleaseEvent(self, event): self.allow_resize_mouse_press = False super().mouseReleaseEvent(event) def mouseMoveEvent(self, event): if self.allow_resize_mouse_press: self.move(event.globalX() - self.mouse_pos[0], event.globalY() - self.mouse_pos[1]) super().mouseMoveEvent(event) def mouseDoubleClickEvent(self, event): self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) super().mouseDoubleClickEvent(event) def keyPressEvent(self, event): if event.key() == Qt.Key_F11: self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) else: super().keyPressEvent(event) def closeEvent(self, event): self.stop_media_show() self.area[0] = self.x() self.area[1] = self.y() self.area[2] = self.width() self.area[3] = self.height() event.accept()