在Pygobject GTK3中使用Gtk.GLArea
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Pygobject GTK3中使用Gtk.GLArea相关的知识,希望对你有一定的参考价值。
使用GTk3的python包装器的文档有些限制。我找到了几个常见的小部件示例。我正在尝试使用Gtk.GLArea小部件。 API文档适用于C,我没有太多运气猜测使用此小部件的等效python调用。在该示例中,使用以下C代码创建窗口小部件:
// create a GtkGLArea instance
GtkWidget *gl_area = gtk_gl_area_new ();
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
然后render函数中有openGL命令:
static gboolean
render (GtkGLArea *area, GdkGLContext *context)
{
// inside this function it's safe to use GL; the given
// #GdkGLContext has been made current to the drawable
// surface used by the #GtkGLArea and the viewport has
// already been set to be the size of the allocation
// we can start by clearing the buffer
glClearColor (0, 0, 0, 0);
glClear (GL_COLOR_BUFFER_BIT);
// draw your object
draw_an_object ();
// we completed our drawing; the draw commands will be
// flushed at the end of the signal emission chain, and
// the buffers will be drawn on the window
return TRUE;
}
我的问题是你如何在python中做同等效力的?
这是我的尝试:
class RootWidget(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='GL Example')
self.set_default_size(800,500)
gl = Gtk.GLArea()
gl.connect("render", self.gl_render)
self.add(gl)
def gl_render(self, gl):
print(gl)
Gtk.glClearColor(0,0,0,1)
Gtk.glClear(Gtk.GL_COLOR_BUFFER_BIT)
return True
你会注意到我添加了Gtk。到gl命令。不确定这是否正确但是python不知道函数中的glClearColor是什么。我不是很熟悉C命名空间,但我无法弄清楚C函数如何理解gl命令是什么。程序运行,我在控制台中收到以下错误:
fb设置不受支持
(python.exe:120048):Gdk-WARNING **:在片段着色器中编译失败:
错误:0:5:'gl_FragColor':未声明的标识符
错误:0:5:'texture2D':找不到匹配的重载函数(使用隐式转换)
对此的任何输入都是有用的。我希望能够使用opengl命令在固定的小部件区域中绘制。
编辑:这是我最近的尝试。在on_render()
函数中我打印上下文,我确实看到context属性设置为<gtk.gdk.Win32GLContext object at 0x3f133f0>
,调试确实显示这是当前上下文。问题是我仍然得到相同的着色器,Frag_Color和纹理错误,我甚至没有调用任何gl命令。
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GLU import *
class MyGLArea(Gtk.GLArea):
def __init__(self):
Gtk.GLArea.__init__(self)
self.connect("realize", self.on_realize)
def on_realize(self, area):
ctx = self.get_context()
ctx.make_current()
print("The context is {}".format(self.get_property("context")))
err = self.get_error()
if err:
print(err)
return
class RootWidget(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='GL Example')
self.set_default_size(800,500)
gl_area = MyGLArea()
self.add(gl_area)
win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
编辑2:好像我刚刚遇到GLArea小部件的安装问题。看起来很奇怪,因为我使用了超过30种不同的Gtk小部件而没有问题。我有错误只是添加小部件,甚至没有发送命令。我在Ubuntu python解释器中运行代码,并且创建窗口小部件时没有任何错误。我遇到某些GL命令的问题,但可能来自我安装的python包装器。我仍在寻找相当于pygame或glut的init的小部件,并设置投影函数来设置视口。如果有人有想法,我很乐意听到。以下代码运行没有错误:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GLU import *
class MyGLArea(Gtk.GLArea):
def __init__(self):
Gtk.GLArea.__init__(self)
self.connect("realize", self.on_realize)
self.connect("render", self.render)
def on_realize(self, area):
ctx = self.get_context()
ctx.make_current()
err = self.get_error()
if err:
print("The error is {}".format(err))
def render(self, area, ctx):
glClearColor(1,0,0,1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
return True
class RootWidget(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='GL Example')
self.set_default_size(800,500)
gl_area = MyGLArea()
self.add(gl_area)
win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
我不确定这对你有用,但它对我有用。
Python文件:
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf, Gdk
from OpenGL.GL import glClearColor, glClear, GL_COLOR_BUFFER_BIT
import os, sys
UI_FILE = "pygtk_gtkglarea.ui"
class GUI:
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_FILE)
self.builder.connect_signals(self)
gl_area = Gtk.GLArea()
gl_area.connect('render', self.area_render)
gl_area.connect('realize', self.area_realize)
#gl_area.connect('create-context', self.area_context)
box = self.builder.get_object('box1')
box.pack_end(gl_area, True, True, 0)
window = self.builder.get_object('window')
window.show_all()
def area_realize (self, gl_area):
error = gl_area.get_error()
if error != None:
print "your graphics card is probably too old : ", error
else:
print gl_area, "realize... fine so far"
def area_context(self, gl_area):
# not needed except for special instances, read the docs
c = gl_area.get_context()
print c , "context"
return c
def area_render(self, area, context):
#print gl_area
#print gl_context
glClearColor (0.5, 0.5, 0.5, 1.0)
glClear (GL_COLOR_BUFFER_BIT)
glFlush()
print "rendering... done"
return True
def on_window_destroy(self, window):
Gtk.main_quit()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
和pygtk_gtkglarea.ui文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkWindow" id="window">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">window</property>
<property name="default_width">500</property>
<property name="default_height">400</property>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
使用Windows的All-In-One安装程序,我注意到GTK +的OpenGL Extentions有一个选项。现在它按预期工作。这是一些有效的代码:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np
FRAGMENT_SOURCE ='''
#version 330
in vec4 inputColor;
out vec4 outputColor;
void main(){
outputColor = vec4(1.0,0.0,0.0,1.0);//constant red. I know it's a poor shader
};'''
VERTEX_SOURCE = '''
#version 330
in vec4 position;
void main(){
gl_Position = position;
}'''
class MyGLArea(Gtk.GLArea):
def __init__(self):
Gtk.GLArea.__init__(self)
self.connect("realize", self.on_realize)
self.connect("render", self.on_render)
def on_realize(self, area):
ctx = self.get_context()
print("realized", ctx)
def on_render(self, area, ctx):
ctx.make_current()
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
VERTEX_SHADER_PROG = shaders.compileShader(VERTEX_SOURCE, GL_VERTEX_SHADER)
FRAGMENT_SHADER_PROG = shaders.compileShader(FRAGMENT_SOURCE, GL_FRAGMENT_SHADER)
self.shader_prog = shaders.compileProgram(VERTEX_SHADER_PROG, FRAGMENT_SHADER_PROG)
self.create_object()
def create_object(self):
# Create a new VAO (Vertex Array Object) and bind it
vertex_array_object = glGenVertexArrays(1)
glBindVertexArray(vertex_array_object)
# Generate buffers to hold our vertices
vertex_buffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer)
# Get the position of the 'position' in parameter of our shader and bind it.
position = glGetAttribLocation(self.shader_prog, 'position')
glEnableVertexAttribArray(position)
# Describe the position data layout in the buffer
glVertexAttribPointer(position, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0))
# Send the data over to the buffer
vertices = np.array([-0.6, -0.6, 0.0,
0.0, 0.6, 0.0,
0.6, -0.6, 0.0,
0.7, -0.1, 0.0,
0.8, 0.1, 0.0,
0.9, -0.1, 0.0
], dtype=np.float32)
glBufferData(GL_ARRAY_BUFFER, 96, vertices, GL_STATIC_DRAW)
# Unbind the VAO first (Important)
glBindVertexArray(0)
# Unbind other stuff
glDisableVertexAttribArray(position)
glBindBuffer(GL_ARRAY_BUFFER, 0)
self.display(vertex_array_object)
def display(self, vert):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(self.shader_prog)
glBindVertexArray(vert)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDrawArrays(GL_TRIANGLES, 4, 3)
glBindVertexArray(0)
glUseProgram(0)
class RootWidget(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='GL Example')
self.set_default_size(800, 500)
gl_area = MyGLArea()
gl_area.set_has_depth_buffer(False)
gl_area.set_has_stencil_buffer(False)
self.add(gl_area)
win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
以上是关于在Pygobject GTK3中使用Gtk.GLArea的主要内容,如果未能解决你的问题,请参考以下文章
使用 Pygobject 和 Python 3 从内存数据中显示图像
对 Python GUI 应用程序进行单元测试的推荐方法是啥?
Anaconda 中的 FileChooserDialog 图标坏了如何修复?