Home > database >  How can I refer to a form element from a class in Qt?
How can I refer to a form element from a class in Qt?

Time:09-24


Hello.
I am writing a minesweeper. I need to call from the `My_PushButton` class to `gridLayout_2` (* just put it on the form, it was not dynamically created *), in which the elements of the `My_PushButton` class are located, so that if the" mine "is clicked with the LMB (mine - value 9 in the variable `val` of `My_PushButton`), deactivate `gridLayout_2`, thus end the game.
Tried the following:
  1. QWidget *form = QApplication::activeWindow();
    
    form->blockSignals(true);
    
    or
    form->setDisabled(true);
    
    In this case, the window is blocked, and with it the pushButton button, which is needed to restart in case of defeat.
  2.  Ui::MainWindow *ui;
    
    ui->gridLayout_2->setEnabled(false);
    
    With this approach, I get the "Segmentation Fault" error, although the pointer is not empty in theory.

    My_PushButton class:
    class My_PushButton: public QPushButton{
        Q_OBJECT
    public:
        //Ui::MainWindow *ui;
        //QWidget *form = QApplication::activeWindow();     //A pointer to the active window (widget) in order to further access form elements through it
        int val;                                            //A variable that will store either the number of mines in the neighborhood, or the mine itself
        My_PushButton(int val = 0): QPushButton(), val(val){
            setFixedHeight(25);
            setFixedWidth(25);
            setIconSize(QSize(25, 24));
            setStyleSheet("background-color: rgb(146, 36, 255)");
        }
    private slots:
        void mousePressEvent(QMouseEvent *event){
            if(event->button() == Qt::RightButton){
                this->setIcon(QIcon(R"(C:\Qt\pictures/flag.png)"));
    
            }
            else{
                if(val == 0) this->setStyleSheet("background-color: rgb(234, 223, 246)"), this->setIcon(QIcon());
                if(val == 1) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("1");
                if(val == 2) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("2");
                if(val == 3) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("3");
                if(val == 4) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("4");
                if(val == 5) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("5");
                if(val == 6) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("6");
                if(val == 7) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("7");
                if(val == 8) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("8");
                if(val == 9){
                    this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon(R"(C:\Qt\pictures/bomb.png)"));
                    //form->blockSignals(true);
                    //form->setDisabled(true);
                    //ui->gridLayout_2->setEnabled(true);
                }
            }
        }
    signals:
        void rightClicked();
        void leftClicked();
    protected:
        void mouseReleaseEvent(QMouseEvent* event){
            if(event->button() == Qt::RightButton){
                emit rightClicked();
            }
            else{
                emit leftClicked();
            }
        }
    };


