pythonのreversedはイテレータを返す
反転したリストを複数回使うときにハマった
a = reversed([1, 2, 3]) # イテレータを返す for x in a: print(x) for x in a: print(x) # ここは呼ばれない
reverseなどでリスト自体を反転させておくか
a = [1, 2, 3] a.reverse()
for文ごとにreversedを呼べばOK
a = [1, 2, 3] for x in reversed(a): print(x) for x in reversed(a): print(x)
ちなみにsortedはリストを返す模様
プログラマのためのMaya攻略法
Mayaの内部構造をgoogle先生をウロウロしながら理解するのは効率が悪いので次の方法がおすすめ
- Complete Maya Programmingを読む
- devkitのサンプルを覗く
- MELコマンドの仕様はリファレンスを読む
Complete Maya Programmingは分厚く読むのは疲れるが、ツールを自作するときにも役立つ情報満載なので一度は読んでおいたほうが良いだろう。骨デジタルさんから日本語版も発売されている。Kindle版が欲しいから英語版を買ったけど日本語版買うべきだったな。一社に一冊欲しい。
devkitには今流行のAlembicのサンプルなんかもあったりします。そういえばCOLLADAってどうなったんですかね?
PySide keyPressEventが反応しないとき
もしかして
self.setFocusPolicy(QtCore.Qt.StrongFocus)
し忘れているんじゃないでしょうか。
PySide1と2でQScrollArea::wheelEventの動作が若干違う
違うんじゃあああああああああああああああああぁぁぁぁあああばばばっばばばば
# from PySide2.QtWidgets import * from PySide.QtGui import * import sys app = QApplication(sys.argv) class MyWidget(QWidget): def wheelEvent(self, event): print('hoge') class MyScrollArea(QScrollArea): def wheelEvent(self, event): print('fuga') # PySide1のときは呼ばれてないっぽい scrollArea = MyScrollArea() w = MyWidget() w.setFixedSize(640, 480) scrollArea.setWidget(w) scrollArea.show() sys.exit(app.exec_())
QTimer.singleShotをサブスレッドで使うには
呼び出しスレッド側でexec関数をよんでイベントループを開始せよ
In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
イベントループにはいるとexitを呼ぶまで帰ってこないので注意
from PySide import QtCore, QtGui import sys, time class SingleShotThread(QtCore.QThread): def run(self): QtCore.QTimer.singleShot(1000, lambda: print('hoge')) self.exec_() # イベントループ開始 app = QtGui.QApplication(sys.argv) th = SingleShotThread() th.finished.connect(lambda: print('finished')) th.start() time.sleep(3) th.exit() # exitを呼んで終了させる sys.exit(app.exec_())
PySide2 ビルドしてみる
ここ見たら大体書いてあるよ
https://wiki.qt.io/PySide2_GettingStarted
PySide2最新の状況はこのへんをチェック
環境
- Windows10
- Python 3.6 (64bit)
- Qt 5.6
- OpenSSLは使わないよ
インストールしておくもの
ビルド
- pyside-setupリポジトリの5.6ブランチをrecursiveでcloneする
- 一応virtualenvでビルド環境つくってactivate
- sphinxモジュールをインストール
- VCコンパイラのパス通す
- wheelビルド実行
こんな感じ
> git clone -b 5.6 http://code.qt.io/cgit/pyside/pyside-setup.git/ --recursive > pip install virtualenv > virtualenv hogehoge > hogehoge/Scripts/activate.bat > pip install sphinx > cd pyside-setup > "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 > python setup.py bdist_wheel --ignore-git --qmake="C:\Qt\Qt5.6.2\5.6\msvc2015_64\bin\qmake.exe" --cmake="C:\Program Files\CMake\bin\cmake.exe"
fcntlを呼ぼうとしてエラーが出る?
popenasync.pyのdecode関数を適当に修正
(たぶん日本語表示しようとして例外出てる)
def decode(b): try: return b.decode('utf-8') except UnicodeDecodeError: return b.decode('shift-jis')
非英語圏へ対応する気はなさそうだ
shibokenのドキュメントビルドでMarkupSafeのエラーが出る?
pip install sphinxでMarkupSafeのインストールに失敗しているのでいつものところからwheelを落とす
pip uninstall MarkupSafe pip install MarkupSafe‑1.0‑cp36‑cp36m‑win_amd64.whl
こんな感じで再インストール
RC Pass 1 failed to run. というエラーが出る?
rc.exeにパスが通っていないか別プラットフォームのrc.exeを読んで失敗している
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64
こんな感じでrc.exeのある場所にパスを通すか、WindowsSDKをインストールしなおすと良いと思う
bdist_wheelコマンドが見つからない?
pip install wheel
もしくはこのあたりを参考に
リンクエラーが発生する?
prebuiltなものとビルドターゲットがズレてると出る気がする。32bit版のPythonとかQtを使ってるとか、vcvarsall.bat呼ぶときにamd64つけてないとか
whlのサイズが大きいのが気になる?
setup.pyのdllコピーの規則がQt4時代から変わってないのが原因
- デバッグ用のdllも含まれてしまっている
- setup.pyの *d4.dll, *d?.dll となっている箇所を *d.dll に修正する
- platformsのdllコピーしてるところに ignore=['*d.dll'] を追加する
pyside2uic.Compiler, pyside2uic.port_v3モジュールを使いたい?
setup.pyのsetup()の引数を変更する
packages = ['PySide2', 'pyside2uic', 'pyside2uic.Compiler', 'pyside2uic.port_v3']
PySide Custom Dialog
Dialogを自分で実装するときのポイント
- QDialogを継承する
- ボタン表示にはQDialogButtonBoxを使う
こんなかんじ
from PySide import QtCore, QtGui import sys class CustomDialog(QtGui.QDialog): def __init__(self): super().__init__() self._buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self._buttons.accepted.connect(self.accept) self._buttons.rejected.connect(self.reject) mainLayout = QtGui.QVBoxLayout() mainLayout.addWidget(self._buttons) self.setLayout(mainLayout) self.setWindowTitle('Custom Dialog') app = QtGui.QApplication(sys.argv) mainwindow = QtGui.QMainWindow() mainwindow.show() dialog = CustomDialog() if QtGui.QDialog.Accepted == dialog.exec_(): QtGui.QMessageBox.information(None, 'Info', 'accepted!', QtGui.QMessageBox.Ok) else: QtGui.QMessageBox.critical(None, 'Info', 'rejected!', QtGui.QMessageBox.Ok)