如何在FLTK中使用两个不同的小部件使用键盘箭头和鼠标单击

How can I use both keyboard arrows and mouse clicks for two different widgets in FLTK?

本文关键字:键盘 小部 单击 鼠标 两个 FLTK      更新时间:2023-10-16

我正在将fltk与c 一起编写一个程序以滚动浏览图像文件夹。我有一个带有缩略图的下一个按钮的下一个图像,而上一个按钮也适用于上一个按钮。我希望通过单击上一个和下一个按钮以及使用键盘上的左和右箭头来浏览图像。

我成功地做到了这一点,但是并非同时。当我只写下回调函数时:

void buttonCallback(Fl_Widget* widget, void* viewerPtr) {
   Viewer* viewer = static_cast<Viewer*>(viewerPtr);
   viewer->navPressed(widget);
   viewer->redraw();
}

我可以单击相应的按钮向前和向后移动,但是当我超载句柄功能以处理键盘箭头时,我可以这样:

int Viewer::handle(int e) {
switch(e) {
    case FL_FOCUS:
    case FL_UNFOCUS:
        return 1;
    case FL_KEYBOARD:
        if ( Fl::event_key() == FL_Left) {
            prev->do_callback();
            return(1);
        } else if (Fl::event_key() == FL_Right) {
            next->do_callback();
            return(1);
        }
        return 1;
    case FL_RELEASE:
        do_callback();
        return 1;
}
   return Fl_Widget::handle(e);
}

我可以使用箭头,但是我无法弄清楚如何使用两个箭头并单击按钮。我尝试将FL_WIDGET *W传递到句柄功能并返回回调,然后单击按钮,但无法再使用箭头。

这是viewer.cpp文件:

#include <iostream>
#include "Viewer.h"
using namespace std;
void buttonCallback(Fl_Widget* widget, void* viewerPtr) {
    //cout << "Callback called" << endl;
    Viewer* viewer = static_cast<Viewer*>(viewerPtr);
    viewer->navPressed(widget);
    viewer->redraw();
}

