Move a scalar bar with pyq5 and python3.5

Hi all,

I’m trying write an application with a vtk windows.
Nevertheless, I have some difficulties to move and resize manually the scalar bar when I use pyqt5. Here’s my code:

# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtWidgets, QtGui, QtCore, Qt 
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import pyqtgraph 
import math
import numpy
import vtk
import vtk.qt
vtk.qt.QVTKRWIBase =  "QGLWidget"
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class Window(QtWidgets.QMainWindow):
    
    def __init__(self) :
        super(Window, self).__init__()
        self.setGeometry(250, 100, 900, 800)
        self.setWindowTitle("Interactive vtk exemple")
                
        extractAction = QtWidgets.QAction( "Leave",self)
        extractAction.setShortcut("Ctrl+Q")
        extractAction.setStatusTip('Leave application')
        extractAction.triggered.connect(qApp.quit)       
          
        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu('&File')
        fileMenu.addAction(extractAction)        
        
        self.statusBar()        
        
        self.home()
        
        
    def home(self):     

        self.frame = QtWidgets.QFrame()    
        self.setCentralWidget(self.frame)    
        
        self.layout = QtWidgets.QGridLayout()
        self.frame.setLayout(self.layout)
           
        ## Source/reader
        reader = vtk.vtkUnstructuredGridReader()
        reader.SetFileName("stripComplex.vtk")    
        reader.SetScalarsName("temperature")
        reader.Update()
           
        pointData = reader.GetOutput().GetPointData()
        drange = pointData.GetScalars().GetRange()
        print("a",drange[0])
        print("b",drange[1])

        colorFunction = vtk.vtkColorTransferFunction()
        colorFunction.SetColorSpaceToHSV()
        colorFunction.HSVWrapOff()
        colorFunction.AddRGBPoint(drange[0], 0.0, 0.0, 1.0)
        colorFunction.AddRGBPoint(drange[1], 1.0, 0.0, 0.0)      
           
        ## Create a mapper
        Mapper = vtk.vtkDataSetMapper()
        Mapper.SetInputConnection(reader.GetOutputPort())       
        Mapper.SetScalarRange(drange)
        Mapper.SetLookupTable(colorFunction)       
        
        ## Create an actor
        Actor = vtk.vtkActor()
        Actor.SetMapper(Mapper)
        
        prop = Actor.GetProperty()
        prop.SetAmbient(0.5)
        prop.EdgeVisibilityOn()
        prop.SetEdgeColor(0, 0, 0)
        prop.SetLineWidth(2)        

        
        ## Renderer
        self.ren = vtk.vtkRenderer()
        self.ren.AddActor(Actor)
        self.ren.GetActiveCamera().SetPosition(2,0.5,10)
        self.ren.GetActiveCamera().SetFocalPoint(2,0.5,2)

        ## Windows renderer    
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)         
        self.renwin = self.vtkWidget.GetRenderWindow()
        self.renwin.AddRenderer(self.ren)
        self.layout.addWidget(self.vtkWidget,2,1)        

        ## Interactor
        self.iren = self.renwin.GetInteractor()         

        ## scalar bar
        scalarBar = vtk.vtkScalarBarActor()
        scalarBar.SetLookupTable( colorFunction )
        
       ## scalar bar widget
        scalar_bar_widget = vtk.vtkScalarBarWidget()
        scalar_bar_widget.SetInteractor(self.iren)
        scalar_bar_widget.SetScalarBarActor(scalarBar)
        scalar_bar_widget.On()
        self.ren.AddActor(scalarBar)            

        ## Slider 1 exemple
        self.slidAmplitude = QtWidgets.QSlider(QtCore.Qt.Vertical)
        self.slidAmplitude.setMinimum(0.0)
        self.slidAmplitude.setMaximum(100.0)
        self.slidAmplitude.setValue(5)
        self.slidAmplitude.setTickInterval(1)
        self.slidAmplitude.setTickPosition(2)
        self.layout.addWidget(self.slidAmplitude,2,0)

        ## Slider 2 exemple
        self.slidFrequence = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slidFrequence.setMinimum(0.0)
        self.slidFrequence.setMaximum(200.0)
        self.slidFrequence.setValue(50.0)
        self.slidFrequence.setTickPosition(1)
        self.slidFrequence.setTickInterval(1.0)
        self.layout.addWidget(self.slidFrequence,3,1)  
        
        self.iren.Initialize()
        self.iren.Start()   
        self.iren.Render() 
    
        self.show()
        
def run() :        
    app = QtWidgets.QApplication(sys.argv)
    GUI = Window()
    sys.exit(app.exec())

run()

When i execute this code, i can interact with the geometry but not with the scalar bar.
Is there anything wrong? any suggestion?
Thanks

+1

I’m also experiencing this issue on a pull request in vtki. The vtkScalarBarWidget is not interactive but the vtkOrientationMarkerWidget works somewhat fine.

FYI @guillaume, we have some Qt-based plotting classes in vtki that might make it easier to create your own sophisticated application. Check out this example.

Update: I think the code you have is correct but there is some sort of bug linking the mouse location of the Qt app and the VTK interactor. See vtki/97 for more details.

For example, if you can successfully add a vtkOrientationMarkerWidget, you’ll see that it detects the mouse in the wrong places (there’s a GIF of this in vtki/97). This leads me to think that the scalar bar simply does not see the mouse hovering over it.

Thanks for the answer Bane.
I wanted to be sure I did not make a programming mistake.
As I started the vtk, I wanted to understand the basics before using a module like VTKI.

Status update: this is an issue that that has appeared and disappeared for me. It has been incredibly difficult to purposely reproduce. See notes in vtki/97

Some days the interactive scalar bars work, some days they don’t. :frowning:

I found a solution for this problem and it’s not a bug in relation with linking mouse location.
Actually, the vtkScalarBarWidget object must be an instance variable (i.e. self.scalar_bar_widget = vtk.vtkScalarBarWidget())

So i replace the previous bloc concerning the scalar bar widget by:

scalar bar widget

    self.scalar_bar_widget = vtk.vtkScalarBarWidget()
    self.scalar_bar_widget.SetInteractor(self.iren)
    self.scalar_bar_widget.SetScalarBarActor(scalarBar)
    scalar_bar_widget.On()

Interesting find! Does that fix the issue for you?

We already assign the vtkScalarBarWidget object in vtki so I must be experiencing something different.

Yes my problem is completely solved. Recently, I stumbled upon a note written by Nicholas R. Rypkema to solve some issue to display an interactive coordinate axes at this link:
https://nrr.mit.edu/blog/note-about-vtk-pyqt-and-vtkorientationmarkerwidget
So I just transpose it to my scalar bar.
In any case, I would like to thank you for your answers.

1 Like