简体   繁体   中英

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

I am using FLTK with C++ to write a program to scroll through a folder of images. I have a next button with the thumbnail for the next image, and the same for the previous button. I want to be able to go through the images by clicking the previous and next buttons as well as using the left and right arrows on the keyboard.

I succeeded in doing this, however not at the same time. When I only write a callback function like so:

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

   viewer->redraw();
}

I can click the respective buttons to go forward and backwards, however when I overload the handle function to handle the keyboard arrows like so:

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);
}

I can use the arrows, however I cannot figure out how to use both arrows and clicking on the buttons. I have tried passing the Fl_Widget *w through to the handle function and back up to the callback, and I was able to click on the buttons, but could no longer use the arrows.

Here is the Viewer.cpp file:

#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);
}

And here is 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

Please let me know if you need any more info to assist me, and thank you in advance!

This may achieve what you want. Add a third routine to do the navigation

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;
}

Then change the other two to call it. In your handler

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

In navpressed,

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM