PySide 編集可能なQTreeWidgetを作る
import sys from PySide import QtCore, QtGui class MyTreeWidget(QtGui.QTreeWidget): def __init__(self): super().__init__() self.setHeaderHidden(True) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.contextMenuRequested) # アイテムの移動を有効にする self.setDragDropMode(QtGui.QAbstractItemView.InternalMove) self.setDragEnabled(True) self.viewport().setAcceptDrops(True) # 挿入位置カーソルを表示する self.setDropIndicatorShown(True) def contextMenuRequested(self, pos): """ コンテキストメニュー """ menu = QtGui.QMenu() item = self.itemAt(pos) if item: action = QtGui.QAction('Delete Item', self) action.triggered.connect(lambda: self.removeItem(item)) menu.addAction(action) else: action = QtGui.QAction('New Item', self) action.triggered.connect(self.createNewItem) menu.addAction(action) menu.exec_(self.mapToGlobal(pos)) def createNewItem(self): """ 新規項目 """ item = QtGui.QTreeWidgetItem() item.setText(0, 'Item') # アイテムを編集可能にする item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable) self.addTopLevelItem(item) def removeItem(self, item): """ 項目削除 """ parent = item.parent() if parent: parent.takeChild(parent.indexOfChild(item)) else: self.takeTopLevelItem(self.indexOfTopLevelItem(item)) app = QtGui.QApplication(sys.argv) tr = MyTreeWidget() tr.show() sys.exit(app.exec_())
PySide movable and resizable widget without frame
import sys, enum from PySide import QtCore, QtGui class Item(QtGui.QLabel): Manipilate = enum.Enum('Manipilate', 'none move resize_l resize_r') def __init__(self, text): super().__init__(text) self.setStyleSheet('background-color: white; border: 1px solid black; padding: 4px;') self.resize(128, 64) self._mani = Item.Manipilate.none self._offset = QtCore.QPoint(0, 0) self._rect = self.rect() self.setMouseTracking(True) def mousePressEvent(self, event): pos = event.pos() if self._mani == Item.Manipilate.none: self._mani = self.get_manipulation(pos) self._offset = event.pos() self._rect = self.geometry() def mouseReleaseEvent(self, event): self._mani = Item.Manipilate.none def mouseMoveEvent(self, event): pos = event.pos() if self._mani == Item.Manipilate.none: self.setCursor({ Item.Manipilate.none: QtCore.Qt.ArrowCursor, Item.Manipilate.move: QtCore.Qt.ArrowCursor, Item.Manipilate.resize_l: QtCore.Qt.SizeHorCursor, Item.Manipilate.resize_r: QtCore.Qt.SizeHorCursor }[self.get_manipulation(pos)]) elif self._mani == Item.Manipilate.move: self.move(self.mapToParent(pos - self._offset)) elif self._mani == Item.Manipilate.resize_l: sub = pos - self._offset self.setGeometry(self._rect.x() + sub.x(), self._rect.y(), self._rect.width() - sub.x(), self._rect.height()) self._rect = self.geometry() elif self._mani == Item.Manipilate.resize_r: sub = pos - self._offset self.setGeometry(self._rect.x(), self._rect.y(), self._rect.width() + sub.x(), self._rect.height()) self.update() def get_manipulation(self, pos): if pos.x() < 8: return Item.Manipilate.resize_l if pos.x() > (self.width() - 8): return Item.Manipilate.resize_r else: return Item.Manipilate.move app = QtGui.QApplication(sys.argv) widget = QtGui.QWidget() widget.setFixedSize(640, 480) item = Item('item') item.setParent(widget) item.move(0, 0) widget.show() sys.exit(app.exec_())
PySide Progressbarを表示してみる
QProgressDialogを使うと一番簡単であります
import sys from PySide import QtGui app = QtGui.QApplication(sys.argv) prog = QtGui.QProgressDialog('何か処理しています...', 'キャンセル', 0, 100, None, 0) prog.show() prog.setValue(50) sys.exit(app.exec_())
キャンセルボタンなくしたい
コンストラクタのキャンセルボタンのテキストにNoneを指定
QtGui.QProgressDialog('何か処理しています...', None, 0, 100, None, 0)
ウインドウのボタンを消したい
コンストラクタの最後の引数でウインドウフラグを指定
QtGui.QProgressDialog('何か処理しています...', 'キャンセル', 0, 100, None, QtCore.Qt.Window | QtCore.Qt.WindowTitleHint | QtCore.Qt.CustomizeWindowHint)
リサイズなくしたい
setFixedSizeを呼ぶ
prog.setFixedSize(prog.sizeHint())
Marqueeスタイル(進捗表示しないで処理の終了だけ待つやつ)にしたい
プログレスバーの範囲を 0 ~ 0 にする
QtGui.QProgressDialog('何か処理しています...', 'キャンセル', 0, 0, None, 0)
バー横の空白が残る場合は進捗表示テキストをセンター寄せすればいい
prog.setStyleSheet('QProgressBar {text-align: center;}')
QScrollAreaに固定されたヘッダーを表示する
import sys from PySide import QtGui class MyTable(QtGui.QWidget): def __init__(self): super().__init__() lo = QtGui.QHBoxLayout() lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(0) self.setLayout(lo) self._header = QtGui.QLabel('header') self._header.setStyleSheet('border-right: 1px solid black;\ border-bottom: 1px solid black;\ background-color: red;') self._header.setFixedSize(128, 32) lo.addWidget(self._header) for i in range(0, 8): item = QtGui.QLabel('cell {0}'.format(i)) item.setStyleSheet('border-right: 1px solid black;\ border-bottom: 1px solid black;\ background-color: white;') item.setFixedSize(128, 32) lo.addWidget(item) def setHeaderPos(self, x, y): self._header.move(x, y) self._header.raise_() app = QtGui.QApplication(sys.argv) table = MyTable() scroll = QtGui.QScrollArea() scroll.setWidget(table) def moveHeader(): x = scroll.horizontalScrollBar().value() table.setHeaderPos(x, 0) scroll.horizontalScrollBar().valueChanged.connect(moveHeader) scroll.show() sys.exit(app.exec_())
スライダーの移動量を固定する
下記コードを追加する
def scrollControll(x): x = int(x / 128) * 128 scroll.horizontalScrollBar().setValue(x) scroll.horizontalScrollBar().setSingleStep(128) # ボタン押された時の移動量 scroll.horizontalScrollBar().sliderMoved.connect(scrollControll)
PySide ドラッグでデータ受け渡し
import sys from PySide import QtCore, QtGui # ドラッグ&ドロップで色を受け渡す class WidgetItem(QtGui.QLabel): def __init__(self, color): super().__init__('') self._color = color self.setStyleSheet('border: 1px solid black;') self.setFixedSize(32, 32) self.setAcceptDrops(True) def paintEvent(self, event): self.changeColor() super().paintEvent(event) def changeColor(self): pal = QtGui.QPalette(self.palette()) pal.setColor(QtGui.QPalette.Window, QtGui.QColor(self._color)) self.setAutoFillBackground(True) self.setPalette(pal) def mousePressEvent(self, event): # ドラッグオブジェクトに色データ(テキスト)を埋め込んで実行 drag = QtGui.QDrag(self) mime = QtCore.QMimeData() mime.setText(self._color) drag.setMimeData(mime) drag.exec_() def dragEnterEvent(self, event): event.accept() def dragMoveEvent(self, event): event.accept() def dropEvent(self, event): if event.mimeData().hasText(): self._color = event.mimeData().text() self.changeColor() app = QtGui.QApplication(sys.argv) widget = QtGui.QWidget() widget.setFixedSize(640, 240) widget.setLayout(QtGui.QHBoxLayout()) layout = widget.layout() layout.addWidget(WidgetItem('red')) layout.addWidget(WidgetItem('blue')) layout.addWidget(WidgetItem('green')) layout.addWidget(WidgetItem('white')) widget.show() sys.exit(app.exec_())
PySide ドラッグでWidgetを移動させる
import sys from PySide import QtCore, QtGui # ドラッグで動くWidget class WidgetItem(QtGui.QLabel): def __init__(self): super().__init__('') self.setStyleSheet('border: 1px solid black; background-color: red;') self.setFixedSize(32, 32) self._drag = False self._offset = QtCore.QPoint(0, 0) def mousePressEvent(self, event): self._drag = True self._offset = event.pos() def mouseReleaseEvent(self, event): self._drag = False def mouseMoveEvent(self, event): if self._drag: self.move(self.mapToParent(event.pos() - self._offset)) app = QtGui.QApplication(sys.argv) widget = QtGui.QWidget() widget.setFixedSize(640, 480) widget.setLayout(QtGui.QVBoxLayout()) layout = widget.layout() item = WidgetItem() layout.addWidget(item) widget.show() sys.exit(app.exec_())
Pythonゲームプログラミング #9 スクロール
gist消してしまったので
代わりにこのリポジトリを参考にしてください
#0 環境構築
#1 メインループ
#2 画像表示
#3 アニメーション
#4 キー入力
#5 サウンド
#6 衝突判定
#7 ステートマシン
#8 マップチップ
#9 スクロール
スクロール
pygameを使ったゲームプログラミングについて説明していきます。
- Windows10
- Python3.6.1
- pygame1.9.3
今回はスクロールについて紹介します。
スクロールとは?
画面に収まりきらない空間をカメラを移動させることで表示する技法です。 実際は描画位置を「カメラからの相対位置」に変換することで実現しています。
サンプルコード
前回のマップを拡げて画面に収まらないようにします。 ついでに上下左右キーで移動できるカメラを追加します。
実行結果