Search code examples
c++qtqwidgetqtguiqt-events

delay in displaying QStackedWidget Item in qt


I am using QStackedWidget item. But for the first time it is taking time and after a while it is working properly.

mymainwindow::mymainwindow() : QMainWindow()
{

    stack = new QStackedWidget();
    list = new QListWidget();
    stack->addWidget(new QLineEdit("Hello U have clicked the first menu"));
    stack->addWidget(new QLineEdit("Second ListWidget Item"));
    stack->addWidget(new QLineEdit("Last Widget Item"));

    widget = new QWidget();
    QLabel *label = new QLabel("Main Window");

    list->addItem("New Item 1");
    list->addItem("New Item 2");
    list->addItem("New Item 3");
    list->setFixedSize(200,100);

    QVBoxLayout *vertical = new QVBoxLayout();
    vertical->addWidget(label);
    vertical->addWidget(list);
    vertical->addWidget(stack);
    stack->hide();

    widget->setLayout(vertical);
    setCentralWidget(widget);
}

void mymainwindow::keyPressEvent(QKeyEvent *event)
{

    switch (event->key()) {

    case Qt::Key_Down:
        connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));
        break;
    case Qt::Key_Up:
        connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));
        break;
    case Qt::Key_Enter:
        stack->show();
        break;
    case Qt::Key_Escape:
        stack->hide();
        break;

    }
}

Solution

  • Well :

    • You are overriding QMainWindow::keyPressEvent(QKeyEvent *event) and completely disregarding the default implementation.
    • Qobject::connect at each key press is a mistake. You seem to have your own interpretation of what it does. read the docs
    • You must not listen to key press of the main window to know items of the listwidget are changing.
    • The proper way of shortcuts is to add a Qaction, and then associate a shortcut to this action. Why? If the widgets inside stack need to receive "Enter" key events (like a QButton), your UI will be completely bogus because you are manipulating the visibility at the same time.

    Basically what you want is to move connection to the constructor of your window, and to make sure the key events are always processed

    mymainwindow::mymainwindow() : QMainWindow()
    {
    
        stack = new QStackedWidget();
        list = new QListWidget();
        stack->addWidget(new QLineEdit("Hello U have clicked the first menu"));
        stack->addWidget(new QLineEdit("Second ListWidget Item"));
        stack->addWidget(new QLineEdit("Last Widget Item"));
    
        widget = new QWidget();
        QLabel *label = new QLabel("Main Window");
    
        list->addItem("New Item 1");
        list->addItem("New Item 2");
        list->addItem("New Item 3");
        list->setFixedSize(200,100);
    
        QVBoxLayout *vertical = new QVBoxLayout();
        vertical->addWidget(label);
        vertical->addWidget(list);
        vertical->addWidget(stack);
        stack->hide();
    
        connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));
        list->setCurrentRow(2);//last, to test 
    
        widget->setLayout(vertical);
        setCentralWidget(widget);
    }
    
    
    void mymainwindow::keyPressEvent(QKeyEvent *event)
    {
    
        switch (event->key()) {
    
        case Qt::Key_Enter:
            stack->show();
            break;
        case Qt::Key_Escape:
            stack->hide();
            break;
        }
        QMainWindow::keyPressEvent(event);
    }
    

    Still, this is a nightmare.

    Edit:
    If the focus is on the list widget, changing rows in the list with the keyboard will trigger the signal.