How can I tab away from a Fl_Button in FLTK? - c++

I have a custom class, CustomButton that extends Fl_Button. On my screen there are a bunch of Fl_Input and CustomButton widgets that I want to be able to navigate between using a tab keypress. Tabbing between input fields works fine, but once a CustomButton gets focus, I can't seem to tab away from it.
Here's my handle function
int CustomButton::handle ( int event )
{
int is_event_handled = 0;
switch (event)
{
case FL_KEYBOARD:
// If the keypress was enter, toggle the button on/off
if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)
{
// Do stuff...
}
is_event_handled = 1;
break;
case FL_FOCUS:
case FL_UNFOCUS:
// The default Fl_Button handling does not allow Focus/Unfocus
// for the button so mark the even as handled to skip the Fl_Button processing
is_event_handled = 1;
break;
default:
is_event_handled = 0;
break;
}
if ( is_event_handled == 1 ) return 1;
return Fl_Round_Button::handle ( event );
}
I am using fltk 1.1.10.

For a very simple, minimal example which demonstrates how to control the focus, please check the navigation.cxx test file.
Maybe your widget did get the focus (check this with Fl::focus()), but it does not show that up (you need to handle the FL_FOCUS and/or FL_UNFOCUS events)?

My problem was my CustomButton::handle() returning 1 after a FL_KEYBOARD event without actually using the tab key press.
Moving is_event_handled = 1 into the if statement lets me consume the FL_Enter keypress only and lets other widgets (i.e. the Fl_Group that controls navigation) take any other keypresses.
Alternatively get rid of the if and replace with something like
switch(Fl::event_key())
{
case FL_Enter:
case FL_KP_Enter:
// Do stuff
is_event_handled = 1;
break;
default:
is_event_handled = 0;
break;
}

Related

How to draw Focus Border to a specific Tab in MFC TabControl

I was trying to Manually Set Focus border to Tabs selected using SetCurSel() API. But While doing so i also wanted to set the Keyboard Focus(Dotted Border Focus around the Tab as shown in Picture). All I could achieve is Tab selection using SetCurSel().
In my project I don't want the TCN_SELCHANGING to be send, that's why I'm using SetCurSel() instead of SetCurFocus() which will invoke TCN_SELCHANGING or TCN_SELCHANGE notification message.
Currently in my code I am overriding LBUTTON down message to take control of Tab Selection and and I would call SetCurSel() from there.
LRESULT TabEx::WindowProc( UINT uMsg_i, WPARAM wParam_i, LPARAM lParam_i )
{
switch( uMsg_i )
{
case WM_LBUTTONDOWN :
{
switch( wParam_i )
{
case MK_LBUTTON:
{
int nIndex = GetCurSel( );
if()// Logic To determine Which Tab to Select
{
// Decide to Select nIndex th Tab
SetCurSel( nIndex );
SendSelChangeNotification( TCN_SELCHANGE );
retrun true;
}
break;
}
}
break;
}
.
.
.
.
}
.
.
}
The issue with the above code is it will change the tab selection but No Focus in changed. I cannot use SetCurFocus() here since I don't want to interfere with TCN_SELCHANGING. Is there any direct Message call or function call to Set the Focus to a specific Tab?

How to change the state of button to clicked in cocos2d-x

