サムネをオサレにボタン化する方法!!

takkun
どうも!たっくんです。

サムネにマウスカーソルを重ねると、再生ボタンがオーバーレイされて、クリックすると再生できる!っという仕組って結構見ますよね!

これを、PySideでやる方法をご紹介したいと思います!(`・ω・´)ゞ

リソース

カスタムウィジェットの作成にあたり、サムネは「160 x 90」の画像オーバーレイする再生ボタンを「64 x 64」の画像で用意しました!

サムネ 再生ボタン

オーバーレイする再生ボタンは、半透明もOKです(*´ω`*)b

クラスの骨格

QLabel」を継承してクラスを作っていきます!サムネをクリックした時のシグナル、オーバーレイする画像の設定をクラス変数で定義します。

from PySide import QtCore, QtGui

class PlaybackLabel(QtGui.QLabel):

	iconClicked = QtCore.Signal()
	overlayIcon = QtGui.QPixmap(r'D:/playIcon.png')

__init__の定義

__init__」では、サムネのファイルパスと、親のWidgetを指定できるようにします。合わせて、マウスカーソルがHover状態であるか管理するためのインスタンス変数を用意し、自身にQPixmapを設定してサムネを表示できるようにします。

from PySide import QtCore, QtGui

class PlaybackLabel(QtGui.QLabel):

	iconClicked = QtCore.Signal()
	overlayIcon = QtGui.QPixmap(r'D:/playIcon.png')
	
	def __init__(self, filename=None, parent=None):
		super(PlaybackLabel, self).__init__(parent)
		self.__isHover = False
		self.setPixmap(QtGui.QPixmap(filename))

PySideのUIに画像を表示する方法!!

2017.08.16

Hover状態の管理

マウスカーソルがWidgetに重なった状態を検知するために、「enterEvent」と「leaveEvent」をオーバーライドしていきます。「enterEvent」はマウスカーソルが重なった時、「leaveEvent」はマウスカーソルが抜け出した時に実行されるイベントです(`・ω・´)ゞ

from PySide import QtCore, QtGui

class PlaybackLabel(QtGui.QLabel):

	iconClicked = QtCore.Signal()
	overlayIcon = QtGui.QPixmap(r'D:/playIcon.png')
	
	def __init__(self, filename=None, parent=None):
		super(PlaybackLabel, self).__init__(parent)
		self.__isHover = False
		self.setPixmap(QtGui.QPixmap(filename))
	
	def enterEvent(self, event):
		super(PlaybackLabel, self).enterEvent(event)
		self.__isHover = True
		self.repaint()# 描画の更新
		
	def leaveEvent(self, event):
		super(PlaybackLabel, self).leaveEvent(event)
		self.__isHover = False
		self.repaint()# 描画の更新

シグナルのエミット

サムネがクリックされた時にシグナルがエミットするように、「mousePressEvent」をオーバーライドします。

from PySide import QtCore, QtGui

class PlaybackLabel(QtGui.QLabel):

	iconClicked = QtCore.Signal()
	overlayIcon = QtGui.QPixmap(r'D:/playIcon.png')
	
	def __init__(self, filename=None, parent=None):
		super(PlaybackLabel, self).__init__(parent)
		self.__isHover = False
		self.setPixmap(QtGui.QPixmap(filename))
	
	def enterEvent(self, event):
		super(PlaybackLabel, self).enterEvent(event)
		self.__isHover = True
		self.repaint()
		
	def leaveEvent(self, event):
		super(PlaybackLabel, self).leaveEvent(event)
		self.__isHover = False
		self.repaint()

	def mousePressEvent(self, event):
		super(PlaybackLabel, self).mousePressEvent(event)
		self.iconClicked.emit()

描画処理

インスタンス変数で管理しているHover状態の時だけ、アイコンを追加で描画するようにしていきます!

from PySide import QtCore, QtGui

class PlaybackLabel(QtGui.QLabel):

	iconClicked = QtCore.Signal()
	overlayIcon = QtGui.QPixmap(r'D:/playIcon.png')
	
	def __init__(self, filename=None, parent=None):
		super(PlaybackLabel, self).__init__(parent)
		self.__isHover = False
		self.setPixmap(QtGui.QPixmap(filename))
	
	def enterEvent(self, event):
		super(PlaybackLabel, self).enterEvent(event)
		self.__isHover = True
		self.repaint()
		
	def leaveEvent(self, event):
		super(PlaybackLabel, self).leaveEvent(event)
		self.__isHover = False
		self.repaint()

	def mousePressEvent(self, event):
		super(PlaybackLabel, self).mousePressEvent(event)
		self.iconClicked.emit()
		
	def paintEvent(self, event):
		super(PlaybackLabel, self).paintEvent(event)
		
		# Hover状態の時の処理
		if self.__isHover:
			painter = QtGui.QPainter()
			painter.begin(self)
			painter.setRenderHint(QtGui.QPainter.Antialiasing)
			
			# サムネの中心と、再生ボタンの中心の差分を求めて、描画位置を決める
			painter.translate(
				(painter.device().width()/2) - (self.overlayIcon.width()/2), 
				(painter.device().height()/2) - (self.overlayIcon.height()/2)
				)
			
			# 再生ボタンを描画する
			painter.drawPixmap(QtCore.QPoint(0, 0), self.overlayIcon)
			painter.end()

QPainterで画像合成してWidgetに表示する方法!!

2018.01.11

実験

以下のコードで実験してみます!(*´ω`*)b

window = QtGui.QWidget()
window.setWindowFlags(QtCore.Qt.Window)
layout = QtGui.QHBoxLayout(window)
thumbnail = PlaybackLabel(r'D:\thumbnail.png')
#thumbnail.iconClicked.connect(some_action)
layout.addWidget(thumbnail)
window.show()

マウスカーソルが重なったときだけ、再生ボタンが重なるようになりました!あとはクリックした時の処理を、シグナルにコネクションしてください!(`・ω・´)ゞ

他にも、閉じるボタンにしたりすれば用途も広がると思います!