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:
-
QWidget *form = QApplication::activeWindow();
orform->blockSignals(true);
In this case, the window is blocked, and with it theform->setDisabled(true);
pushButton
button, which is needed to restart in case of defeat. -
Ui::MainWindow *ui;
With this approach, I get the "Segmentation Fault" error, although the pointer is not empty in theory.ui->gridLayout_2->setEnabled(false);
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.