The whole mainwindow.cpp file containing `My_PushButton`:
```
    #include "./ui_mainwindow.h"
    #include "mainwindow.h"
    #include <iostream>
    #include <QTextBrowser>
    #include <QPushButton>
    #include <QVariant>
    #include <time.h>
    #include <QLayout>
    #include <QMouseEvent>
    #include <QObject>

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

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

class My_PushButton: public QPushButton{
    Q_OBJECT
public:
    //Ui::MainWindow *ui;
    //QWidget *form = QApplication::activeWindow();     //A pointer to the active window (widget) in order to further access form elements through it
    int val;                                            //A variable that will store either the number of mines in the neighborhood, or the mine itself
    My_PushButton(int val = 0): QPushButton(), val(val){
        setFixedHeight(25);
        setFixedWidth(25);
        setIconSize(QSize(25, 24));
        setStyleSheet("background-color: rgb(146, 36, 255)");
    }
private slots:
    void mousePressEvent(QMouseEvent *event){
        if(event->button() == Qt::RightButton){
            this->setIcon(QIcon(R"(C:\Qt\pictures/flag.png)"));

        }
        else{
            if(val == 0) this->setStyleSheet("background-color: rgb(234, 223, 246)"), this->setIcon(QIcon());
            if(val == 1) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("1");
            if(val == 2) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("2");
            if(val == 3) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("3");
            if(val == 4) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("4");
            if(val == 5) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("5");
            if(val == 6) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("6");
            if(val == 7) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("7");
            if(val == 8) this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon()), this->setText("8");
            if(val == 9){
                this->setStyleSheet("background-color: rgb(209, 173, 245)"), this->setIcon(QIcon(R"(C:\Qt\pictures/bomb.png)"));
                //form->blockSignals(true);
                //form->setDisabled(true);
                //ui->gridLayout_2->setEnabled(true);
            }
        }
    }
signals:
    void rightClicked();
    void leftClicked();
protected:
    void mouseReleaseEvent(QMouseEvent* event){
        if(event->button() == Qt::RightButton){
            emit rightClicked();
        }
        else{
            emit leftClicked();
        }
    }
};

#include "mainwindow.moc"

void MainWindow::on_action_triggered()
{
    QTextBrowser *tb = new QTextBrowser(); //Create a window with game rules
    tb->setFixedSize(610, 150);
    tb->setText("Use the left click button on the mouse to select a space on the grid.\n"
                "If you hit a bomb, you lose.\n"
                "The numbers on the board represent how many bombs are adjacent to a square.\n"
                "For example, if a square has a \"3\" on it, then there are 3 bombs next to that square.\n"
                "The bombs could be above, below, right and (or) left, or diagonal to the square.\n"
                "Avoid all the bombs and expose all the empty spaces to win Minesweeper.\n"
                "You can right click a square with the mouse to place a flag where you think a bomb is. This allows you to avoid that spot.");
    tb->setEnabled(true);
    tb->setVisible(true);
}

My_PushButton** my_rand(int size){

    /*************************************************************
     * The following values ​​will be used to customize the cells: *
     * 0 - empty cell;                                           *
     * 1 - cell showing the number of mines around it = 1;       *
     * 2 - cell showing the number of mines around it = 2;       *
     * 3 - cell showing the number of mines around it = 3;       *
     * 4 - cell showing the number of mines around it = 4;       *
     * 5 - cell showing the number of mines around it = 5;       *
     * 6 - cell,showing the number of mines around it = 6;       *
     * 7 - cell showing the number of mines around it = 7;       *
     * 8 - cell showing the number of mines around it = 8;       *
     * 9 - mine cell;                                            *
     *************************************************************/


    srand(time(NULL));
    int counter = 0, numines = (rand() % ((size * size) / 2))   1, x = 0, y = 0; //numines - number of mines, x & y - coordinates for placing a mine

    My_PushButton **but;            //Create a 2D array and fill it with 0
    but = new My_PushButton*[size];
    for(int i = 0; i < size;   i){
        but[i] = new My_PushButton[size];
    }

    while(numines > 0){ //Placing mines
        x = rand() % size, y = rand() % size;
        if(but[x][y].val != 9){
            but[x][y].val = 9;
            numines --;
        }
    }

    //Checking neighbors for mines
    for(int i = 1; i < size - 1;   i){                  //Checking an area without borders
        for(int j = 1; j < size - 1;   j){
            if(but[i][j].val != 9){
                if(but[i - 1][j - 1].val == 9)   counter;
                if(but[i - 1][j].val == 9)   counter;
                if(but[i - 1][j   1].val == 9)   counter;

                if(but[i][j - 1].val == 9)   counter;
                if(but[i][j   1].val == 9)   counter;

                if(but[i   1][j - 1].val == 9)   counter;
                if(but[i   1][j].val == 9)   counter;
                if(but[i   1][j   1].val == 9)   counter;
            }

            if(counter > 0) but[i][j].val = counter;
            counter = 0;
        }
    }

    for (unsigned int i = 0; i < size;   i) {                   //upper border
            for (unsigned int j = 0; j < size;   j) {
                if (but[i][j].val != 9) {
                    if (i == 0 && j == 0) {
                        if (but[i][j   1].val == 9)   counter;
                        if (but[i   1][j].val == 9)   counter;
                        if (but[i   1][j   1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }
                    if (i == 0 && j == size - 1) {
                        if (but[i][j - 1].val == 9)   counter;
                        if (but[i   1][j].val == 9)   counter;
                        if (but[i   1][j - 1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }
                    if (i == 0 && (j > 0 && j < size - 1)) {
                        if (but[i][j - 1].val == 9)   counter;
                        if (but[i][j   1].val == 9)   counter;
                        if (but[i   1][j - 1].val == 9)   counter;
                        if (but[i   1][j].val == 9)   counter;
                        if (but[i   1][j   1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }



                    if (i == size - 1 && j == 0) {                  //lower border
                        if (but[i - 1][j].val == 9)   counter;
                        if (but[i - 1][j   1].val == 9)   counter;
                        if (but[i][j   1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }
                    if (i == size - 1 && j == size - 1) {
                        if (but[i - 1][j].val == 9)   counter;
                        if (but[i - 1][j - 1].val == 9)   counter;
                        if (but[i][j - 1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }
                    if (i == size - 1 && (j > 0 && j < size - 1)) {
                        if (but[i][j - 1].val == 9)   counter;
                        if (but[i - 1][j - 1].val == 9)   counter;
                        if (but[i - 1][j].val == 9)   counter;
                        if (but[i - 1][j   1].val == 9)   counter;
                        if (but[i][j   1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }



                    if (j == 0 && (i > 0 && i < size - 1)) {        //left border
                        if (but[i - 1][j].val == 9)   counter;
                        if (but[i - 1][j   1].val == 9)   counter;
                        if (but[i][j   1].val == 9)   counter;
                        if (but[i   1][j].val == 9)   counter;
                        if (but[i   1][j   1].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }



                    if (j == size - 1 && (i > 0 && i < size - 1)) { //right border
                        if (but[i - 1][j].val == 9)   counter;
                        if (but[i - 1][j - 1].val == 9)   counter;
                        if (but[i][j - 1].val == 9)   counter;
                        if (but[i   1][j - 1].val == 9)   counter;
                        if (but[i   1][j].val == 9)   counter;
                        if (counter > 0) but[i][j].val = counter, counter = 0;
                    }
                }
        }
    }
    return but;
}

void MainWindow::on_pushButton_pressed()
{
    QVariant index_but = ui->comboBox->currentIndex(); //Find out the value selected in the ComboBox
    int a = index_but.toInt();

    switch(a){
    case 0:             //number of buttons = 10
    {
        My_PushButton** but =  my_rand(10);

        for(int i = 0; i < 10;   i){
            for(int j = 0; j < 10;   j){
                ui->gridLayout_2->addWidget(&but[i][j], i, j);
            }
        }
        ui->gridLayout_2->setSpacing(0);
        ui->gridLayout_2->setSizeConstraint(QLayout::SetFixedSize);

        /*for(int i = 0; i < 5;   i){
            delete [] but[i];
        }
        delete but;*/

        break;
    }

    case 1: //number of buttons = 17
        break;

    case 2: //number of buttons = 25
        break;

    case 3: //self-entry
        break;

    default:
        break;
    }
}



Mainwindow.ui file:

<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>650</width>
    <height>800</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>649</width>
    <height>770</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>1000</width>
    <height>1000</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Minesweeper</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QWidget" name="horizontalLayoutWidget">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>157</width>
      <height>41</height>
     </rect>
    </property>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QComboBox" name="comboBox">
       <property name="editable">
        <bool>false</bool>
       </property>
       <property name="currentText">
        <string>Level 1</string>
       </property>
       <item>
        <property name="text">
         <string>Level 1</string>
        </property>
       </item>
       <item>
        <property name="text">
         <string>Level 2</string>
        </property>
       </item>
       <item>
        <property name="text">
         <string>Level 3</string>
        </property>
       </item>
       <item>
        <property name="text">
         <string>Self-entry</string>
        </property>
       </item>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="pushButton">
       <property name="text">
        <string>Start</string>
       </property>
      </widget>
     </item>
    </layout>
   </widget>
   <widget class="QWidget" name="gridLayoutWidget">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>90</y>
      <width>601</width>
      <height>541</height>
     </rect>
    </property>
    <layout class="QGridLayout" name="gridLayout_2"/>
   </widget>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <widget class="QMenuBar" name="menubar">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>650</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuMinesweeper">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="title">
     <string>Menu</string>
    </property>
    <addaction name="action"/>
    <addaction name="separator"/>
    <addaction name="actionNotes"/>
   </widget>
   <addaction name="menuMinesweeper"/>
  </widget>
  <action name="action">
   <property name="text">
    <string>Rules of the game</string>
   </property>
  </action>
  <action name="actionNotes">
   <property name="text">
    <string>Notes</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections/>
</ui>



`UPD`:
What I've done? Added a getter in the `MainWindow` class -
Ui::MainWindow *getPointer(){ return ui;  }

that returns a pointer to the form. In the My_PushButton class, I added a pointer that takes a getter from MainWindow -

    MainWindow m;
    Ui::MainWindow *form = m.getPointer();

, now I can refer to the desired form object - form->gridLayout_2->setEnabled(false);, but the object does not need to be changed. The getter, of course, has a public access modifier.

CodePudding user response:

It was possible to do as drescherjm said, but due to further obstacles I had to take a global pointer to the form and through it carry out the necessary manipulations with objects. Yes, I understand that this approach is not very desirable, but for myself (training) it will do. And just as Sergey Tatarincev (in post https://ru.stackoverflow.com/a/1330855/460029) said - this also works. Thanks to all.

  • Related