在 KeyPress 中拦截 "Q" 和公司

Intercept "Q" and company in KeyPress

我正在尝试找到一种拦截所有键的方法,但显然所有默认命令仍然存在,并且可以正常运行。我从圆锥体示例开始,并按照示例中的建议尝试了 vtkCallbackCommandSetInteractorStyle

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCylinderSource.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCallbackCommand.h>
#include <vtkCommand.h>

#include <array>

class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
    static KeyPressInteractorStyle* New();
    vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyleTrackballCamera);
    
    virtual void OnKeyPress() override
    {
        vtkRenderWindowInteractor* rwi = this->Interactor;
        std::string key = rwi->GetKeySym();

        std::cout << "Pressed " << key << std::endl;
        
        if (key == "Up")
        {
            std::cout << "The up arrow was pressed." << std::endl;
        }
        
        // Handle a "normal" key
        if (key == "q" || key == "Q")
        {
            std::cout << "The q key was pressed." << std::endl;
            return;
        }
        
        // DO NOT Forward events
        //vtkInteractorStyleTrackballCamera::OnKeyPress();
    }
};
vtkStandardNewMacro(KeyPressInteractorStyle);

void KeypressCallbackFunction(vtkObject* caller, long unsigned int eventId,
                              void* clientData, void* callData)
{
    std::cout << "Keypress callback" << std::endl;
    
    vtkRenderWindowInteractor* iren = static_cast<vtkRenderWindowInteractor*>(caller);
    
    std::cout << "Pressed: " << iren->GetKeySym() << std::endl;
}

int main(int, char*[])
{
    vtkNew<vtkNamedColors> colors;

    std::array<unsigned char, 4> bkg{{26, 51, 102, 255}};
    colors->SetColor("BkgColor", bkg.data());

    vtkNew<vtkCylinderSource> cylinder;
    cylinder->SetResolution(8);

    vtkNew<vtkPolyDataMapper> cylinderMapper;
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());

    vtkNew<vtkActor> cylinderActor;
    cylinderActor->SetMapper(cylinderMapper);
    cylinderActor->GetProperty()->SetColor(colors->GetColor4d("Tomato").GetData());
    cylinderActor->RotateX(30.0);
    cylinderActor->RotateY(-45.0);

    vtkNew<vtkRenderer> renderer;
    renderer->AddActor(cylinderActor);
    renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
    // Zoom in a little by accessing the camera and invoking its "Zoom" method.
    renderer->ResetCamera();
    renderer->GetActiveCamera()->Zoom(1.5);

    vtkNew<vtkRenderWindow> renderWindow;
    renderWindow->SetSize(800, 800);
    renderWindow->AddRenderer(renderer);
    renderWindow->SetWindowName("Cylinder");

    vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
    renderWindowInteractor->SetRenderWindow(renderWindow);
    
    // VIA STYLE
//    vtkNew<KeyPressInteractorStyle> style;
//    renderWindowInteractor->SetInteractorStyle(style);
//    style->SetCurrentRenderer(renderer);
    
    // VIA CALLBACK
    vtkNew<vtkCallbackCommand> keypressCallback;
    keypressCallback->SetCallback(KeypressCallbackFunction);
    renderWindowInteractor->AddObserver(vtkCommand::KeyPressEvent, keypressCallback);
    
    renderWindow->Render();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

在这两种情况下,“Q”仍然退出,“W”仍然进入线框。

有没有办法正确处理所有关键事件,甚至是默认事件?

对于那些快捷方式(即字母),还有发送的 CharEvent,链接到实现 quitwireframevtkInteractorStyle::OnChar 方法。

所以要么用你的风格覆盖它(除了 OnKeyPress),要么用观察者机制处理事件。