如何根据 QListWidget 上的选择在 QStackedWidget 上显示正确的 GUI

How to show the correct GUI on a QStackedWidget depending on the choice on a QListWidget

如何根据 QListWidget 上的选择在 QStacked Widget 上正确显示正确的用户界面?

下面我有一个 QDialog 包含:

1 QListWidget

1 QStackedWidget

根据列表的 selected 选择,例如,Vessel Position System 或 Output,界面应如下所示,但问题是不幸的是 QStacked Widget 目前没有改变 QWidgets 因为我 select QListWidgets 实际上没有显示任何东西。 A Minimal Verifiable Example can be found here。只需克隆它即可运行:

代码下方:

optionsdialog.h

#include <QDialog>
#include "vesselpossystemwidget.h"
#include "outputdialog.h"
#include "sonarsystem.h"
namespace Ui {
class OptionsDialog;
}

class OptionsDialog : public QDialog
{
    Q_OBJECT
public:
    explicit OptionsDialog(QWidget *parent = nullptr);
    ~OptionsDialog();

private:
    Ui::OptionsDialog *ui;
    VesselPosSystemWidget *mVesPos;
    OutputDialog *mOutput;
    SonarSystem *mSonar;
};

#endif // OPTIONSDIALOG_H

optionsdialog.h

#include "optionsdialog.h"
#include "ui_optionsdialog.h"

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog)
{
    ui->setupUi(this);
    switch(ui->stackedWidget->currentIndex()){

      case 0:
        // Go to positioning system
        mVesPos = new VesselPosSystemWidget();
        mVesPos->show();
        break;
      case 1:
        // Go to sonar set up...
        mSonar = new SonarSystem();
        mSonar->show();
        break;
      case 2:
        // Go to output
        mOutput = new OutputDialog();
        mOutput->show();
        break;
      default:
        break;
    }
}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

vesselposwidget.h

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class VesselPosSystemWidget; }
QT_END_NAMESPACE

class VesselPosSystemWidget : public QWidget
{
    Q_OBJECT

public:
    VesselPosSystemWidget(QWidget *parent = nullptr);
    ~VesselPosSystemWidget();

private:
    Ui::VesselPosSystemWidget *ui;
};
#endif // VESSELPOSSYSTEMWIDGET_H

vesselposwidget.cpp

#include "vesselpossystemwidget.h"
#include "ui_vesselpossystemwidget.h"

VesselPosSystemWidget::VesselPosSystemWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::VesselPosSystemWidget)
{
    ui->setupUi(this);
}

VesselPosSystemWidget::~VesselPosSystemWidget()
{
    delete ui;
}

output.h

#include <QDialog>

namespace Ui {
class OutputDialog;
}

class OutputDialog : public QDialog
{
    Q_OBJECT

public:
    explicit OutputDialog(QWidget *parent = nullptr);
    ~OutputDialog();

private:
    Ui::OutputDialog *ui;
};

#endif // OUTPUTDIALOG_H

output.cpp

#include "outputdialog.h"
#include "ui_outputdialog.h"

OutputDialog::OutputDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OutputDialog)
{
    ui->setupUi(this);
}

OutputDialog::~OutputDialog()
{
    delete ui;
}

到目前为止我做了什么:

我正在探索使用 QStacked Widget 的可能性,因为我对它不是很熟悉并且想通过一个基本示例进行练习。我在调查 and also this one

我还从 same 源中阅读了更多文档。但是我并不能完全清楚地理解这个特定小部件的使用。

除此之外,我尝试了一个 switch - case 循环,正如我在上面的代码中所示,但我不确定为什么它不起作用

谁能提供一些指导,说明如何根据 QListWidget 上的选择在 QStacked Widget 上正确显示正确的用户界面?解决此问题的任何方向表示赞赏。

QStackedWidget 是一个容器小部件,用于多个子小部件,一次只显示其中一个。

因此,应立即添加所有子窗口小部件。

currentIndex 可用于控制其中哪些当前应该可见。

A minimal reproducible example 来证明这一点 – testQStackedWidgetMin.cc:

// Qt header:
#include <QtWidgets>

// main application
int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QWidget qWinMain;
  QHBoxLayout qHBox;
  QListWidget qList;
  qList.addItem(QString::fromUtf8("Config. 1"));
  qList.addItem(QString::fromUtf8("Config. 2"));
  qList.addItem(QString::fromUtf8("Output"));
  qHBox.addWidget(&qList);
  QStackedWidget qStack;
  QLabel qConfig1(QString::fromUtf8("<b>Config Page 1</b>"));
  qStack.addWidget(&qConfig1);
  QLabel qConfig2(QString::fromUtf8("<b>Config Page 2</b>"));
  qStack.addWidget(&qConfig2);
  QLabel qOutput(QString::fromUtf8("<b>Output Page</b>"));
  qStack.addWidget(&qOutput);
  qHBox.addWidget(&qStack, 1);
  qWinMain.setLayout(&qHBox);
  qWinMain.show();
  // install signal handlers
  QObject::connect(&qList, &QListWidget::currentRowChanged,
    &qStack, &QStackedWidget::setCurrentIndex);
  // runtime loop
  return app.exec();
}

