按钮处理(伪代码/c)

按钮处理(伪代码/c),c,button,pseudocode,C,Button,Pseudocode,我有一个按钮,我希望它能根据用户的动作做出反应。 这是: 你可以看到它有4种不同的状态。第一个是当没有执行任何特定操作时(NONE),第二个是当鼠标指针悬停在按钮上时(HOVER),第三个是当鼠标当前正在单击按钮时(ONCLICK),最后一个是当按钮被单击时(已选择) 即使我们不太在意,按钮图如下所示: 这些状态显示为枚举: enum button_states { NONE, HOVER, ONCLICK, SELECTED, BSTATE_LAST }; 现在我尝试了一些代码来更改按

我有一个按钮,我希望它能根据用户的动作做出反应。 这是:

你可以看到它有4种不同的状态。第一个是当没有执行任何特定操作时(
NONE
),第二个是当鼠标指针悬停在按钮上时(
HOVER
),第三个是当鼠标当前正在单击按钮时(
ONCLICK
),最后一个是当按钮被单击时(
已选择

即使我们不太在意,按钮图如下所示:

这些状态显示为枚举:

enum button_states  { NONE, HOVER, ONCLICK, SELECTED, BSTATE_LAST };
现在我尝试了一些代码来更改按钮的状态,这些代码是在无限循环中执行的。我有一个变量
prevState
,它保存最后一次单击之前的状态,还有一个变量
previouslyClicked
,如果单击在最后一次循环迭代中处于活动状态,则值1,否则值0

if (CursorIsOnTheButton())  {
    if (LeftClickIsActive())    {
        if (actualState != ONCLICK)
            prevState = actualState ;
        previouslyClicked = 1;
        actualState = ONCLICK;
    }
    else if (prevState == SELECTED && previouslyClicked) {
        actualState = HOVER;
        prevState = NONE;
        previouslyClicked = 0;
    }
    else if (prevState == HOVER && previouslyClicked)   {
        actualState = SELECTED;
        prevState = NONE;
        previouslyClicked = 0;
    }
    else
        actualState  = HOVER;
}
else if (actualState != SELECTED)
    actualState = NONE;
除了选定的状态外,它工作正常:按钮永远不会进入该状态


我做错了什么?

编写代码是为了将所选内容从任何一个块中排除:

if (CursorIsOnTheButton())  {
    if (LeftClickIsActive())    {

        //if execution flow ever goes into this section...
        //(i.e. if SELECTED is set here, because you are in this block, it cannot be recognized by the 
        //else if block, because it can only go in there if it did NOT go into this one.)
    }
}
//...it will never go into the else if
else if (actualState != SELECTED)
    actualState = NONE;
修改代码以将选定状态包括在与其他状态相同的块中

将此代码段添加到if块:

else if (actualState == SELECTED)   {

    //do something 
} 

解决问题

编写代码是为了将所选内容从任何一个块中排除:

if (CursorIsOnTheButton())  {
    if (LeftClickIsActive())    {

        //if execution flow ever goes into this section...
        //(i.e. if SELECTED is set here, because you are in this block, it cannot be recognized by the 
        //else if block, because it can only go in there if it did NOT go into this one.)
    }
}
//...it will never go into the else if
else if (actualState != SELECTED)
    actualState = NONE;
修改代码以将选定状态包括在与其他状态相同的块中

将此代码段添加到if块:

else if (actualState == SELECTED)   {

    //do something 
} 

解决问题

创建这样一个函数。。。无论何时,只要您将某个对象标记为选定对象,就可以将最近选定的按钮作为第三个参数来调用它

void ClearOthers("Array of buttons" buttons[], int amountOfButtons, int selected)
{
     for(int i = 0; i < amountOfButtons; i++)
         if(i != selected)
             button[i].State = NONE
}

创建一个这样的函数。。。无论何时,只要您将某个对象标记为选定对象,就可以将最近选定的按钮作为第三个参数来调用它

void ClearOthers("Array of buttons" buttons[], int amountOfButtons, int selected)
{
     for(int i = 0; i < amountOfButtons; i++)
         if(i != selected)
             button[i].State = NONE
}

好吧,我也要试一试。我建议重新组织状态变量。去掉实际的和以前的状态,只使用一个
state
作为按钮外观,这将在我们的伪代码片段中设置。摆脱先前点击的
按钮(相当于
状态==ONCLICK
),并引入按下的
按钮,如果按下按钮则为true,如果未按下则为false:

if (CursorIsOnTheButton())  {
    if (LeftClickIsActive())  {
        if (state != ONCLICK) pressed = !pressed;
        state = ONCLICK;
    } else {
        state = (pressed) ? SELECTED : HOVER;
    }
} else {
    state = (pressed) ? SELECTED : NONE;
}
ONCLICK
状态在这里起双重作用;它标记了“刚刚点击”的状态,并确保在长时间按下鼠标按钮时不会打开和关闭按钮。所有其他状态由一个简单的逻辑确定:

pressed?      in button?     clicking?      state
------------  ------------  ------------  ------------
true          dontcare      dontcare       SELECTED
false         true          true           ONCLICK
false         true          false          HOVER
false         false         dontcare       NONE
这种方法的优点是,您可以在按下
时检查按钮的按下状态,否则必须检查状态


它仍然只是伪代码,这意味着我当然还没有测试它。

好吧,我也要试试。我建议重新组织状态变量。去掉实际的和以前的状态,只使用一个
state
作为按钮外观,这将在我们的伪代码片段中设置。摆脱先前点击的
按钮(相当于
状态==ONCLICK
),并引入按下的
按钮,如果按下按钮则为true,如果未按下则为false:

if (CursorIsOnTheButton())  {
    if (LeftClickIsActive())  {
        if (state != ONCLICK) pressed = !pressed;
        state = ONCLICK;
    } else {
        state = (pressed) ? SELECTED : HOVER;
    }
} else {
    state = (pressed) ? SELECTED : NONE;
}
ONCLICK
状态在这里起双重作用;它标记了“刚刚点击”的状态,并确保在长时间按下鼠标按钮时不会打开和关闭按钮。所有其他状态由一个简单的逻辑确定:

pressed?      in button?     clicking?      state
------------  ------------  ------------  ------------
true          dontcare      dontcare       SELECTED
false         true          true           ONCLICK
false         true          false          HOVER
false         false         dontcare       NONE
这种方法的优点是,您可以在按下
时检查按钮的按下状态,否则必须检查状态


当然,这仍然只是伪代码,这意味着我还没有测试它。

基于vmp答案和您的大力帮助,我解决了这个问题

我使用vmp的变量
actualSelected
beingClicked
,但不是布尔值,来存储所选按钮和单击按钮的ID

让我解释一下,我想我没有给你留下足够的信息来解决这件事。我不仅有一个按钮,还有一组按钮,
按钮[NBUTTONS]
是它们的状态,它们的行为应该和单选按钮完全一样

for (int i = 0; i < NBUTTONS; i++)  {
    if (IsMouseOnButton(button[i])  {
        if (LeftClickIsActive())    {
            beingClicked = i;
            buttons[i] = ONCLICK;
        }
        else if (beingClicked == i) {
            actualSelected = i;
            beingClicked = -1;
            for (int j = 0; j < NBUTTONS; j++)
                buttons[i] = NONE;
            buttons[i] = SELECTED;
        }
        else if (actualSelected != i)   {
            buttons[i] = HOVER;
        }
    }
    else if (selected != i)
        buttons[i] = NONE;
}
for(int i=0;i
基于vmp答案和您的大力帮助,我解决了这个问题

我使用vmp的变量
actualSelected
beingClicked
,但不是布尔值,来存储所选按钮和单击按钮的ID

让我解释一下,我想我没有给你留下足够的信息来解决这个问题。我不仅有一个按钮,还有一系列按钮,
按钮[NBUTTONS]
是它们的状态,它们的行为应该和单选按钮一模一样

for (int i = 0; i < NBUTTONS; i++)  {
    if (IsMouseOnButton(button[i])  {
        if (LeftClickIsActive())    {
            beingClicked = i;
            buttons[i] = ONCLICK;
        }
        else if (beingClicked == i) {
            actualSelected = i;
            beingClicked = -1;
            for (int j = 0; j < NBUTTONS; j++)
                buttons[i] = NONE;
            buttons[i] = SELECTED;
        }
        else if (actualSelected != i)   {
            buttons[i] = HOVER;
        }
    }
    else if (selected != i)
        buttons[i] = NONE;
}
for(int i=0;i
可能是因为在一个分支中设置了先前单击的
,然后在另一个互斥分支中选中了
左键单击