#!python # -*- mode: python; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2016/10/16 22:20:55 +0900> """ 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()