输出:

注:

这个样本的基本语句之一是信号槽连接:

  QObject::connect(&qList, &QListWidget::currentRowChanged,
    &qStack, &QStackedWidget::setCurrentIndex);

QStackedWidget qStackQListWidget::currentRowChanged signal of the QListWidget qList is connected to the QStackedWidget::setCurrentIndex()函数。 这负责为 qList.

中的任何(交互式)行更改更新 qStack

根据 OP 的意图,一个不是那么小的样本 – testQStackedWidget.cc:

// Qt header:
#include <QtWidgets>

class Config1: public QWidget {
  private:
    // GUI
    QVBoxLayout _qVBox;
    QLabel _qLbl;

  public:
    // constructor.
    Config1();
    // destructor.
    virtual ~Config1() = default;
    // disabled:
    Config1(const Config1&) = delete;
    Config1& operator=(const Config1&) = delete;
};


Config1::Config1(): QWidget()
{
  // setup GUI
  _qLbl.setText(QString::fromUtf8("<b>Config Page 1</b>"));
  _qVBox.addWidget(&_qLbl);
  setLayout(&_qVBox);
}

class Config2: public QWidget {
  private:
    // GUI
    QVBoxLayout _qVBox;
    QLabel _qLbl;

  public:
    // constructor.
    Config2();
    // destructor.
    virtual ~Config2() = default;
    // disabled:
    Config2(const Config2&) = delete;
    Config2& operator=(const Config2&) = delete;
};

Config2::Config2(): QWidget()
{
  _qLbl.setText(QString::fromUtf8("<b>Config Page 2</b>"));
  _qVBox.addWidget(&_qLbl);
  setLayout(&_qVBox);
}

class Output: public QWidget {
  private:
    // GUI
    QVBoxLayout _qVBox;
    QLabel _qLbl;

  public:
    // constructor.
    Output();
    // destructor.
    virtual ~Output() = default;
    // disabled:
    Output(const Output&) = delete;
    Output& operator=(const Output&) = delete;
};

Output::Output(): QWidget()
{
  _qLbl.setText(QString::fromUtf8("<b>Output Page</b>"));
  _qVBox.addWidget(&_qLbl);
  setLayout(&_qVBox);
}

class OptionDialog: public QDialog {
  private:
    // GUI
    QHBoxLayout _qHBox;
    QListWidget _qList;
    QStackedWidget _qStack;
    Config1 _qConfig1;
    Config2 _qConfig2;
    Output _qOutput;

  public:
    // constructor.
    OptionDialog();
    // destructor.
    virtual ~OptionDialog() = default;
    // disabled:
    OptionDialog(const OptionDialog&) = delete;
    OptionDialog& operator=(const OptionDialog&) = delete;
};

OptionDialog::OptionDialog(): QDialog()
{
  // setup GUI
  _qList.addItem(QString::fromUtf8("Config. 1"));
  _qList.addItem(QString::fromUtf8("Config. 2"));
  _qList.addItem(QString::fromUtf8("Output"));
  _qHBox.addWidget(&_qList);
  _qStack.addWidget(&_qConfig1);
  _qStack.addWidget(&_qConfig2);
  _qStack.addWidget(&_qOutput);
  _qHBox.addWidget(&_qStack, 1);
  setLayout(&_qHBox);
  // install signal handlers
  QObject::connect(&_qList, &QListWidget::currentRowChanged,
    &_qStack, &QStackedWidget::setCurrentIndex);
}

// main application
int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  OptionDialog qDlgOpt;
  qDlgOpt.show();
  // runtime loop
  return app.exec();
}

输出:


CMakeLists.txt,我用于创建 VisualStudio 解决方案:

project(QStackedWidget)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#set(CMAKE_CXX_STANDARD 17)
#set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Qt5Widgets CONFIG REQUIRED)

include_directories("${CMAKE_SOURCE_DIR}")

add_executable(testQStackedWidgetMin
  testQStackedWidgetMin.cc)

target_link_libraries(testQStackedWidgetMin
  Qt5::Widgets)

add_executable(testQStackedWidget
  testQStackedWidget.cc)

target_link_libraries(testQStackedWidget
  Qt5::Widgets)