フレームレスなウインドウをリサイズできるようにする方法!!

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

フレームレスなウインドウにすると、リサイズするためのハンドルも消えてしまいリサイズできない・・・

っということで!「フレームレスなウインドウをD&Dで動かす方法!!」でご紹介したウインドウをリサイズできるようにする方法をご紹介したいと思います!

QMainWindowベース

前回の記事では、フレームレスなウインドウをQMainWindowをベースに作成しました!QMainWindowをベースにした場合は、とってもシンプルで「statusBar」を呼び出せば、フレームレスなウインドウでも、リサイズするためのハンドルを簡単に追加できます!

from PySide import QtCore, QtGui
 
class OptionWidget(QtGui.QWidget):
	closed = QtCore.Signal()
	 
	def __init__(self, *args, **kwargs):
		super(OptionWidget, self).__init__(*args, **kwargs)
		 
		mainLayout = QtGui.QVBoxLayout(self)
		 
		button = QtGui.QPushButton('Close', self)
		button.clicked.connect(self.__close)
		mainLayout.addWidget(button)
		mainLayout.addStretch(True)
	 
	def __close(self):
		self.closed.emit()
	 
class DraggableWindow(QtGui.QMainWindow):
	def __init__(self, *args, **kwargs):
		super(DraggableWindow, self).__init__(*args, **kwargs)
		self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
		 
		optionWidget = OptionWidget(self)
		optionWidget.closed.connect(self.close)
		self.setCentralWidget(optionWidget)
		
		statusBar = self.statusBar()
		
		self.__isDrag = False
		self.__startPos = QtCore.QPoint(0, 0)
	  
	def mousePressEvent(self, event):
		self.__isDrag = True
		self.__startPos = event.pos()
		super(DraggableWindow, self).mousePressEvent(event)
	  
	def mouseReleaseEvent(self, event):
		self.__isDrag = False
		super(DraggableWindow, self).mouseReleaseEvent(event)
		  
	def mouseMoveEvent(self, event):
		if self.__isDrag:
			self.move(self.mapToParent(event.pos() - self.__startPos))
			  
		super(DraggableWindow, self).mouseMoveEvent(event)

実行してみると、以下のようになります!(*´ω`*)b

QWidgetベース

QWidgetなど、Status Barがないウィジェットをベースにした場合は、QStatusBarを作成してレイアウトなどを駆使して好みの場所に来るように追加します!(`・ω・´)ゞ

from PySide import QtCore, QtGui
 
class FramelessWindow(QtGui.QWidget):
	def __init__(self, *args, **kwargs):
		super(FramelessWindow, self).__init__(*args, **kwargs)
		
		self.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.FramelessWindowHint)
		
		mainLayout = QtGui.QVBoxLayout(self)# メインのレイアウト
		mainLayout.setContentsMargins(0, 0, 0, 0)# 余白をなくす
		
		innerLayout = QtGui.QVBoxLayout(self)# 閉じるボタン用のレイアウト
		innerLayout.setContentsMargins(10, 10, 10, 0)# 余白を作る
		mainLayout.addLayout(innerLayout)
		
		button = QtGui.QPushButton('Close', self)
		button.clicked.connect(self.close)
		innerLayout.addWidget(button)
		
		mainLayout.addStretch(True)# StatusBarが下部に来るようにストレッチ
		
		statusBar = QtGui.QStatusBar(self)
		mainLayout.addWidget(statusBar)# 余白のないレイアウトに追加
		
		self.__isDrag = False
		self.__startPos = QtCore.QPoint(0, 0)
	  
	def mousePressEvent(self, event):
		self.__isDrag = True
		self.__startPos = event.pos()
		super(FramelessWindow, self).mousePressEvent(event)
	  
	def mouseReleaseEvent(self, event):
		self.__isDrag = False
		super(FramelessWindow, self).mouseReleaseEvent(event)
		  
	def mouseMoveEvent(self, event):
		if self.__isDrag:
			self.move(self.mapToParent(event.pos() - self.__startPos))
			  
		super(FramelessWindow, self).mouseMoveEvent(event)

実行してみると、、、QMainWindowと同じようにできました!(*´ω`*)b

各部位に枠線を付けてわかりやすくすると、以下のようになります!

ステータスバーを追加する問題

ステータスバーを追加してしまうと、どうしてもウインドウの下部に大きめの隙間ができてしまいます・・・(´・ω・`)

この隙間を作らずに、リサイズするハンドルを作りたい場合は「QSizeGrip」をオススメします!(*´ω`*)b

QSizeGrip

QWidgetベース」を例に、「QStatusBar」ではなく「QSizeGrip」にしたものを作ってみます!

from PySide import QtCore, QtGui
 
class FramelessWindow(QtGui.QWidget):
	def __init__(self, *args, **kwargs):
		super(FramelessWindow, self).__init__(*args, **kwargs)
		
		self.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.FramelessWindowHint)
		
		mainLayout = QtGui.QVBoxLayout(self)
		mainLayout.setContentsMargins(0, 0, 0, 0)
		mainLayout.setSpacing(0)
		
		innerLayout = QtGui.QVBoxLayout(self)
		innerLayout.setContentsMargins(10, 10, 10, 0)
		mainLayout.addLayout(innerLayout)
		
		button = QtGui.QPushButton('Close', self)
		button.clicked.connect(self.close)
		innerLayout.addWidget(button)
		
		mainLayout.addStretch(True)
		
		sizeGrip = QtGui.QSizeGrip(self)
		mainLayout.addWidget(sizeGrip, False, QtCore.Qt.AlignRight)# 右寄せ
		
		self.__isDrag = False
		self.__startPos = QtCore.QPoint(0, 0)
	  
	def mousePressEvent(self, event):
		self.__isDrag = True
		self.__startPos = event.pos()
		super(FramelessWindow, self).mousePressEvent(event)
	  
	def mouseReleaseEvent(self, event):
		self.__isDrag = False
		super(FramelessWindow, self).mouseReleaseEvent(event)
		  
	def mouseMoveEvent(self, event):
		if self.__isDrag:
			self.move(self.mapToParent(event.pos() - self.__startPos))
			  
		super(FramelessWindow, self).mouseMoveEvent(event)

すると、以下の様にウインドウの下部にスペースを節約できます!(`・ω・´)ゞ