处理不同的GUI状态

时间:2018-10-08 07:22:49

标签: c++ qt user-interface button design-patterns

因此,我想在Qt / cpp中为服务器创建gui接口,该服务器可以处于许多不同的状态,并且根据其状态,gui中的按钮需要进行不同的设置,例如: GUI:

button1-未被选中并允许点击

button2-禁用(显示为灰色)

button3-禁用

button3-禁用

然后单击按钮1 GUI:

button1-选中

button2-可以点击

button3-可以单击

button3-可以单击

但是例如,如果服务器处于不同状态,并且您通过gui连接,则按钮应如下所示:

GUI:

button1-选中

button2-可以点击

button3-不能点击

button3-不能点击

是否存在一些直观的既定模式/处理方式?这里最大的问题是,如果服务器具有许多不同的状态,则需要在许多不同的配置中设置按钮。我唯一能想到的就是将所有按钮的状态映射到特定状态,但是……有很多按钮和状态。

3 个答案:

答案 0 :(得分:0)

您可以尝试使用标志,其想法是,当事件发生并且您希望GUI更改时,您可以设置标志,然后在循环中调用该标志。您可以在下面看到一般的想法和概念。

如果更改标志的状态,将获得不同的输出,并且它将遍历侦听事件,只需为处于不同状态的每个事件编写GUI代码。

#include <iostream>
using namespace std;

int getserverstatusfunction() {/*your code to check server status returns 0,1 or 2*/
    return 0;
}
UI.button.click(true) { getresult = 1; }; //change the UI state when the button is clicked

int main() {
    bool running;
    while (running){
    int getresult = getserverstatusfunction();

    if (getresult == 0)
    {
        cout << "Draw flag one interface code\n";
    }
    else if (getresult == 1)
    {
        cout << "Draw flag two interface code\n";
    }
    else {
        cout << "Draw flag three interface code\n";
    }
    system("pause");
    return 0;
}

答案 1 :(得分:0)

启用/禁用按钮UI逻辑可能非常脏,难以管理和跟踪。另外,有时我们想要处于特定状态,并希望进行一些小的更改,例如仅更改一个按钮的状态。这是一种方法。它是通用的,但是您必须使用UI相应地删除它。

#include <iostream>

class UIState
{
protected:
    bool btn1;
    bool btn2;
    bool btn3;

public:
    UIState()
    {
        btn1 = false;
        btn2 = false;
        btn3 = false;
    }

    virtual void setBtn1State(bool new_state)
    {
        btn1 = new_state;

        std::cout << btn1 << btn2 << btn3 << std::endl;
    };
    virtual void setBtn2State(bool new_state)
    {
        btn2 = new_state;

        std::cout << btn1 << btn2 << btn3 << std::endl;
    };
    virtual void setBtn3State(bool new_state)
    {
        btn3 = new_state;

        std::cout << btn1 << btn2 << btn3 << std::endl;
    };
};

class UIStateAllEnabled : public UIState
{

public:
    UIStateAllEnabled()
    {
        btn1 = true;
        btn2 = true;
        btn3 = true;

        std::cout << btn1 << btn2 << btn3 << std::endl;
    }

};

class UIStateAllDisabled : public UIState
{

public:
    UIStateAllDisabled()
    {
        btn1 = false;
        btn2 = false;
        btn3 = false;

        std::cout << btn1 << btn2 << btn3 << std::endl;
    }

};

class UI
{
    UIState * currentState;

public:
    UI()
    {
        currentState = NULL;
    }

    ~UI()
    {
        if (currentState != NULL)
        {
            delete currentState;
            std::cout << "deleted current state" << std::endl;
        }
    }

    void setState(UIState * new_state)
    {
        // should also check for if already current state?

        UIState * prevState = currentState;
        currentState = new_state;

        if (prevState != NULL)
        {
            delete prevState;

            std::cout << "deleted previous state" << std::endl;
        }
    }

    void setBtn1State(bool new_state)
    {
        currentState->setBtn1State(new_state);
    };

    void setBtn2State(bool new_state)
    {
        currentState->setBtn2State(new_state);
    };

    void setBtn3State(bool new_state)
    {
        currentState->setBtn3State(new_state);
    };
};


int main()
{
    UI ui;

    // enable all buttons
    ui.setState(new UIStateAllEnabled);

    // Now say you want to change state of a particular button within this state.
    ui.setBtn1State(false);
    ui.setBtn3State(false);

    // switch to a completely new state, disable all buttons
    ui.setState(new UIStateAllDisabled);

    // customize within that sate
    ui.setBtn3State(true);

    return 0;
}

答案 2 :(得分:0)

我发现执行此操作的最佳方法就是使用一个插槽方法(例如UpdateAllButtonStates(),它会更新您所有的按钮和复选框,例如:

void MyWindow::UpdateAllButtonStates()   // Qt-slot method
{
   const bool shouldButton1BeEnabled = [...];
   button1->setEnabled(shouldButton1BeEnabled);

   const bool shouldButton2BeEnabled = [...];
   button2->setEnabled(shouldButton2BeEnabled);

   [... and so on for all enables and checked/unchecked states in your GUI]
}

...则您的程序的内部状态以任何可能需要更新GUI中的一个或多个按钮/复选框的方式发生任何更改,显式调用此方法或设置将调用它的信号/插槽连接时为你。

这样做的好处是操作简单-通过这种方法,可以确保在任何内部状态更改后,GUI窗口小部件都可以更新到期望的状态,这很简单,因为只有一个代码-编写和调试的路径。另一种选择(试图为程序中的每个可能状态更改提供正确的过渡行为)迅速导致难以解决的复杂性,以及无尽的调试和拖拉操作。

您可能会认为缺点是效率低下-毕竟,即使在任何情况下,我们都在更新所有按钮,尽管其中只有一个可能已更改-但是Qt的代码足够聪明,可以在一个按钮上调用setEnabled(false)已经禁用的按钮是无操作的(同样在已启用的按钮上调用setEnabled(true),依此类推),因此重绘窗口小部件像素的重量级代码仅在窗口小部件的状态实际改变时才执行

UpdateAllButtonStates()中用于计算shouldButton1BeEnabled等的逻辑确实执行了很多,但是通常最终都是非常琐碎的逻辑,因此结果并不重要。但是,如果由于某种原因逻辑变得昂贵,则可以选择使用异步执行和布尔“脏位”来降低UpdateAllButtonStates()的执行频率,例如:

void MyWindow::ScheduleUpdateAllButtonStates()   // Qt-slot method
{
   if (_dirtyBit == false)
   {
      _dirtyBit = true;
      QTimer::singleShot(0, this, SLOT(UpdateAllButtonStates()));
   }
}

void MyWindow::UpdateAllButtonStates()
{
   if (_dirtyBit == false) return; 
   _dirtyBit = false;

   // Update button enables/checked states as previously, here
}

...然后让您所有的内部状态更改代码都调用ScheduleUpdateAllButtonStates(),而不是直接调用UpdateAllButtonStates();优点在于,即使ScheduleUpdateAllButtonStates()连续被调用500次,也只会导致UpdateAllButtonStates()在Qt事件循环的下一次迭代期间被调用一次。