Viewer::Viewer(string imageFolder, vector<string> imageFilenames, int width = 800, int height = 600) :
    Fl_Window(width, height, "Image Viewer"), imageFolder(imageFolder), imageFilenames(imageFilenames), currentIndex(0), nextIndex(1), prevIndex(imageFilenames.size()-1),
    prev(nullptr), next(nullptr), imageBox(nullptr), pic(nullptr) {

    prev = new NavButton(getPathFilename(imageFilenames.at(prevIndex), true), "Previous Button", borderSize, this->h() - borderSize - thumbnailSize - borderSize, thumbnailSize, imageFilenames.size() - 1);

    next = new NavButton(getPathFilename(imageFilenames.at(nextIndex), true), "Next Button",
        this->w() - borderSize - thumbnailSize - borderSize, this->h() - borderSize - thumbnailSize - borderSize, thumbnailSize, imageFilenames.size()-1);

    imageBox = new Fl_Box(borderSize, borderSize, this->w() - (2*borderSize), this->h() - (2*borderSize) - thumbnailSize - 2*borderSize);

    //imageBox->box(FL_BORDER_BOX); // useful to see where the full size of the widget holding the images
    pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
    imageBox->image(pic);
    this->end();
    prev->callback(buttonCallback, static_cast<void*>(this));
    next->callback(buttonCallback, static_cast<void*>(this));
}
string Viewer::getPathFilename(string filename, bool thumb) {
    string thumbPart = "";
    if (thumb) thumbPart = "t_";
    return imageFolder + "/" + thumbPart+ filename;
}
void Viewer::navPressed(Fl_Widget *widget) {
    NavButton* b = dynamic_cast<NavButton*>(widget);
    // adds to the click counts to keep track of them
    b->addClickCount(); b->addTotalClicks();
    cout <<  b->getLabel() << " has been pressed " << b->getClickCount() << " times." << endl;
    cout << "All buttons have been pressed " << b->getTotClicks() << " times." << endl;
    // determines which button is pressed
    if (b->getLabel() == "Next Button") {
        changeAllInds(true);
        // check to see if at end of list
        if ((nextIndex) > imageFilenames.size()-1) {
            nextIndex = 0;
        } else if (currentIndex > imageFilenames.size()-1) {
            currentIndex = 0;
        } else if (prevIndex > imageFilenames.size()-1) {
            prevIndex = 0;
        }
        // changes main image
        pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
        imageBox->image(pic);
        // changes thumbnails
        prev->setImage(getPathFilename(imageFilenames.at(prevIndex), true).c_str());
        next->setImage(getPathFilename(imageFilenames.at(nextIndex), true).c_str());

    } else {
        changeAllInds(false);
        // check to see if at end of list
        if ((nextIndex) < 0) {
            nextIndex = imageFilenames.size()-1;
        } else if (currentIndex < 0) {
            currentIndex = imageFilenames.size()-1;
        } else if (prevIndex < 0) {
            prevIndex = imageFilenames.size()-1;
        }
        // changes main image
        pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
        imageBox->image(pic);
        // changes thumbnails
        prev->setImage(getPathFilename(imageFilenames.at(prevIndex), true).c_str());
        next->setImage(getPathFilename(imageFilenames.at(nextIndex), true).c_str());
    }
    //cout << currentIndex << endl;
    cout << endl;
}
void Viewer::changeAllInds(bool increase) {
    if (increase) {
        currentIndex++; nextIndex++; prevIndex++;
    } else {
        currentIndex--; nextIndex--; prevIndex--;
    }
}
int Viewer::handle(int e) {
    switch(e) {
        case FL_FOCUS:
        case FL_UNFOCUS:
            return 1;
        case FL_KEYBOARD:
            if ( Fl::event_key() == FL_Left) {
                prev->do_callback();
                return(1);
            } else if (Fl::event_key() == FL_Right) {
                next->do_callback();
                return(1);
            }
            return 1;
        case FL_RELEASE:
            do_callback();
            return 1;
    }
    return Fl_Widget::handle(e);
}

这是viewer.h:

#ifndef VIEWER_H
#define VIEWER_H
#include <vector>
#include <string>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include "NavButton.h"
class Viewer : public Fl_Window {
    std::vector<std::string> imageFilenames;
    Fl_Box *imageBox;   // Holds image being shown
    Fl_JPEG_Image *pic; // Image being shown
    NavButton* prev;    // Button to go to previous item
                        //   Image is thumbnail of previous image
    NavButton* next;    // Button to go to next item
                        //   Image is thumbnail of next image
    int currentIndex;   // Index of the image currently shown
    int nextIndex;      // Index of next image
    int prevIndex;      // Index of previous image
    // private helper functions
    std::string imageFolder;
    std::string getPathFilename(std::string filename, bool thumb=false);
public:
    static const int thumbnailSize = 50; // size of NavButton
    static const int borderSize = 10; // size of border between window edge     and widgets
    void navPressed(Fl_Widget* widget);
    // constructor
    Viewer(std::string, std::vector<std::string>, int, int);
    virtual int handle(int e);
    //int key_handle(int e, int key);
    //int mouse_handle(int e);
    void changeAllInds(bool increase);
};
#endif

请让我知道您是否需要更多信息来帮助我,并提前感谢您!

这可能会实现您想要的东西。添加第三个例程进行导航

int Navigate(int key)
{
    if ( key == FL_Left) {
        prev->do_callback();
        return(1);
    } else if (key == FL_Right) {
        next->do_callback();
        return(1);
    }
    return 1;
}

然后更改另外两个来称呼它。在您的处理程序中

int Viewer::handle(int e) {
switch(e) {
    ...
    case FL_KEYBOARD:
        return Navigate(Fl::event_key());
    case FL_RELEASE:
    ...
    }
...

在navpressed中,

...
if (b->getLabel() == "Next Button") {
    ...
    Navigate(FL_Right);
}
else {
    ...
    Navigate(FL_Left);
}