0

I am trying to create a GUI using Vispy and PySide2. I'm quite new to these libraries. I am facing a problem when I try to set an alignment for Vispy's canvas.

I'm getting this error message for whatever alignment flag I try. I suspect that the Vispy canvas embedding is done incorrectly. Could anyone help?

   central_layout.addWidget(canvas       , 2,0,1,2 , QtCore.Qt.AlignCenter )

TypeError: 'PySide2.QtWidgets.QGridLayout.addWidget' called with wrong argument types:
 PySide2.QtWidgets.QGridLayout.addWidget(SceneCanvas, int, int, int, int, AlignmentFlag)
Supported signatures:
 PySide2.QtWidgets.QGridLayout.addWidget(PySide2.QtWidgets.QWidget, int, int, PySide2.QtCore.Qt.Alignment = Default(Qt.Alignment))
 PySide2.QtWidgets.QGridLayout.addWidget(PySide2.QtWidgets.QWidget, int, int, int, int, PySide2.QtCore.Qt.Alignment = Default(Qt.Alignment))
 PySide2.QtWidgets.QGridLayout.addWidget(PySide2.QtWidgets.QWidget)

I'm running Python 3.8.1, vispy 0.9.3 and PySide2 5.13.2 on Spyder.

import matplotlib
matplotlib.use('Agg')
import sys
sys.path.append("../../../")


import vispy
import pyglet
vispy.app.use_app('pyglet')
from vispy import color, scene, app

from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QComboBox, QHBoxLayout, QPushButton, QCheckBox, QLineEdit, QLabel
from PySide2 import QtCore



if not QApplication.instance():
    app = QApplication(sys.argv)
else:
    app = QApplication.instance()

mw  = QMainWindow()
mw.resize(1900,1000)

# build canvas
canvas = scene.SceneCanvas(keys='interactive', show=False)
# canvas = vispy.app.canvas.Canvas(keys='interactive', show=False)

central_layout = QGridLayout()
central_widget = QWidget()
central_widget.setLayout(central_layout)

mw.setCentralWidget(central_widget)
mw.setWindowTitle('Driving Test (2D/3D)')

configuration_layout      = QHBoxLayout()
debug_layout              = QHBoxLayout()

cmap_attribute            = QComboBox()
cmap_type                 = QComboBox()
cycle_label               = QLabel('Cycle :')
debug_mode_checkbox       = QCheckBox('Debug Mode')
input_cycle               = QLineEdit()
go_to_specific_cycle_btn  = QPushButton('GO')
next_cycle_btn            = QPushButton('Next Cycle')
previous_cycle_btn        = QPushButton('Previous Cycle')
attribute_selected_info   = QLabel()

input_cycle.setPlaceholderText('Enter a spécific cycle and click on (GO)')

input_cycle.setMaximumWidth(250)
go_to_specific_cycle_btn.setMaximumWidth(50)
debug_mode_checkbox.setMaximumWidth(100)
cycle_label.setFixedSize(80, 40)
attribute_selected_info.setFixedSize(500, 40)

cmap_attribute.addItems(['snr','power','rcs','velocity', 'range','detection_confidence','elevation'])
cmap_type.addItems(['jet','viridis'])

configuration_layout.addWidget(cmap_attribute)
configuration_layout.addWidget(cmap_type)

debug_layout.addWidget(debug_mode_checkbox)
debug_layout.addWidget(input_cycle)
debug_layout.addWidget(go_to_specific_cycle_btn)
debug_layout.addWidget(previous_cycle_btn)
debug_layout.addWidget(next_cycle_btn)
debug_layout.addWidget(cycle_label)
debug_layout.addWidget(attribute_selected_info)

central_layout.addLayout(configuration_layout , 0,0,1,2)
central_layout.addLayout(debug_layout         , 1,0,1,2)
central_layout.addWidget(canvas       , 2,0,1,2 , QtCore.Qt.AlignCenter )
top_grid = canvas.central_widget.add_grid()


mw.show()


if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QApplication.instance().exec_()
```
B.Sarah
  • 119
  • 1
  • 3
  • 11
  • Use `canvas.native` instead of `canvas` in your `addWidget` call. Let me know how that goes. – djhoese Nov 24 '21 at 13:18
  • I've already tried this but it's not working. I get this error message : ```TypeError: 'PySide2.QtWidgets.QGridLayout.addWidget' called with wrong argument types: PySide2.QtWidgets.QGridLayout.addWidget(CanvasBackend, int, int, int, int, AlignmentFlag)``` – B.Sarah Nov 24 '21 at 13:47
  • So `.native` should be a `QGLWidget` which is a subclass of `QWidget` so that should be fine. Just to be sure could you try removing the last argument (AlignCenter) and see if that fixes things? – djhoese Nov 24 '21 at 17:40
  • Still does not work. I get the same error message. – B.Sarah Nov 25 '21 at 08:41
  • @djhoese do you know if this is due to my spyder version or just to spyder? – B.Sarah Nov 25 '21 at 08:53
  • There is something else funny going on here. Can you try running it from the command line and not from spyder? – djhoese Nov 25 '21 at 17:48
  • Wait, why do you have it configured to use `pyglet` and then you use pyside2? – djhoese Nov 25 '21 at 17:49
  • Regarding ```pyglet```, I used it just to try another backend since ```PySide2``` backend does not work for me and I forgot to change it before I share my code. I get this error message when I try to configure ```vispy``` to use ```PySide2``` : `AttributeError: module 'vispy.app.backends._pyside2' has no attribute 'ApplicationBackend` – B.Sarah Nov 26 '21 at 08:15
  • It works fine from the command line ( after using ```canvas.native``` instead of ```canvas``` in ```addWidget```) – B.Sarah Nov 26 '21 at 08:18

1 Answers1

0

As discussed in the comments, the proper way to add a vispy Canvas (or SceneCanvas) object to a GUI framework is to add canvas.native to the GUI. canvas.native should be an equivalent of whatever "widget" the GUI backend expects.

Your other issue turned out to be that you were running from Spyder and were forcing the vispy backend to pyglet. I don't know much about pyglet so I'm not sure if it should be possible to use pyglet + pyside2, but as mentioned above .native is tied to the backend you choose so it must have been passing a pyglet object to pyside2.

The last error you mention when using pyside2 and running your program from spyder may be an incompatibility between running other GUI frameworks from within spyder. At least that's my guess.

djhoese
  • 3,567
  • 1
  • 27
  • 45