Kohshi's Blog
2016/01/28
import matplotlibでハング
[ここ](http://kohshi.blogspot.jp/2015/06/homebrewpythonnumpy-scipy-matplotlib.html)で紹介した方法でmatplotlibやspicyをinstallしたが、実際にmatplotlibを使おうとするとハングする問題が発生。 アクティビティモニターでチェックしてみると"fc-list"なるプロセスがCPUを食ってるよう。 色々調べてみると[ここ](http://stackoverflow.com/questions/17490444/import-matplotlib-pyplot-hangs)で、同じ現象が取り上げられてる。対策は以下のコマンドを打てとのこと。 ```bash $ cd ~/.matplotlib/ $ fc-list ``` 上をうつと大量のログが出力されたのち、普通に使えるようになった。
ツイート
2016/01/19
PyQtでvtkをWidget表示
PyQtでvtkの3次元表示ViewをWidgetとしてEmbbedしたい場合の自分メモ 普通はQVTKWidgetPlugin.dll/.soなりをQt Designerのpluginsフォルダに入れる事によって、 Qt DesignerのサイドバーにQVTKWidgetが表示され、それをDrag&DropするだけでLayoutされる!というスマートなやり方が正しいはずなんだが。 ことpython + QVTKWidgetに限ってはなんか以下の理由でできない(なんで?と思うが) (Windows + Anaconda環境と、MacOS + homebrew環境で確認) * そもそもQVTKWidgetというモジュールがvtkをpython + qtで使う環境に存在しない。 ↓のサイトによるとfrom QVTKWidget import QVTKWidgetに存在しない。from vtk import QVTKWidgetなら存在するとかあるが、これも存在しないと起こられる。 *
http://paulklemm.com/zenf/blog/2012/08/20/install-python-together-with-vtk-using-homebrew-for-mountain-lion/
で、色々探してみるとfrom vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor を使えというサイトを見つけた。 *
http://www.vtk.org/Wiki/VTK/Examples/Python/Widgets/EmbedPyQt
ためしにこれで試すとうまくいくが、もしQt DesignerでQVTKWidgetPlugin.dll/soを使ってDrag&DropでLayoutをすると強制的にQVTKWidgetをloadされちゃうので できない。 なのでQt Desingerのpromote toを使って、 1. まずWidgetをvtkを配置したい箇所に配置 2. promote toでpromotionの設定を開く 3. headerにvtk.qt4.QVTKRenderWindowInteractor.hをpromotion classにQVTKRenderWindowInteractorを書いて追加 4. 1.で追加したWidgetを右クリックしてpromote to -> QVTKRenderWindowInteractorを選択してpromoteさせる 3. のQVTKRenderWindowInteractorクラスをPromotion用に追加した所↓
4.の後↓のようになる
という手順を踏むとQt Designderでの変更に対して何もしなくても以下のpythonコードで呼べる。 (C++と.uiファイルが共通化できなかったりというデメリットもあるが、現状これしかない気もする。) ```python import sys import vtk from PyQt4 import QtCore, QtGui, uic #from ui_mainwindow import Ui_MainWindow class testPyQt(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) Ui_MainWindow = uic.loadUiType("ui_mainwindow.ui", self)[0] self.ui = Ui_MainWindow() self.ui.setupUi(self) # setup connection self.ui.pushButton.clicked.connect(self.onClickButton) ### !!! Added from here !!! ### self.renderer = vtk.vtkRenderer() self.ui.qvtkWidget.GetRenderWindow().AddRenderer(self.renderer) self.ui.qvtkWidget.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera()) # Add initial actores self.axes = vtk.vtkAxesActor() transform = vtk.vtkTransform() transform.Translate(0.0, 0.0, 0.0) self.axes.SetUserTransform(transform) self.axes.GetXAxisCaptionActor2D().GetTextActor().SetTextScaleModeToNone() self.axes.GetYAxisCaptionActor2D().GetTextActor().SetTextScaleModeToNone() self.axes.GetZAxisCaptionActor2D().GetTextActor().SetTextScaleModeToNone() self.axes.SetTotalLength(1, 1, 1) self.renderer.AddActor(self.axes) self.renderer.ResetCamera() ### !!! Added until here !!! ### # Added to draw call should be called after open window def show(self): QtGui.QMainWindow.show(self) self.ui.qvtkWidget.Initialize() @QtCore.pyqtSlot() def onClickButton(self): self.ui.label.setText("Pushed!!") def main(): app = QtGui.QApplication(sys.argv) window = testPyQt() window.show() sys.exit(app.exec_()) if __name__ == "__main__": main() ``` show()関数をoverrideしているのは、RenderingがWindowが開かないうちに実行されるのを避ける為。例えば、Mac環境で__init__内でself.qvtkWidget.Initialize()をやってしまうと以下の様なエラーが大量に出る ```bash ERROR: In /tmp/vtk20151007-9396-c4u0qe/VTK-6.2.0/Rendering/OpenGL/vtkOpenGLPolyDataMapper2D.cxx, line 442 vtkOpenGLPolyDataMapper2D (0x7f9d3c171460): failed after RenderOverlay 1 OpenGL errors detected 0 : (1286) Invalid framebuffer operation ``` 以下のForumで議論されている内容で、Forumでもshowを明示的に呼んでからRenderしろのような事が書かれている(と思う)。 http://paulklemm.com/zenf/blog/2012/08/20/install-python-together-with-vtk-using-homebrew-for-mountain-lion/ なのでmain()内で呼ばれるshow()の後にInteractorのInitialize()が呼ばれる様にするためにこの構成。
ツイート
PyQtでGUI:.uiファイルのload
PyQt(PyQt4)でGUIプログラムする自分用メモ .uiファイル+Qt Designerが使いやすいのもQtのメリットだと思ってるのでpythonからもUIのレイアウトはこれでやりたい。 .uiでレイアウトしてpythonで読み込むには2つ方法があるらしい。 1. pyuic4を使って.ui -> .pyに変換しimport 2. uicを使って直接import 1.は.pyに統一できていいが、開発中は毎UI変更の度に変換が必要でめんどい。 2.は変換は不要だが.uiファイルをPackageに含まないといけない(それでもいい場合もある?)。 ↓によると開発中は2.でお手軽に、配布時に1.で変換するみたいのが良いってことかな? [https://riverbankcomputing.com/pipermail/pyqt/2010-September/027970.html](https://riverbankcomputing.com/pipermail/pyqt/2010-September/027970.html) というわけでサンプル作ってみた。 まずQt Designerで簡単なUI(PushButtonを押すと、Labelの文字が変わるというだけ)を作成
.uiファイルをloadして表示するコードが以下。 ```python import sys from PyQt4 import QtCore, QtGui, uic # form classを直接importする場合は必要 #from ui_mainwindow import Ui_MainWindow class testPyQt(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) # form classを直接importする場合は↓の行が不要になる Ui_MainWindow = uic.loadUiType("ui_mainwindow.ui", self)[0] self.ui = Ui_MainWindow() self.ui.setupUi(self) # setup connection self.ui.pushButton.clicked.connect(self.onClickButton) @QtCore.pyqtSlot() def onClickButton(self): self.ui.label.setText("Pushed!!") def main(): app = QtGui.QApplication(sys.argv) window = testPyQt() window.show() sys.exit(app.exec_()) if __name__ == "__main__": main() ``` testPyQtクラスのself.uiにform class(C++ではUi::MainWindowClassとかでmoc_*.cppファイルに生成されてたやつだと思う)をnewする。 検索するとtestPyQtクラス自体をform classから継承する例や、self.uiにuic.loadUi()で生成されたQMainWindow(or QWidget)を直接showするコード(下記)もあったというか結構多い。 前者はUIと制御コードが一緒のclassになっちゃうので避けたい実装、後者はtestPyQtでQMainWindowを継承している意味がわかんなくなるので、その辺のやり方を避けると上のやり方に落ち着きそう。 ```python class testPyQt(QtGui.QMainWindow): def __init__(self): # uic.loadUi returns QMainWindow self.ui = uic.loadUi("ui_mainwindow.ui") self.ui.show() def main(): app = QtGui.QApplication(sys.argv) window = testPyQt() # window.show() # ここでshowしない sys.exit(app.exec_()) ``` 結果、こんな感じにできる。
ツイート
新しい投稿
前の投稿
ホーム
登録:
投稿 (Atom)