我正在尝试学习并构建一个小型扫雷gui应用程序,这是这样的:c++ - 如何在Qt的CentralWidget中用QLabel替换QPushButton?-LMLPHP

我要做的下一件事是单击一个按钮后,该按钮将设置为hide(),并且QLabel将出现在同一位置。

我的代码是这样的:
。H

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void setUI();
    void clickedBtnInfo();

private:
    Ui::MainWindow *ui;

    QWidget *centralWidget;
    QGridLayout *centralLayout;
    QPushButton *btn[81];
    QPushButton *btnSender;
    QLabel *lbl[81];
    QString clickedBtnName;

private slots:
    void btnClicked();
};


.cpp

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

    centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    lbl[81] = new QLabel(centralWidget);
    setUI();

    for(int i = 0; i < 81; i++) {
        connect(btn[i], SIGNAL(clicked(bool)), btn[i], SLOT(hide()));
        connect(btn[i], SIGNAL(clicked(bool)), this, SLOT(btnClicked()));
    }

    centralWidget->setLayout(centralLayout);
}

void MainWindow::setUI()
{
    ...
    centralLayout = new QGridLayout(centralWidget);
    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j++) {
            centralLayout->addWidget(btn[j + i * 9], 0 + i, j);
            centralLayout->setSpacing(0);
        }
    }
    ...
}

void MainWindow::clickedBtnInfo()
{
    btnSender = qobject_cast<QPushButton*>(sender());
    clickedBtnName = btnSender->objectName();
}

void MainWindow::btnClicked()
{
    clickedBtnInfo();
    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j++) {
            if(btn[j + i * 9]->objectName() == clickedBtnName) {
                centralLayout->addWidget(lbl[j + i * 9], 0 + i, j);
                centralLayout->setSpacing(0);
            }
        }
    }
}


当我运行它并单击其中一个按钮时,该应用程序仅强制退出(The program has unexpectedly finished.
那么,如何解决此问题并在单击后用QPushButton替换QLabel?谢谢。

最佳答案

@ G.M正确指出了代码为何导致崩溃的问题。 -lbl[81] = new QLabel(centralWidget);仅创建1个标签,并将其放置在第81个数组字段中。一次有2个错误:


如果数组的长度为81个元素,则它们的编号为:0, 1, ..., 79, 80。最后一个元素是80,因为您从0开始计数。因此无法将某些内容放置在位置81
要实际创建81个新标签,您必须循环创建它们:


样例代码:

for(int i = 0; i < 81; i++) { //goes from 0 to 80
    lbl[i] = new QLabel(centralWidget);
    lbl[i]->setObjectName(QStringLiteral("Label %1").arg(i));
}


第二行为每个标签指定一个自定义名称。有关详细信息,请参见QString::arg



另一个提示:避免使用C数组,除非您需要高性能/低内存(在您的示例中不是这种情况)。相反,请尝试使用Qt容器类之一,例如QListQVector。 (您也可以使用std::vector等,但是在使用Qt时,我建议使用Qt容器)

对于您的情况,我建议使用QVector,因为它在固定大小的数组上表现最佳。通过这两个更改,将代码更新为:

class MainWindow : public QMainWindow
{
    //...
private:
    Ui::MainWindow *ui;

    QWidget *centralWidget;
    QGridLayout *centralLayout;
    QVector<QPushButton> btn;
    QPushButton *btnSender;
    QVector<QLabel> lbl;
    QString clickedBtnName;
};


在cpp文件中,更新创建数组的部分:

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

    centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    lbl.resize(81);
    for(int i = 0; i < lbl.size(); i++) { //goes from 0 to 80
        lbl[i] = new QLabel(centralWidget);
        lbl[i]->setObjectName(QStringLiteral("Label %1").arg(i));
    }
    setUI();

    //...
}

void MainWindow::setUI()
{
    //keep your code, but remember to prepare the btn vector with:
    btn.resize(81);

    //then you can fill the vector just like you are used to:
    btn[0] = ui->btn0;
    //...
}


其余部分保持不变,因为这些类使您可以保留已知的标准数组访问语法。

关于c++ - 如何在Qt的CentralWidget中用QLabel替换QPushButton?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47236009/

10-13 06:58