简体   繁体   English

如何在Qt的CentralWidget中用QLabel替换QPushButton?

[英]How to replace QPushButton with QLabel in CentralWidget in Qt?

I am trying to learn and build a small minesweeper gui app. 我正在尝试学习并构建一个小型扫雷gui应用程序。
Here is how this looks like: 这是这样的:
在此处输入图片说明

The next thing I want to do is after clicking one button, then the button will be set to hide() and a QLabel will appear in the same place. 我要做的下一件事是单击一个按钮后,该按钮将设置为hide()并且QLabel将出现在同一位置。

My code is like this: 我的代码是这样的:
.h 。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 的.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);
            }
        }
    }
}

When I ran this and clicked one of the buttons, the app just force quit( The program has unexpectedly finished. ) 当我运行它并单击其中一个按钮时,该应用程序只是强制退出( The program has unexpectedly finished.
So how can I solve this problem and replace QPushButton with QLabel after clicking? 那么,如何解决此问题并在单击后用QLabel替换QPushButton
Thanks. 谢谢。

The Problem why your code leads to a crash was correctly pointed out by @GM - lbl[81] = new QLabel(centralWidget); @GM正确指出了代码为何导致崩溃的问题-lbl lbl[81] = new QLabel(centralWidget); will create only 1 label, and place it in the 81st array field. 将仅创建1个标签,并将其放置在第81个数组字段中。 That are 2 errors at once: 一次有2个错误:

  1. If your array is 81 elements long, they are numbered: 0, 1, ..., 79, 80 . 如果数组的长度为81个元素,则它们的编号为: 0, 1, ..., 79, 80 The last element is 80, because you start counting at 0. So placing something at position 81 is not possible 最后一个元素是80,因为您从0开始计数。因此无法将某些内容放置在位置81
  2. To actually create 81 new labels, you have to create them in a loop: 要实际创建81个新标签,您必须循环创建它们:

Sample code: 样例代码:

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));
}

The second line gives each label a custom name. 第二行为每个标签指定一个自定义名称。 See QString::arg for details. 有关详细信息,请参见QString::arg


One more tip: Avoid C-arrays, unless you need high performace/low memory (which is not the case for your example). 另一个提示:避免使用C数组,除非您需要高性能/低内存(在您的示例中不是这种情况)。 Instead try to use one of the Qt container classes, eg QList or QVector . 而是尝试使用Qt容器类之一,例如QListQVector (You can use std::vector etc. as well, but when working with Qt, I would recommend to use the Qt containers) (您也可以使用std::vector等,但是当使用Qt时,我建议使用Qt容器)

For your case, I would recommend QVector, as it performs best with fixed-sized arrays. 对于您的情况,我建议使用QVector,因为它在固定大小的数组上表现最佳。 With both of these changes, update your code to: 通过这两个更改,将代码更新为:

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

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

In your cpp file, update the part where you create the arrays: 在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;
    //...
}

And the rest stays the same, as these classes allow you to keep the standard array access syntax you know. 其余部分保持不变,因为这些类使您可以保留已知的标准数组访问语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM