PDA

View Full Version : Sudoku QLineEdit focusInEvent



laurynas2003
16th April 2020, 18:51
Hey,

I am creating Sudoku game/solver and i am almost done:) , just couple things left to do - one of them is highlight row and column whenever tile(QLineEdit)
is selected. So i created a class with focusInEvent



// focusInEvent header file

#ifndef QLINEEDIT_CLICKABLE_H
#define QLINEEDIT_CLICKABLE_H

#include <QWidget>
#include <Qt>
#include <QLineEdit>
#include <QVector>

class QLineEdit_Clickable : public QLineEdit
{
Q_OBJECT
public:
explicit QLineEdit_Clickable(QWidget *parent = nullptr);


protected:

void focusInEvent(QFocusEvent *e);

};

#endif // QLINEEDIT_CLICKABLE_H




// focusInEvent source file

#include "qlineedit_clickable.h"
#include <QMouseEvent>
#include <QMessageBox>

QLineEdit_Clickable::QLineEdit_Clickable(QWidget *parent)
: QLineEdit(parent){

}

void QLineEdit_Clickable::focusInEvent(QFocusEvent *e)
{
QLineEdit::focusInEvent(e);

}



So my problem is that i don't know how to get my tile(QLineEdit) position, i need them because I need to know which row and column to higlight. Could someone help me how to get them?



// Sudoku grid widget
#include "sudoku_widget.h"
#include "qlineedit_clickable.h"

#include <QGridLayout>
#include <QFrame>
#include <QLineEdit>
#include <QIntValidator>
#include <QMessageBox>
#include <QPushButton>
#include <QRandomGenerator>
#include <QDateTime>
#include <QSet>
#include <iostream>
#include <QSignalMapper>
#include <QMainWindow>
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QLayout>
#include <QFont>
#include <QTimer>


SudokuWidget::SudokuWidget(QWidget * parent)
: QWidget(parent) {

mapper = new QSignalMapper( this );

QIntValidator *pValidator = new QIntValidator( this ); // user can input only 1 - 9
pValidator->setRange( 1, 9 ); // 1 - 9

// Sudoku big square
QGridLayout *pMainLayout = new QGridLayout( this );
pMainLayout->setSpacing(0);
pMainLayout->setAlignment(Qt::AlignCenter);

// 3 x 3 array of smaller squares
QVector< QGridLayout * > bigGrids;
for ( int y = 0; y < 3; y++ ){
for ( int x = 0; x < 3; x++ ){
QGridLayout *pInnerGrid = new QGridLayout( this );

pInnerGrid->setAlignment(Qt::AlignHCenter);
pInnerGrid->setSpacing(0);
pInnerGrid->setMargin(0);

pMainLayout->addLayout( pInnerGrid, y, x );
bigGrids.push_back( pInnerGrid );
}
}


tiles.resize(81);
solve_data.resize(81);
// adds tiles into smaller squares
for (int y = 0; y < 9; y++){
for (int x = 0; x < 9; x++){
int bigGridIndex = box_position( y, x);
QGridLayout *pInnerGrid = bigGrids[bigGridIndex];

// square coordinates in the box
int grid_y = y % 3;
int grid_x = x % 3;

QLineEdit *tile = new QLineEdit_Clickable( this );

int rowColId = x + y * 10;
mapper->setMapping( tile, rowColId );
connect( tile, SIGNAL( textEdited(QString) ), mapper, SLOT( map() ) );

// tile customization
tile->setValidator(pValidator); // input 1 - 9
tile->setMaxLength(1);
tile->setFixedSize(30,30);
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-style: solid; border-color: gray gray gray gray; }");
tile->setAlignment(Qt::AlignCenter);
tile->setFrame(QFrame::Box);

if (y == 0){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-style: solid; border-color: black gray gray gray; }");
}

if (x == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-right: 5px; border-style: solid; border-color: gray black gray gray; }");
}
if (y == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-style: solid; border-color: gray gray black gray; }");
}
if (x == 0){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-left: 5px; border-style: solid; border-color: gray gray gray black; }");
}
if (x == 0 && y == 0){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-left: 5px; border-style: solid; border-color: black gray gray black; }");
}
if (x == 8 && y == 0){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-right: 5px; border-style: solid; border-color: black black gray gray; }");
}
if (x == 8 && y == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black black; }");
}
if (x == 0 && y == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-left: 5px; border-style: solid; border-color: gray gray black black; }");
}
if (x == 5 || x == 2){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-right: 5px; border-style: solid; border-color: gray black gray gray; }");
}
if (y == 2 || y == 5){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-style: solid; border-color: gray gray black gray; }");
}
if (x == 2 && y == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
}
if (x == 5 && y == 8){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
}
if ( ( x == 2 || x == 5 || x == 8 ) && y == 5){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
}
if ( ( x == 2 || x == 5 || x == 8 ) && y == 2){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-right: 5px; border-style: solid; border-color: gray black black gray; }");
}
if (x == 0 && (y == 2 || y == 5)){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-bottom: 5px; border-left: 5px; border-style: solid; border-color: gray gray black black; }");
}
if ( y == 0 && ( x == 2 || x == 5 ) ){
tile->setStyleSheet("QLineEdit{ border-width: 1.5px; border-top: 5px; border-right: 5px; border-style: solid; border-color: black black gray gray; }");
}



pInnerGrid->addWidget( tile, grid_y, grid_x);

// inedex of tile in tiles array
int tileIndex = y * 9 + x;
tiles [tileIndex] = tile;
}
}

connect( mapper, SIGNAL( mapped( int ) ), this, SLOT( onMapped( int ) ) );


// Generate random digits with solvable solution ( 10 digs )
random_position(10, random_pos_value);
for (int i = 0;i < 10; i++){
tiles[random_pos_value[i].first]->setText(QString::number(random_pos_value[i].second));
tiles[random_pos_value[i].first]->setReadOnly(true);
}

// solve button
Solve = new QPushButton( "Solve", this);
connect( Solve, SIGNAL(clicked()), this, SLOT(on_Solve_clicked()) );
pMainLayout->addWidget(Solve, 5, 0);

// clear board button
Solve = new QPushButton( "Generate", this);
connect( Solve, SIGNAL(clicked()), this, SLOT(on_Reset_clicked()) );
pMainLayout->addWidget(Solve, 5, 1);

// Finish Button
Solve = new QPushButton( "Finish", this);
connect( Solve, SIGNAL(clicked()), this, SLOT(on_Finish_clicked()) );
pMainLayout->addWidget(Solve, 5, 2);

setLayout( pMainLayout );

}

// ........

Ginsengelf
17th April 2020, 07:49
Hi, the easiest way would be to pass row and column to the constructor, and store it in member variables of QLineEdit_Clickable.

Ginsengelf

laurynas2003
17th April 2020, 08:28
But how could I access my tiles (QVector < *QLineEdit>) in QLineEdit_Clickable?

d_stranz
17th April 2020, 18:16
But how could I access my tiles (QVector < *QLineEdit>) in QLineEdit_Clickable?

You don't need to. When your QLineEdit_Clickable class gets a focus in event, have it emit a signal that contains the row and column as arguments. Handle this signal in a slot in SudokuWidget, and let it highlight the rest of the cells in the row and column. It contains the vector that knows about all the other line edits.

It really isn't necessary to create a new class just to handle the focus in events on the QLineEdits. You could just as easily have installed an event filter on standard QLineEdit and implemented it in SudokuWidget:



// SudokuWidget.h

class SudokuWidget : public // ...
{

protected:
bool eventFilter( QObject * pObj, QEvent * pEvent );
};

// SudokuWidget.cpp

SudokuWidget:SudokuWidget( QWidget * parent ) //...
{
// ...
tile = new QLineEdit( this );
tile->installEventFilter( this );
// ...
}

bool SudokuWidget::eventFilter( QObject * pObj, QEvent * pEvent )
{
if ( pEvent->type() == QEvent::FocusIn )
{
QLineEdit * pEdit = qobject_cast< QLineEdit * >( pObj );
if ( pEdit )
{
// Now look up the line edit in your QVector, determine its row and column, and highlight them
}
}
return QWidget::eventFilter( obj, event ); // Let normal processing continue
}


See QObject::eventFilter() and QObject:installEventFilter().

laurynas2003
17th April 2020, 21:18
Hey,
Thanks again, you such an amazing guy:), you always help me so much:D