PDA

View Full Version : QlineEdit and mouse clicks



GerJan
15th April 2021, 15:24
Some years ago I implemented a Sudoku checker and solver on Windows XP/Qt 4.8.1/Visual Studio 8. Recently I reactivated the code on Xindows 8/Qt 5.13.1/Visual Studio 2017. The application is working fine but a strange effect I already noticed on the old system is still there.

The main Sudoku panel, meaning the fields for the 81 digits I realized using 81 QLineEdit with setMaxLength(1) and setInputMask("D"). I can display loaded or calculated Sudokus and I can also input digits when defining or solving ones.

The strange thing I would like to understand and failed to find in documentation or other threads happens when I do a mouse click to select the QLineEdit where I want to input a digit.
There are two sensitive points in the QLineEdit although MaxLength==1.
When I click in the center of the field I get a cursur in the center that takes about a third of the place and no input is accepted.
When I click on the left third of the field I get a cursor in the left third and I have all the functionality I want.

If somebody could explain why there are two separate sensitive points and what I could do to get rid of the unusable one of the two that would be really great.

d_stranz
15th April 2021, 15:59
Without seeing some code or a .ui file, there isn't enough information here to give an answer. From your description, it sounds like you have two widgets overlapped so depending where you click you set focus to one or the other of them.

GerJan
15th April 2021, 20:32
Basically it is something like:


for (int y = 0; y<9; ++y)
{
for (int x = 0; x<9; ++x)
{
textEditSudo[x][y] = new QLineEdit;
}
}

for (int y = 0; y<9; ++y)
{
for (int x = 0; x<9; ++x)
{
textEditSudo[x][y]->setFont(font);
textEditSudo[x][y]->setReadOnly(false);
textEditSudo[x][y]->setMaximumWidth(36);
textEditSudo[x][y]->setMaximumHeight(36);
textEditSudo[x][y]->setMinimumWidth(36);
textEditSudo[x][y]->setMinimumHeight(36);
textEditSudo[x][y]->setMaxLength(1);
textEditSudo[x][y]->setInputMask("D"); // numbers 1..9
textEditSudo[x][y]->insert(tmpStr.setNum(x+1)); // display test only
textEditSudo[x][y]->setContextMenuPolicy(Qt::NoContextMenu);
}
}

for (int y = 0; y<9; ++y)
{
for (int x = 0; x<9; ++x)
{
connect(textEditSudo[x][y], SIGNAL(textEdited(const QString &)), this, SLOT(getTextEditSudoChanged(const QString &)));
}
}

But although I don't think it can be a second widget interfering it might be a good idea to make a small program with only these basic widgets, or even only a single one, to check the behaviour then.
Or is there anything in the above code snippet that must not be done that way?

d_stranz
15th April 2021, 21:05
So, are you putting these into a grid layout? How are you positioning them in your main widget?

GerJan
16th April 2021, 06:53
I tried to put together all parts that might be relevant and leave out all parts of the board that are not relevant:


QGroupBox *gridGroupBoxDA = new QGroupBox(tr("Display Area"));
QGridLayout *gridLayoutDA = new QGridLayout;

QGridLayout *gridLayoutDA1 = new QGridLayout;
for (int y = 0; y < 9; ++y)
{
for (int x = 0; x < 9; ++x)
{
gridLayoutDA1->addWidget(m_pBoardWidget->getSudoTextWidget(x,y), y, x);
}
}
gridGroupBoxDA1->setLayout(gridLayoutDA1);
gridLayoutDA->addWidget((QWidget *)gridGroupBoxDA1, 0, 0);

gridGroupBoxDA->setLayout(gridLayoutDA);

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(gridGroupBoxDA);

QWidget *widget = new QWidget;
widget->setLayout(mainLayout);

setCentralWidget(widget);

Maybe I did make it more complicated than needed but there are lots of other parts on the board I left out here like the second grid (DA2) showing all moves that are possible at the moment etc. I think there is no misleading by leaving these things out because all the widgets I left out here can not overlap since I can see and use them as should be.

d_stranz
16th April 2021, 16:48
Please use CODE tags the next time you post source code. The instructions are in my signature.


Maybe I did make it more complicated than needed
You do seem to like running through those double for() loops a lot. Everything you have posted so far could have been done in one set of loops instead of 5 or 6...

I don't see anything that pops out as being obviously wrong with what you have done. If I have time, I will try to recreate this over the weekend to see if I see similar behavior.

ChrisW67
17th April 2021, 06:19
What I think you have here is an insert cursor. There are three possibilities:

You click right of center and the cursor is placed right of the existing character. The max length stops you typing another character. :(
You click left of center and the cursor is placed before the existing character. The max length will stop you inserting another character. :(
You click and it selects the character which will be erased when you type another character. :D


If you use a QLineEdit subclass that selects all text when focus moves into the widget then you should get the overwriting behaviour (3) by default.


#ifndef OVERWRITINGEDIT_H
#define OVERWRITINGEDIT_H

#include <QLineEdit>

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

signals:


// QWidget interface
protected:
void focusInEvent(QFocusEvent *event);
};

#endif // OVERWRITINGEDIT_H



#include "overwritingedit.h"

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

}

void OverwritingEdit::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);

// Select all text
selectAll();
}


This will still not handle, for example, pressing 5 then 4 and expecting to get 4. Pressing 5 leaves the insert cursor after the 5 and you are back into scenario (1) above. Perhaps you could select all in a slot attached to textChanged() or perhaps you are better off with a completely custom widget.

GerJan
17th April 2021, 20:41
What I think you have here is an insert cursor. There are three possibilities:
You click right of center and the cursor is placed right of the existing character. The max length stops you typing another character.
You click left of center and the cursor is placed before the existing character. The max length will stop you inserting another character.
You click and it selects the character which will be erased when you type another character.

Looks like it is really points 1 and 3 happening. As the fastest possible verification test I just inserted selectAll in the receiving slot (or whatever it is called correctly). If I click right it now just selects the digit. If I click left that's what it did before and still does. And if I input a digit it stays selected (and inputable).

So I now have a quick and a clean way to solve the problem :)

Many thanks!

GerJan
20th April 2021, 19:07
I have to correct myself. I consider the only way that worked not as clean. The selectAll only worked reliable in the following way:


QTimer::singleShot(0, [this](){selectAll();});

This was not my invention but as I started to get a bit desperate I found this solution in a thread about problems with selectAll.

MarselinBrown
20th April 2021, 21:43
Thank you for your answer, it helped me a lot!

ChrisW67
21st April 2021, 06:56
I have to correct myself. I consider the only way that worked not as clean.
I was thinking something like this (untested):


#include "overwritingedit.h"

OverwritingEdit::OverwritingEdit(QWidget *parent)
: QLineEdit(parent)
{
// The extra parameter coming out of the signal should be ignored by Qt for the purposes of this slot
connect(this, SIGNAL(textChanged(QString)), this, SLOT(selectAll()));
}

void OverwritingEdit::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);

// Select all text
selectAll();
}