如何在嵌入wxpython的vispy canvas中动态添加对象到场景
How to dynamically add an object to a scene in vispy canvas embedded in wxpython
我想在按下按钮时添加一个箭头(某个对象)。该代码是 vispy 存储库中给出的示例的修改版本。
import wx
from vispy import scene
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
view = self.central_widget.add_view()
view.bgcolor = 'snow'
view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='red', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='red', antialias=True)#, parent=view.scene) -Unable to access view from the Canvas class
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()
我已经创建了示例中给出的 Canvas,并尝试从 mainFrame
对其进行实例化。在 Canvas
class 的 __init__
中给出的所有对象都会被创建。如果我想在按下按钮创建 GUI 后添加任何新对象,我将无法从 mainFrame
访问 Canvas
class 中的 view
.或者有没有其他方法可以实现。
更新:
以下是遵循评论中给出的建议后的代码:
import wx
from vispy import scene, gloo
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
self.unfreeze()
self.view = self.central_widget.add_view()
self.view.bgcolor = 'snow'
self.view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=self.view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=self.view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=self.panel_vispy.canvas.view.scene)
self.panel_vispy.canvas.update() # Canvas not getting updated
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()
代码现在运行没有任何错误,这意味着箭头可能已添加但场景未更新。
根据@djhoese 和@RolfofSaxony 的建议,我更新了代码。代码现在可以在单击按钮时成功添加箭头。
import wx
from vispy import scene, gloo
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
self.unfreeze()
self.view = self.central_widget.add_view()
self.view.bgcolor = 'snow'
self.view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=self.view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='red', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='blue', antialias=True, parent=self.view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, -1, -0.5, 1)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (-1, -0.5, 1)]), color='green', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='blue', antialias=True, parent=self.panel_vispy.canvas.view.scene)
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()
我想在按下按钮时添加一个箭头(某个对象)。该代码是 vispy 存储库中给出的示例的修改版本。
import wx
from vispy import scene
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
view = self.central_widget.add_view()
view.bgcolor = 'snow'
view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='red', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='red', antialias=True)#, parent=view.scene) -Unable to access view from the Canvas class
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()
我已经创建了示例中给出的 Canvas,并尝试从 mainFrame
对其进行实例化。在 Canvas
class 的 __init__
中给出的所有对象都会被创建。如果我想在按下按钮创建 GUI 后添加任何新对象,我将无法从 mainFrame
访问 Canvas
class 中的 view
.或者有没有其他方法可以实现。
更新: 以下是遵循评论中给出的建议后的代码:
import wx
from vispy import scene, gloo
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
self.unfreeze()
self.view = self.central_widget.add_view()
self.view.bgcolor = 'snow'
self.view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=self.view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=self.view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='teal', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='teal', antialias=True, parent=self.panel_vispy.canvas.view.scene)
self.panel_vispy.canvas.update() # Canvas not getting updated
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()
代码现在运行没有任何错误,这意味着箭头可能已添加但场景未更新。
根据@djhoese 和@RolfofSaxony 的建议,我更新了代码。代码现在可以在单击按钮时成功添加箭头。
import wx
from vispy import scene, gloo
from vispy.scene.visuals import Arrow
import numpy as np
class Canvas(scene.SceneCanvas):
def __init__(self, *a, **k):
sizes = k.pop("sizes", (300, 300)) # Default value is (300, 300)
scene.SceneCanvas.__init__(self, *a, **k, size=sizes)
self.unfreeze()
self.view = self.central_widget.add_view()
self.view.bgcolor = 'snow'
self.view.camera = scene.TurntableCamera(up='+y', azimuth=100, elevation=15, fov=60)
axis = scene.visuals.XYZAxis(parent=self.view.scene)
arrow1 = np.array([(0, 0, 0, 1, 1, 0)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (1, 1, 0)]), color='red', method='gl', width=5., arrows=arrow1,
arrow_type="angle_30", arrow_size=5.0, arrow_color='blue', antialias=True, parent=self.view.scene)
self.show()
class mainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = "Add Object", pos = wx.DefaultPosition, size = wx.Size( 905,569 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.panel_vispy = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer1.Add( self.panel_vispy, 9, wx.EXPAND |wx.ALL, 5 )
self.panel_Buttons = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.button_AddArrow = wx.Button( self.panel_Buttons, wx.ID_ANY, u"Add Arrow", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.button_AddArrow, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( ( 0, 0), 1, wx.EXPAND, 5 )
self.panel_Buttons.SetSizer( bSizer2 )
self.panel_Buttons.Layout()
bSizer2.Fit( self.panel_Buttons )
bSizer1.Add( self.panel_Buttons, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.button_AddArrow.Bind(wx.EVT_BUTTON, self.button_AddArrow_OnClick)
self.panel_vispy.canvas = Canvas(app="wx", parent=self, sizes=self.panel_vispy.GetSize())
def button_AddArrow_OnClick(self, event):
print("Adding arrow")
arrow2 = np.array([(0, 0, 0, -1, -0.5, 1)]) # Arrow direction, position
arr = Arrow(pos=np.array([(0, 0, 0), (-1, -0.5, 1)]), color='green', method='gl', width=5., arrows=arrow2,
arrow_type="angle_30", arrow_size=5.0, arrow_color='blue', antialias=True, parent=self.panel_vispy.canvas.view.scene)
if __name__ == "__main__":
app = wx.App(False)
GUI = mainFrame(None)
GUI.Show(True)
app.MainLoop()