wxPythonとpyOpenGLについて・・・

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
puchimilk
記事: 20
登録日時: 11年前

wxPythonとpyOpenGLについて・・・

#1

投稿記事 by puchimilk » 11年前

プログラミングをはじめたばかりのものです。
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()

アバター
みょん
記事: 16
登録日時: 12年前
住所: 京都
連絡を取る:

Re: wxPythonとpyOpenGLについて・・・

#2

投稿記事 by みょん » 11年前

``同時に起動"というのは一つの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の処理をそれぞれ書けばよいようです.

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#3

投稿記事 by puchimilk » 11年前

 教えていただいたことをやってみてエラーは出なくなったのですが、メニューバーが表示されません。原因は何でしょうか。

コード:

# 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()

アバター
みょん
記事: 16
登録日時: 12年前
住所: 京都
連絡を取る:

Re: wxPythonとpyOpenGLについて・・・

#4

投稿記事 by みょん » 11年前

提示されたコードでは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

以上の説明で分からなければ説明を加えますのでどこが分からないかを言ってください。

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#5

投稿記事 by puchimilk » 11年前

もう少し細かい説明お願いできますか。

コード:

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)
と入力するんですよね? その後のことを詳しくお願いします。

アバター
みょん
記事: 16
登録日時: 12年前
住所: 京都
連絡を取る:

Re: wxPythonとpyOpenGLについて・・・

#6

投稿記事 by みょん » 11年前

コード:

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があればそちらに変えてください。
おそらくこれで問題なく動くと思います。

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#7

投稿記事 by puchimilk » 11年前

コード:

# 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
と出ます。

アバター
みょん
記事: 16
登録日時: 12年前
住所: 京都
連絡を取る:

Re: wxPythonとpyOpenGLについて・・・

#8

投稿記事 by みょん » 11年前

エラーメッセージにある通り、インデントが合わないのでコンパイルが通りませんと言われています。
Pythonだと空のブロックは作れないので、函数の内容を書くか

コード:

def empty_block(self):
    pass
と書きます。

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#9

投稿記事 by puchimilk » 11年前

どこに書けばいいですか。
def OnSize(self): の下ですか?

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#10

投稿記事 by puchimilk » 11年前

コード:

# 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()
エラーは出なくなりましたが、メニューバーが出てきません。まだ何か違うのでしょうか?

アバター
みょん
記事: 16
登録日時: 12年前
住所: 京都
連絡を取る:

Re: wxPythonとpyOpenGLについて・・・

#11

投稿記事 by みょん » 11年前

何度も言うようですが、こういうことです。
みょん さんが書きました: 提示されたコードでは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かも?)の情報が古いのか開発が止まっているのかもしれないです。
今後お使いになられるなら注意してください。

puchimilk
記事: 20
登録日時: 11年前

Re: wxPythonとpyOpenGLについて・・・

#12

投稿記事 by puchimilk » 11年前

もっと基本をマスターしてからやってみようと思います。
回答にお時間を使っていただきありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る