ページ 1 / 1
wxPythonとpyOpenGLについて・・・
Posted: 2014年7月29日(火) 19:40
by puchimilk
プログラミングをはじめたばかりのものです。
wxPythonとpyOpenGLを別々でプログラムを作ったのですがこれを同時に起動させるにはどうしたらいいのでしょうか。どうやっても別々のウィンドウで開いてしまいます。
プログラムを貼っておきます。
コード:
# coding:utf-8
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
def display():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
gluLookAt(0,4,10, 0,0,0, 0,1,0)
glRotatef(-40, 0.0, 1.0, 0.0)
glColor3f(float(0xbb)/0xff, float(0xdd)/0xff, 0xff/0xff)
glutSolidCube(3.5)
glPopMatrix()
glFlush()
def reshape(width,height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0) #投影変換
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(200, 200)
glutCreateWindow('pyopengl')
glutReshapeFunc(reshape) #リサイズコールバック関数の登録
glutDisplayFunc(display)
glutMainLoop()
コード:
#! /usr/bin/env python
# coding:UTF-8
# simplemenu.py
import wx
class SimpleMenu(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(800, 600))
menubar = wx.MenuBar()
file = wx.Menu()
edit = wx.Menu()
file.Append(-1, u'新規')
file.Append(-1, u'開く')
file.Append(-1, u'保存')
file.Append(-1, u'名前を付けて保存')
file.Append(-1, u'終了', 'Quit application')
edit.Append(-1, u'元に戻す')
menubar.Append(file, u'&ファイル')
menubar.Append(edit, u'&編集')
self.SetMenuBar(menubar)
self.Centre()
self.Show(True)
app = wx.App()
SimpleMenu(None, -1, 'simplemenu.py')
app.MainLoop()
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年7月30日(水) 20:41
by みょん
``同時に起動"というのは一つのwindowで提示されたコードを実行するという意味でしょうか?
wxPythonの中でGLUTを使いたいならwx.glcanvasというのがあるみたいです.
http://stackoverflow.com/questions/6031 ... el-problem
http://d.hatena.ne.jp/Megumi221/20110411/1302252987
使い方はwx.Frameにwx.glcanvasを追加し, glcanvasにはGLUTの処理を, wx.Frameの方にはwxの処理をそれぞれ書けばよいようです.
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年7月31日(木) 02:04
by puchimilk
教えていただいたことをやってみてエラーは出なくなったのですが、メニューバーが表示されません。原因は何でしょうか。
コード:
# coding:utf-8
import sys
import wx
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from wx.glcanvas import GLCanvas
class myGLCanvas(GLCanvas):
def __init__(self, *args, **kwargs):
GLCanvas.__init__(self, *args, **kwargs)
def display():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
gluLookAt(0,4,10, 0,0,0, 0,1,0)
glRotatef(-40, 0.0, 1.0, 0.0)
glColor3f(float(0xbb)/0xff, float(0xdd)/0xff, 0xff/0xff)
glutSolidCube(3.5)
glPopMatrix()
glFlush()
def reshape(width,height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0) #投影変換
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(500, 500)
glutCreateWindow('pyopengl')
glutReshapeFunc(reshape) #リサイズコールバック関数の登録
glutDisplayFunc(display)
glutMainLoop()
class SimpleMenu(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
menbar = wx.MenuBar()
file = wx.Menu()
edit = wx.Menu()
file.Append(-1, u'新規')
file.Append(-1, u'開く')
file.Append(-1, u'保存')
file.Append(-1, u'名前を付けて保存')
file.Append(-1, u'終了', 'Quit application')
edit.Append(-1, u'元に戻す')
menubar.Append(file, u'&ファイル')
menubar.Append(edit, u'&編集')
self.SetMenuBar(menubar)
self.Centre()
self.Show(True)
app = wx.App()
SimpleMenu(None, -1, 'simplemenu.py')
app.MainLoop()
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年7月31日(木) 10:30
by みょん
提示されたコードではGLUTの処理とwxの処理が分離しています。
今のままだとGLUT→wxの順番で書いてあるのでglutMainLoopを実行した時点でGLUTが起動して、wxのウィンドウが表示されないと思われます。
私が上に貼ったリンク先のコードを確認してください。
現状ではやりたい処理をGLUTの函数を使ってコールバックを登録して呼び出し、となっていますが、glCanvasではself.Bind(wx.EVT_PAINT, self.OnPaint)のようにしてglCanvas内でself.OnPaintコールバックをEVT_PAINTに登録して呼び出すことになります。
上のコードではdisplayをEVT_PAINT, reshapeをEVT_SIZEに登録すればOKだと思います。
- wx.glcanvas公式ドキュメント
http://xoomer.virgilio.it/infinity77/wx ... anvas.html
- バインド可能なイベントの一覧はここのKnown Subclassesを参照
http://xoomer.virgilio.it/infinity77/wx ... Event.html
以上の説明で分からなければ説明を加えますのでどこが分からないかを言ってください。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年7月31日(木) 12:38
by puchimilk
もう少し細かい説明お願いできますか。
コード:
class myGLCanvas(GLCanvas):
def __init__(self, *args, **kwargs):
GLCanvas.__init__(self, *args, **kwargs)
の下に
コード:
self.Bind(wx.EVT_PAINT,self.OnPaint)
self.Bind(wx.EVT_SIZE,self.OnSize)
と入力するんですよね? その後のことを詳しくお願いします。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年7月31日(木) 15:37
by みょん
コード:
class myGLCanvas(GLCanvas):
def __init__(self, *args, **kwargs):
GLCanvas.__init__(self, *args, **kwargs)
self.Bind(wx.EVT_PAINT,self.OnPaint) # self.OnPaintをEVT_PAINTに登録(glutDisplayFuncの代わり)
self.Bind(wx.EVT_SIZE,self.OnSize) # self.OnSizeをEVT_SIZEに登録(glutReshapeFuncの代わり)
def OnPaint(self): # 画面描画の処理
def OnSize(self): # リサイズのときの処理
ここまでは大丈夫だと思います。一つ前のポストでも述べたようにOnPaintはdisplay, OnSizeはreshapeの代わりになります。
次に、glCanvasはそれ単体で動かすのではなくwx.Frame上の部品として動くので、wx.Frame側に部品の宣言と配置を行います。
コード:
# wx.Frameクラスで以下のように初期化
self.canvas = myGLCanvas(self, size=(640, 480)) # myGLCanvasのインスタンスを生成
self.sizer = wx.BoxSizer() # 画面にwidgetを配置する これはBoxSizerでなくともなんでもよい
self.sizer.Add(self.canvas) # canvasをwidgetに追加
self.SetSizerAndFit(self.sizer) # この行は不要かも(?)
上ではBoxSizerを使いましたが、他により適切なwidgetがあればそちらに変えてください。
おそらくこれで問題なく動くと思います。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月01日(金) 00:03
by puchimilk
コード:
# coding:utf-8
import sys
import wx
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from wx.glcanvas import GLCanvas
class myGLCanvas(GLCanvas):
def __init__(self, *args, **kwargs):
GLCanvas.__init__(self, *args, **kwargs)
self.Bind(wx.EVT_PAINT,self.OnPaint) # self.OnPaintをEVT_PAINTに登録(glutDisplayFuncの代わり)
self.Bind(wx.EVT_SIZE,self.OnSize) # self.OnSizeをEVT_SIZEに登録(glutReshapeFuncの代わり)
def OnPaint(self): # 画面描画の処理
def OnSize(self): # リサイズのときの処理
def display():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
gluLookAt(0,4,10, 0,0,0, 0,1,0)
glRotatef(-40, 0.0, 1.0, 0.0)
glColor3f(float(0xbb)/0xff, float(0xdd)/0xff, 0xff/0xff)
glutSolidCube(3.5)
glPopMatrix()
glFlush()
def reshape(width,height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0) #投影変換
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(500, 500)
glutCreateWindow('pyopengl')
glutReshapeFunc(reshape) #リサイズコールバック関数の登録
glutDisplayFunc(display)
glutMainLoop()
class SimpleMenu(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.canvas = myGLCanvas(self, size=(500,500)) # myGLCanvasのインスタンスを生成
self.sizer = wx.BoxSizer() # 画面にwidgetを配置する これはBoxSizerでなくともなんでもよい
self.sizer.Add(self.canvas) # canvasをwidgetに追加
self.SetSizerAndFit(self.sizer) # この行は不要かも(?)
menbar = wx.MenuBar()
file = wx.Menu()
edit = wx.Menu()
file.Append(-1, u'新規')
file.Append(-1, u'開く')
file.Append(-1, u'保存')
file.Append(-1, u'名前を付けて保存')
file.Append(-1, u'終了', 'Quit application')
edit.Append(-1, u'元に戻す')
menubar.Append(file, u'&ファイル')
menubar.Append(edit, u'&編集')
self.SetMenuBar(menubar)
self.Centre()
self.Show(True)
app = wx.App()
SimpleMenu(None, -1, 'simplemenu.py')
app.MainLoop()
def OnSize(self):のdefにエラーがでます。なぜですか。
エラー
Syntax error
There's an error in your program:
expected an indented block
と出ます。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月01日(金) 11:59
by みょん
エラーメッセージにある通り、インデントが合わないのでコンパイルが通りませんと言われています。
Pythonだと空のブロックは作れないので、函数の内容を書くか
コード:
def empty_block(self):
pass
と書きます。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月02日(土) 00:12
by puchimilk
どこに書けばいいですか。
def OnSize(self): の下ですか?
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月02日(土) 11:19
by puchimilk
コード:
# coding:utf-8
import sys
import wx
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from wx.glcanvas import GLCanvas
class myGLCanvas(GLCanvas):
def __init__(self, *args, **kwargs):
GLCanvas.__init__(self, *args, **kwargs)
self.Bind(wx.EVT_PAINT,self.OnPaint) # self.OnPaintをEVT_PAINTに登録(glutDisplayFuncの代わり)
self.Bind(wx.EVT_SIZE,self.OnSize) # self.OnSizeをEVT_SIZEに登録(glutReshapeFuncの代わり)
def OnPaint(self): # 画面描画の処理
def OnSize(self): # リサイズのときの処理
def empty_block(self):
pass
def display():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
gluLookAt(0,4,10, 0,0,0, 0,1,0)
glRotatef(-40, 0.0, 1.0, 0.0)
glColor3f(float(0xbb)/0xff, float(0xdd)/0xff, 0xff/0xff)
glutSolidCube(3.5)
glPopMatrix()
glFlush()
def reshape(width,height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(width)/float(height), 0.1, 100.0) #投影変換
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(500, 500)
glutCreateWindow('pyopengl')
glutReshapeFunc(reshape) #リサイズコールバック関数の登録
glutDisplayFunc(display)
glutMainLoop()
class SimpleMenu(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.canvas = myGLCanvas(self, size=(500,500)) # myGLCanvasのインスタンスを生成
self.sizer = wx.BoxSizer() # 画面にwidgetを配置する これはBoxSizerでなくともなんでもよい
self.sizer.Add(self.canvas) # canvasをwidgetに追加
menbar = wx.MenuBar()
file = wx.Menu()
edit = wx.Menu()
file.Append(-1, u'新規')
file.Append(-1, u'開く')
file.Append(-1, u'保存')
file.Append(-1, u'名前を付けて保存')
file.Append(-1, u'終了', 'Quit application')
edit.Append(-1, u'元に戻す')
menubar.Append(file, u'&ファイル')
menubar.Append(edit, u'&編集')
self.SetMenuBar(menubar)
self.Centre()
self.Show(True)
app = wx.App()
SimpleMenu(None, -1, 'simplemenu.py')
app.MainLoop()
エラーは出なくなりましたが、メニューバーが出てきません。まだ何か違うのでしょうか?
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月02日(土) 18:40
by みょん
何度も言うようですが、こういうことです。
みょん さんが書きました:
提示されたコードではGLUTの処理とwxの処理が分離しています。
今のままだとGLUT→wxの順番で書いてあるのでglutMainLoopを実行した時点でGLUTが起動して、wxのウィンドウが表示されないと思われます。
あなたのコードでは、上から順に実行されて、48行目にさしかかったところでGLUTのウィンドウが起動するのでそれより下に書いたwxの処理は一切実行されません。
Pythonに不慣れな方とお見受けしますが、wxのフレームワークの基本的な設計を理解しないとこのコードを自分で書くのは難しいと思います。
オブジェクト指向に関して、クラスの使い方、メンバ関数とはなにか、インスタンスとはなにか、クラスの継承をするとどうなるか、などは理解されていますか?そしてそれらはPythonではどのような構文で表せばよいのかご存知ですか?
wxやQtなどのたいていのGUIフレームワークを利用するには、オブジェクト指向の基本的なことをまず理解する必要があります。そしてPythonで書くならPythonの基本的なことはマスターしてください。
現状、(当然GLUTはある程度できるという前提で)GLUTとwxを組み合わせて動かすという非常に高度なことをしようとしているので、これが難しいと感じるならもう少し簡単なところから始めるのはいかがでしょうか、というのが私からの提案です。
上のことを踏まえた上で、一応以下に解答を述べます。
まずglut関連のコードは不要なので
コード:
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(500, 500)
glutCreateWindow('pyopengl')
glutReshapeFunc(reshape) #リサイズコールバック関数の登録
glutDisplayFunc(display)
glutMainLoop()
はすべて削除します。次に、myGLCanvas.__init__で以下のように初期化を行います。
コード:
self.initialized = False
glutInit()
OnPaint, OnSizeを以下のように実装します。
コード:
def OnPaint(self, event):
self.SetCurrent()
if self.initialized == False:
reshape(*self.GetSize())
self.initialized = True
display()
def OnSize(self,event):
w,h = event.GetSize()
reshape(w,h)
こちらではこれで動きましたが、何故か画面のCubeが暗いので、OpenGLのライティングの設定などがおかしいのだと思います。それと、今のコードだと描画のたびにglEnable(GL_LIGHTING)などを呼んでいるなどの少し気になる点も散見されますので、この辺を直せば正しく動く可能性もあります。
オフトピック
サンプルやドキュメントを調べていて思ったのですが、glCanvas.SwapBuffersにバグがあったり公式サイトのコードが動かなかったりしたので、wxPython(wxかも?)の情報が古いのか開発が止まっているのかもしれないです。
今後お使いになられるなら注意してください。
Re: wxPythonとpyOpenGLについて・・・
Posted: 2014年8月03日(日) 09:05
by puchimilk
もっと基本をマスターしてからやってみようと思います。
回答にお時間を使っていただきありがとうございます。