Different behavior of events in different projects - c++

In the last question, I had a problem with placing the cursor in the right place when clicking on the LineEdit with the mouse.
The problem was solved, I, with God's help, wrote an algorithm that solves my problem. I wrote it in an EMPTY project, where there is nothing but LineEdit. Everything worked great there. Here is the code:
if(object == ui->lineEdit_newClientPhone && event->type() == QEvent::MouseButtonRelease)
{
QString line = ui->lineEdit_newClientPhone->displayText();
qDebug() << line;
ui->lineEdit_newClientPhone->setFocus();
bool isValid = true;
for(int i = 0; i<=15; i++){
if(line[i] == '_'){
ui->lineEdit_newClientPhone->setCursorPosition(i);
isValid = false;
break;
}
}
if(isValid){
ui->lineEdit_newClientPhone->setCursorPosition(16);
}
}
It worked great. You click on any place in lineEdit, the mouse cursor is placed on the first empty "_" character. I joyfully ran to transfer it to the main project.
But then I encountered a strange behavior - in the main project, exactly copied code does not give such behavior. When you click on lineEdit with the mouse, the cursor is placed in the place where you clicked. I debugged all the events associated with this LineEdit and found strange behavior - the order of the events is different. Excluding unnecessary events, which were the MOST:
if(object == ui->lineEdit_newClientPhone){
if(event->type() != QEvent::Paint && event->type() != QEvent::MouseMove && event->type() != QEvent::HoverMove){
qDebug() << event->type();
}
}
Got this result in "EMPTY" project:
QEvent::MouseButtonPress
QEvent::MouseButtonRelease
QEvent::InputMethodQuery
But in the main project, the sequence turned out to be different:
QEvent::MouseButtonPress
QEvent::InputMethodQuery
QEvent::MouseButtonRelease
I don't know if this is the case, but in this way, my logic does not work and the cursor remains in the place where you clicked. I was able to fix the situation by changing the event to QEvent::MouseButtonRelease, but this way I get mocking cursor travels first to the place where you clicked, then to the place I need. What could be the problem and how can it be fixed? Thanks to all!

I don't think this is the right decision, so I would like to hear more solutions, but QTimer::singleShot helped me
f(object == ui->lineEdit_newClientPhone && event->type() == QEvent::MouseButtonPress){
QTimer::singleShot(0,ui->lineEdit_newClientPhone,[this]
{
QString line = ui->lineEdit_newClientPhone->displayText();
qDebug() << line;
ui->lineEdit_newClientPhone->setFocus();
bool isValid = true;
for(int i = 0; i<=15; i++){
if(line[i] == '_'){
ui->lineEdit_newClientPhone->setCursorPosition(i);
isValid = false;
break;
}
}
if(isValid){
ui->lineEdit_newClientPhone->setCursorPosition(16);
}
});
}

Related

ActionScript 3 If Else for Button Click

I'm complete noob about this.
So, in a scene, there is an answer choice button A or B and a "next" button. In short, if we want to go to the next frame (click the "next" button), we have to click on one of the answer options first. However, I am confused about how to make the code.
Can you guys help me? (sorry for my bad english)
errorframe5.visible = false;
var pressed = "yes";
nextbutton.addEventListener(MouseEvent.CLICK, nextframe6);
function nextframe6(event:MouseEvent):void
{
if(button_a == "no" && button_b == "no")
{
errorframe5.visible = true;
}
else
{
gotoAndStop(7, "Material");
}
}
I think you need code like that:
nextbutton.enabled = false;
buttonA.addEventListener(MouseEvent.CLICK, buttonAPressed);
buttonB.addEventListener(MouseEvent.CLICK, buttonBPressed);
function buttonAPressed (MouseEvent){
trace("your answer is correct");
nextbutton.enabled = true;
buttonA.enabled= false;
buttonB.enabled = false;
}
function buttonBPressed (MouseEvent){
trace("your answer is wrong");
nextbutton.enabled = true;
buttonA.enabled= false;
buttonB.enabled = false;
}

QT c++: drop in multi line edite

