2016/10/16(日) [n年前の日記]
#1 [python] PySideのQMainWindow上に色々配置する例
こんな感じかな…。
_mainwdwlayout.py
QMainWindowは、上、下、左、右に、ドックウィジェット(QDockWidget)なるものを配置することができるらしいので、そのあたりにRGB値を設定するアレコレを置いてみたり。
QDockWidget は、タイトルバーをドラッグすればメインウインドウから切り離したり、またくっつけたり、左じゃなくて右に再配置したりできる。しかし、デフォルト設定では閉じることも可能で…。閉じてしまうと、再復活させる方法が…。なので、今回は設定を変えて閉じるボタンを無効にしてみたり。
QDockWidget を一度メインウインドウから切り離して(フロート状態にして)、またメインウインドウに戻そうとしても戻ってくれなくて悩んだけれど。どうやらメインウインドウのサイズより、ドックウィジェットのほうがサイズが大きいとくっついてくれないようで。メインウインドウのサイズを大きくしてからドラッグしたらくっついてくれた。気づくまで時間がかかった…。
_mainwdwlayout.py
"""
PySideを使ってQMainWindow上にレイアウトする事例
"""
import sys
from PySide.QtCore import *
from PySide.QtGui import *
color_info = None
class MyColorInfo(QPushButton):
""" 色を表示するウィジェット """
def __init__(self, parent=None):
super(MyColorInfo, self).__init__(parent)
self.color = QColor(128, 128, 128)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.setMinimumSize(48, 48)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
qp.setPen(QColor(0, 0, 0))
qp.setBrush(self.color)
qp.drawRect(2, 2, 44, 44)
qp.end()
def updateColor(self, r, g, b):
""" 色を更新 """
self.color.setRgb(r, g, b)
self.update()
class MySlider(QWidget):
"""
RGB値指定スライダー部分
"""
def __init__(self, parent=None):
super(MySlider, self).__init__(parent)
gb = QGridLayout() # 升目上に並べる
gb.setContentsMargins(0, 0, 0, 0) # 外のマージン(隙間)を極力無くす
# 色表示部分
global color_info
color_info = MyColorInfo(self)
gb.addWidget(color_info, 0, 0, 1, 3)
# スライダーやスピンボックス部分
self.value = []
self.sld = []
self.spb = []
# RGBの3つ分、Slider や SpinBox を確保
for (i, s) in enumerate(["R", "G", "B"]):
lbl = QLabel(s)
sld = QSlider(Qt.Orientation.Horizontal, self)
spb = QSpinBox()
# レイアウト
gb.addWidget(lbl, i + 1, 0)
gb.addWidget(sld, i + 1, 1)
gb.addWidget(spb, i + 1, 2)
# 値の範囲を 0-255 に設定
sld.setRange(0, 255)
spb.setRange(0, 255)
# 現在値を初期化
v = 128
sld.setValue(v)
spb.setValue(v)
# 後で使うので記録しておく
self.value.append(v)
self.sld.append(sld)
self.spb.append(spb)
# 自身のレイアウトとして登録
self.setLayout(gb)
# Slider や SpinBox 値が変えられた時に呼ばれるメソッドを設定
for i in range(3):
self.sld[i].valueChanged[int].connect(self.sliderChangeValue)
self.spb[i].valueChanged[int].connect(self.spinBoxChangeValue)
def sliderChangeValue(self, value):
""" Slider の値が変わった時に呼ばれる処理 """
for (i, sld) in enumerate(self.sld):
self.spb[i].setValue(sld.value())
self.updateColor()
def spinBoxChangeValue(self, value):
""" SpinBox の値が変わった時に呼ばれる処理 """
for (i, spb) in enumerate(self.spb):
self.sld[i].setValue(spb.value())
self.updateColor()
def updateColor(self):
""" 色表示部分を更新 """
v = []
for spb in self.spb:
v.append(spb.value())
global color_info
color_info.updateColor(v[0], v[1], v[2])
class MyBrushWidget(QWidget):
""" メインウインドウ左側に配置するウィジェット """
def __init__(self, parent=None):
super(MyBrushWidget, self).__init__(parent)
layout = QVBoxLayout() # 縦に並べる
# ブラシ画像選択部分
self.cb = QComboBox()
self.cb.addItem("default.png")
self.cb.addItem("extra.png")
layout.addWidget(self.cb)
# ブラシ画像表示部分
self.scene_brush = QGraphicsScene()
self.gview_brush = QGraphicsView(self.scene_brush, self)
self.gview_brush.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.gview_brush.setMinimumSize(256, 256)
layout.addWidget(self.gview_brush)
# 色選択部分
self.rgb_area = MySlider(self)
layout.addWidget(self.rgb_area)
# スペーシング
spc = QSpacerItem(16, 16, QSizePolicy.Expanding, QSizePolicy.Expanding)
layout.addSpacerItem(spc)
# 自身のレイアウトとして設定
self.setLayout(layout)
class MyMainWindow(QMainWindow):
""" メインウインドウ """
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
# メニューバー
mb = QMenuBar()
file_menu = QMenu("&File", self)
exit_action = file_menu.addAction("&Close")
exit_action.setShortcut('Ctrl+Q')
exit_action.triggered.connect(qApp.quit)
mb.addMenu(file_menu)
self.setMenuBar(mb)
# ステータスバー
self.status = QStatusBar(self)
self.status.showMessage("Status Bar")
self.setStatusBar(self.status)
# 左側のドックウィジェット
self.leftDock = QDockWidget("Left Dock Widget", self)
self.brushw = MyBrushWidget(self)
self.leftDock.setWidget(self.brushw)
# 移動とフローティングは有効にするが閉じるボタンは無効にする
# 注意:
# メインウインドウが十分大きくないと、フローティング後、元に戻せない
self.leftDock.setAllowedAreas(Qt.LeftDockWidgetArea
| Qt.RightDockWidgetArea)
self.leftDock.setFeatures(QDockWidget.DockWidgetMovable
| QDockWidget.DockWidgetFloatable \
# | QDockWidget.DockWidgetVerticalTitleBar
)
self.addDockWidget(Qt.LeftDockWidgetArea, self.leftDock)
# 中央ウィジェット
self.scene_image = QGraphicsScene()
self.gview_image = QGraphicsView(self.scene_image, self)
self.setCentralWidget(self.gview_image)
def main():
app = QApplication(sys.argv)
# app.setStyle(QStyleFactory.create('Cleanlooks'))
w = MyMainWindow()
w.setWindowTitle("PySide Layout on QMainWindow")
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
QMainWindowは、上、下、左、右に、ドックウィジェット(QDockWidget)なるものを配置することができるらしいので、そのあたりにRGB値を設定するアレコレを置いてみたり。
QDockWidget は、タイトルバーをドラッグすればメインウインドウから切り離したり、またくっつけたり、左じゃなくて右に再配置したりできる。しかし、デフォルト設定では閉じることも可能で…。閉じてしまうと、再復活させる方法が…。なので、今回は設定を変えて閉じるボタンを無効にしてみたり。
QDockWidget を一度メインウインドウから切り離して(フロート状態にして)、またメインウインドウに戻そうとしても戻ってくれなくて悩んだけれど。どうやらメインウインドウのサイズより、ドックウィジェットのほうがサイズが大きいとくっついてくれないようで。メインウインドウのサイズを大きくしてからドラッグしたらくっついてくれた。気づくまで時間がかかった…。
◎ 参考ページ。 :
[ ツッコむ ]
以上です。