I am pretty new to cocos2d-x.I have created a button and i wanted to change the state of the button when i tap the button . i am having trouble changing the state from play to pause similar to a music player.Below is the code.
void Gallery::buttonUI(Size visibleSize,Vec2 origin)
{
button = Button::create("play.png");
//button->loadTextures("pause.png","play.png","pause.png");
button->setPosition(Point((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y-80));
button->setContentSize(Size(100.0f, button->getVirtualRendererSize().height));
button->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type){
switch (type)
{
case Widget::TouchEventType::BEGAN:
break;
case Widget::TouchEventType::ENDED:
CCLOG("Characters: %c %c", 'a', 65);
if (!flag)
Gallery::pauseSong();
else
Gallery::resumeSong();
break;
default:
break;
}
});
this->addChild(button);
}
void Gallery::playSong()
{
CocosDenshion::SimpleAudioEngine::getInstance()->preloadBackgroundMusic("1.mp3");
CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("1.mp3");
flag = false;
}
void Gallery::pauseSong()
{
CocosDenshion::SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
flag = true;
}
void Gallery::resumeSong()
{
CocosDenshion::SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
flag = false;
}
I don’t know of such methods for the ui::Button. But I don’t see the use of specific ui::Button items (capinsets, different methods for different touch events etc.) in your method also.
So, I think the MenuItemImage is better in your case:
bool flag = true;
MenuItemImage *button = MenuItemImage::create("play.png", "play_pressed.png", CC_CALLBACK_0(Gallery::playSong, this));
button->setPosition(Vec2((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y-80)); // better is use Vec2, Point can be ambiguous
Menu* menu = Menu::create(button, NULL); // add created button on Menu
menu ->setPosition(0,0);
this->addChild(menu);
And then set the images in handler pressing:
void Gallery::playSong()
{
if(flag)
{
// preload better move to AppDelegate.cpp
// CocosDenshion::SimpleAudioEngine::getInstance()->preloadBackgroundMusic("1.mp3");
flag = false;
CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("1.mp3");
button->setNormalImage(Sprite::create(“pause.png”));
button->setSelectedImage(Sprite::create(“pause_pressed.png”)); // if you use selected image
}
else
{
flag = true;
CocosDenshion::SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
button->setNormalImage(Sprite::create(“play.png”));
button->setSelectedImage(Sprite::create(“play_pressed.png”));
}
}
In cocos 3.x use property: setHighlighted(bool)
Example:
When press a key: button->setHighlighted(true);
When release the key:
button->setHighlighted(false);

event check only when clicked on a button

I have a simple test script, which it meant to change a boolean when the user clicks within the dimensions of the button but it is not working.
I approached it like so:
while( SDL_PollEvent( &event ) ) {
switch( event.type ){
case SDL_QUIT: quit = true; break;
case SDL_MOUSEMOTION: mouseX = event.motion.x; mouseY = event.motion.y; break;
case SDL_MOUSEBUTTONDOWN: click = true;
}
}
Button btn_settings(btn_x,btn_y);
if(btn_settings.IsIn(mouseX,mouseY)){
btn_settings.RenderImg(menu,screen,"button_on.png","Settings");
if(click){
quit = true;
}
} else {
btn_settings.RenderImg(menu,screen,"button.png","Settings");
}
The problem is if i click any where then click equals true, then if the mouse is over the quit button it exits even if the button wasn't pressed when over the button.
I'm confused how i can make it work properly.
Try handling your "click" event on mouse button up instead. I've never used SDL but I suspect there is a SDL_MOUSEBUTTONUP defined. Otherwise you don't know if they want to perform a drag operation or if they moved the mouse someplace else before letting go of the mouse button.

how to get the name of a button created by QDialogButtonBox?

I'm trying get all the button child widgets of a window. The buttons were created through QDialogButtonBox. How do I get the which one is the cancel/ok/save button?
I have:
QWidget *pWin = QApplication::activeWindow();
QList<QPushButton *> allPButtons = pWin->findChildren<QPushButton *>();
QListIterator<QPushButton*> i(allPButtons);
while( i.hasNext() )
{
//identify which button is cancel/ok/save button here
/*Note: This is where I'm having trouble, getting the text of the
button here returns NULL. Any other way of Identifying which is
which?
Is it a special case when buttons are created through QDialogButtonBox?
*/
}
You should use the QDialogButtonBox::button() method, to get the button of the corresponding role.
For instance :
QPushButton* pOkButton = pButtonBox->button(QDialogButtonBox::Ok);
QPushButton* pCancelButton = pButtonBox->button(QDialogButtonBox::Cancel);
// and so on...
Generally speaking, I would say it's a bad idea to find a button from it's text, as this text might change when you app is internationalized.
One way is by text parameter from constructor such as QPushButton(const QString & text, QWidget * parent = 0):
QPushButton* buttonSave = new QPushButton("Save");
// etc..
while( i.hasNext() )
{
//identify which button is cancel/ok/save button here
if(i.next()->text() == "Save") {
// do something to save push button
}
}
Another alternative solution:
Use QDialogButtonBox's buttons function to return a list of all the buttons that have been added to the button box, then iterate over the list and identify each button using QDialogButtonBox's standardButton.
auto buttons = ui->buttonBox->buttons();
for (auto button : buttons) {
switch (ui->buttonBox->standardButton(button)) {
case QDialogButtonBox::Ok:
// do something
break;
case QDialogButtonBox::Cancel:
// do something
break;
case QDialogButtonBox::Save:
// do something
break;
default:
break;
}
}
For non-standard buttons
Map each button to an enum:
.h file:
private:
enum class NonStandardButton { Undo, Redo };
// map of non-standard buttons to enum class NonStandardButton
QHash<QAbstractButton*, NonStandardButton> buttonsMap;
.cpp file:
// in constructor
auto undoQPushButton =
ui->buttonBox->addButton("Undo", QDialogButtonBox::ActionRole);
auto redoQPushButton =
ui->buttonBox->addButton("Redo", QDialogButtonBox::ActionRole);
buttonsMap.insert(undoQPushButton, NonStandardButton::Undo);
buttonsMap.insert(redoQPushButton, NonStandardButton::Redo);
Then use QDialogButtonBox::NoButton to identify non-standard buttons:
switch (ui->buttonBox->standardButton(button)) {
case QDialogButtonBox::NoButton:
switch (buttonsMap.value(button)) {
case NonStandardButton::Undo:
// do something
break;
case NonStandardButton::Redo:
// do something
break;
default:
break;
}
default:
break;
}

GLUT pop-up menus

Is it easy to create GLUT pop-up menus for my OpenGL application? If yes, how?
Creating and using pop-up menus with GLUT is very simple. Here is a code sample that creates a pop-up menu with 4 options:
// Menu items
enum MENU_TYPE
{
MENU_FRONT,
MENU_SPOT,
MENU_BACK,
MENU_BACK_FRONT,
};
// Assign a default value
MENU_TYPE show = MENU_BACK_FRONT;
// Menu handling function declaration
void menu(int);
int main()
{
// ...
// Create a menu
glutCreateMenu(menu);
// Add menu items
glutAddMenuEntry("Show Front", MENU_FRONT);
glutAddMenuEntry("Show Back", MENU_BACK);
glutAddMenuEntry("Spotlight", MENU_SPOT);
glutAddMenuEntry("Blend 'em all", MENU_BACK_FRONT);
// Associate a mouse button with menu
glutAttachMenu(GLUT_RIGHT_BUTTON);
// ...
return;
}
// Menu handling function definition
void menu(int item)
{
switch (item)
{
case MENU_FRONT:
case MENU_SPOT:
case MENU_DEPTH:
case MENU_BACK:
case MENU_BACK_FRONT:
{
show = (MENU_TYPE) item;
}
break;
default:
{ /* Nothing */ }
break;
}
glutPostRedisplay();
return;
}