Im beginner in qt and i do my first project. I am encountering a problem.
I put somes edit line in a scroll area. All of this edit text should countains path to files. To make this app more userfriendly i decided to implement a drag and drop. By this way, users can just take a file from their explorer and drop it to line edit which will be fill with the path of the file.
My problem is: When i try to drop, all edit line where my mouse passed on, will be fill with the path of the file. If i change if statements by else if, its the first edit line that my mouse passed on which will be fill but not the one where my mouse is at the moment of the drop.
here the code:
void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
e->accept()
}
void MainWindow::dropEvent(QDropEvent *e)
{
foreach (const QUrl &url, e->mimeData()->urls()) {
QString fileName = StringManagement::getDir(url.toLocalFile());
if(ui->lineEdit->underMouse())
ui->lineEdit->setText(fileName);
if(ui->lineEdit_2->underMouse())
ui->lineEdit_2->setText(fileName);
if(ui->lineEdit_5->underMouse())
ui->lineEdit_5->setText(fileName);
if(ui->lineEdit_9->underMouse())
ui->lineEdit_9->setText(fileName);
if(ui->lineEdit_10->underMouse())
ui->lineEdit_10->setText(fileName);
if(ui->lineEdit_11->underMouse())
ui->lineEdit_11->setText(fileName);
}
}
On other point that i dont really understand is:
<pre><code>void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
qInfo() << "enter";
e->accept();
}
void MainWindow::dragLeaveEvent(QDragLeaveEvent *e){
qInfo() << "leave";
e->accept();
}
when i put my mouse on an edit line and i stay on it, i will see both message in the console... i expected to see the first one when my mouse enter in and the second one when my mouse leave it.
thank you in advance for your helps.
Following your answer to my comment I'll try to help you.
I'm not an expert at Qt so I may be wrong but since there is no answer yet I'll try to give one.
I tried to reproduce your code and for the second question:
void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
qInfo() << "enter";
e->accept();
}
void MainWindow::dragLeaveEvent(QDragLeaveEvent *e)
{
qInfo() << "leave";
e->accept();
}
I have the same behaviour if MainWindow and the lineEdits both manage drag and drop (setAcceptDrops(true)). I think that you "enter" when you enter the MainWindow and then "leave" when you enter the lineEdit since it manages itself the drag and drop.
If you set :
ui->lineEdit->setAcceptDrops(false);
Then you don't "leave" anymore.
For the first part
If I try to reproduce your code, I have a problem with the underMouse() function.
Maybe your problem comes from here?
If I implement my own underMouse() then everything is fine.
I hope someone else with better Qt knowledge will come to your help.
Ok i find a solution. I dont really like it because i dont find it really clean but that works. If others have cleaner solution im open to it. I put my solution here. Maybe that could help someone in the future. I finaly didn't use drop methode but i used an eventFilter which give me the posibility to have a better management of events.
<pre><code>MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
this->data = DataModel::GetInstance();
ui->setupUi(this);
setAcceptDrops(true);
//ui->lineEdit->dragEnabled();
//ui->lineEdit->setAcceptDrops();
installEventFilter(this);
ui->lineEdit->installEventFilter(this);
ui->lineEdit_2->installEventFilter(this);
ui->lineEdit_5->installEventFilter(this);
ui->lineEdit_9->installEventFilter(this);
ui->lineEdit_10->installEventFilter(this);
ui->lineEdit_11->installEventFilter(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
qInfo() << "enter";
e->accept();
}
bool MainWindow::eventFilter(QObject* obj, QEvent* event){
if(event->type() == QEvent::DragEnter){
if(obj == ui->lineEdit){
this->flag = 1;
}
else if(obj == ui->lineEdit_2){
this->flag = 2;
}
else if(obj == ui->lineEdit_5){
this->flag = 3;
}
else if(obj == ui->lineEdit_9){
this->flag = 4;
}
else if(obj == ui->lineEdit_10){
this->flag = 5;
}
else if(obj == ui->lineEdit_11){
this->flag = 6;
}
qInfo()<<"flag" <<this->flag;
}
if(event->type() == QEvent::Drop){
qInfo()<< obj;
QDropEvent *drop = static_cast<QDropEvent *>(event);
foreach (const QUrl &url, drop->mimeData()->urls()) {
QString fileName = StringManagement::getDir(url.toLocalFile());
qInfo()<<"flag drop" <<this->flag;
if(this->flag == 1){
ui->lineEdit->setText(fileName);
}
else if(this->flag == 2){
ui->lineEdit_2->setText(fileName);
}
else if(this->flag == 3){
ui->lineEdit_5->setText(fileName);
}
else if(this->flag == 4){
ui->lineEdit_9->setText(fileName);
}
else if(this->flag == 5){
ui->lineEdit_10->setText(fileName);
}
else if(this->flag == 6){
ui->lineEdit_11->setText(fileName);
}
return true;
}
}
}
</code></pre>
I dont manage return in the filter for now but the idea is here.

SDL_KEYDOWN triggering twice

I am following lazy foo's tutorial, however I realized every time I press press s or p, SDL_KEYDOWNtriggers twice. How can this be fixed?
Here is the code snippet:
while(SDL_PollEvent(&e) != 0) {
if(e.type == SDL_QUIT) {
quit = true;
}
else if(e.type == SDL_KEYDOWN) {
if(e.key.keysym.sym == SDLK_s) {
if(timer.isStarted()) {
timer.stop();
printf("stop\n");
}
else {
timer.start();
printf("start\n");
}
}
else if(e.key.keysym.sym == SDLK_p) {
if(timer.isPaused()) {
timer.unpause();
printf("unpause\n");
}
else {
timer.pause();
printf("pause\n");
}
}
}
}
Pressing s once:
start
stop
TL;DR: Check if e.key.repeat equals to 0 before handling the events.
SDL generates fake repeated keypresses if you hold a key long enough. This is used mostly for text input.
The original key press has .repeat == 0, and fake presses have .repeat == 1.
For convenience reasons probably (I'd argue that it's rather inconvenient), since SDL 2.0.5 the actual key press generates two events instead of one. One has .repeat set to 0, and other (new) one has it set to 1.

Qt How to highlight menu? [duplicate]

This question already has answers here:
How to focus menuBar() with Qt
(2 answers)
Closed 4 years ago.
I need to do hide/show main menu function by pressing the Alt key (like in FireFox). I know how to hide and show it, but I can't highlight menu after showing it. I've tried menuBar()->actions()[0].hover(), activateWindow(), setActiveAction(), activate(QAction::Hover), but nothing helps. How can I do it? Maybe I should use WinApi functions instead of Qt?
bool MainWindow::event(QEvent *event){
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *ke = static_cast<QKeyEvent*>(event);
if (ke->key() == Qt::Key_Alt)
{
keyReleaseEvent(ke);
return true;
}
}
return QMainWindow::event(event);
}
Handle Alt
void MainWindow::keyReleaseEvent (QKeyEvent* event)
{
if (event->key() == Qt::Key_Alt){
if (menuBar()->isHidden()){
menuBar()->show();
menuBar()->setFocus(Qt::MenuBarFocusEvent); //here I trying to highlight the menu
}
else{
menuBar()->hide();
{
}
}
Duplicate of How to focus menuBar() with Qt (which I just answered)
Because the answer isn't accepted on the other question, I can't flag this one as a duplicate. Including answer below as well:
I wanted to do the same thing. My solution, complete example, as a gist:
https://gist.github.com/xim/ee56564f425151ea2fa70f730d644873
As it contains a lot of other junk, a minimal example:
class AutoHidingMenuBar : public QMenuBar {
Q_OBJECT
public:
AutoHidingMenuBar() : QMenuBar() {
setMaximumHeight(0);
connect(qApp, &QApplication::focusChanged, this, &AutoHidingMenuBar::focusChanged);
}
private slots:
void focusChanged(QWidget *from, QWidget *to) {
bool inFocus = hasFocus() || isAncestorOf(focus) || hasFocusedChild();
if (inFocus && maximumHeight() == 0) {
auto action = activeAction();
setMaximumHeight(100);
if (action) {
// XXX This is a bit of a hack. We could do
// QCoreApplication::processEvents();
// setActiveAction(action);
// with almost the same effect, but then we *open* the first menu on single alt press...
auto evt = new QMouseEvent(QEvent::MouseMove, actionGeometry(action).center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
QCoreApplication::postEvent(this, evt);
}
} else if (!inFocus && maximumHeight() != 0)) {
setMaximumHeight(0);
}
}
private:
bool hasFocusedChild();
};
Try to debug it and see what is happening.
You can do something like:
if (menuBar()->hasFocus())
qDebug() << " I have the focus";
else
qDebug() << " I don't have the focus";
And see if it has the focus but works bad or if it has no focus which I think that is problem... somewhere it is losing it
A little trick that may help you is using:
QTimer::singleShot(0, menuBar(), SLOT(setFocus()));
on your MainWindow::keyReleaseEvent
And last thing... Note that set focus needs a focusPolicy, maybe this helps you.

Quit application call twice the closeevent

I have wrote an application in Qt/c++ on OSX. When quitting the app, I'm catching the closeevent to display dialog box
void MainUI::closeEvent (QCloseEvent *event)
{
if( DeviceUnplugged == false) {
ExitDialog = new DialogExit;
ExitDialog->exec();
if(ExitDialog->result() == QDialog::Accepted) {
m_device.CloseDevice();
event->accept();
}
else {
event->ignore();
}
}
}
The dialog box is correctly displayed when closing using the red cross or using the menu "quit".
but when I'm closing the app using the right click on the icon in the dock, the dialog box appears twice the close event is called twice.
Any idea why ?
Yes, I think it is normal for Mac, at least I had this in my Qt application, too (only on Mac).
I used the following workaround:
void MainUI::closeEvent (QCloseEvent *event)
{
if (m_closing)
{
event->accept();
return;
}
if( DeviceUnplugged == false) {
ExitDialog = new DialogExit;
ExitDialog->exec();
if(ExitDialog->result() == QDialog::Accepted) {
m_device.CloseDevice();
m_closing = true;
event->accept();
}
else {
event->ignore();
}
}
}
By default, boolean variable m_closing should be initialized by false of course in your class. This way second time nothing will be done (processing will be skipped). This worked for me.
Looks like this is a QT bug:
See: https://bugreports.qt.io/browse/QTBUG-43344
Also had this problem when using qt-5.6_4 ,
In my case it happened when using CMD+Q but didn't happen when using the red x button.
Used a similar patch.
I avoided accept or ignore since this is a bug and I don't think we should "talk to it" :-)
Instead I simply return when called more then once.
static int numCalled = 0;
if (numCalled++ >= 1)
return;