PDA

View Full Version : QPushButton Requires Two Clicks (Not Always)



TravisLedo
14th August 2020, 00:34
MacOS 10.15.16
QT version 5.15
Creator 4.12.4

Hey everyone,

I am having a really annoying issue with buttons in my project. I made a very simple project that can replicate the bug.
What happens is when I click the remove button to remove an item, the next time I click the add button will always require me to click it twice. It does not register the first time.
I narrowed down the issue but have no idea how to fix it.
The problem is from layouts I think. The first screenshot shows it working works fine, does not require two clicks. But when I add the new button in the same layout as the remove button, that is when it happens.


13524


13525




Here are the only lines of code in my project

void MainWindow::on_removeItemButton_clicked()
{
ui->listWidget->takeItem(ui->listWidget->currentRow());

}

void MainWindow::on_addItemButton_clicked()
{
ui->listWidget->addItem("test");

}





I noticed that this happens with many things I try to do. Here is an instance where if I put everything inside a Tab Widget, the first time running the app will require two clicks on any of those buttons.
Clicking on an itemList item however works fine.

13526

The issue only applies to buttons. Nothing else is being affected by this.




Any ideas?

d_stranz
14th August 2020, 17:14
Here are the only lines of code in my project

Wow, you have an entire application that runs with only two methods of one line each? No header files, no main.cpp, no MainWindow constructor? Amazing.

Showing screenshots of Qt Designer in meaningless. All it shows is that you've specified a UI file for your project. The problem is almost certainly not in the layout of your GUI, it is in how you are connecting the signals and slots of the various UI components and what you are doing in those slots.

TravisLedo
15th August 2020, 01:24
Wow, you have an entire application that runs with only two methods of one line each? No header files, no main.cpp, no MainWindow constructor? Amazing.

Showing screenshots of Qt Designer in meaningless. All it shows is that you've specified a UI file for your project. The problem is almost certainly not in the layout of your GUI, it is in how you are connecting the signals and slots of the various UI components and what you are doing in those slots.

Whatever comes with a default new project is all that is in the rest of the code. The only thing I did was add a slot for the buttons like I said. Didn't think they would be important but here they are. If this is a default feature that's pretty weird lol.
It seems that what ever button is in the position of the remove button will be affected. If i swapped the add with remove, the remove button will be the one requiring two clicks after the add button is clicked. My guess about it being the layout is because of this reason. It affects that specific position in the layout.


Here is the project, I'm curious if it happens to anyone else running it.

13527




#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:

void on_removeItemButton_clicked();

void on_addItemButton_clicked();

private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H






#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}







#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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


void MainWindow::on_removeItemButton_clicked()
{
ui->listWidget->takeItem(ui->listWidget->currentRow());

}

void MainWindow::on_addItemButton_clicked()
{
ui->listWidget->addItem("test");

}






<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addItemButton">
<property name="text">
<string>Add Item</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QVBoxLayout" name="verticalLayout"/>
</item>
<item row="0" column="0">
<widget class="QListWidget" name="listWidget">
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="removeItemButton">
<property name="text">
<string>Remove Item</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

TravisLedo
15th August 2020, 16:58
Not sure why the site is not allowing me to edit my post but I forgot to mention that even if I don't touch the code at all. If I don't add slots to the buttons or anything. It still happens. I can still see the remove button only showing that it's clicked on the second attempt.

d_stranz
15th August 2020, 21:40
For one thing, you aren't doing any error checking at all in your slots. You don't check the value of "currentRow()" and I would bet you real money that the first time you click, it has the value -1 because there is no current item. If you run your code in a debugger and set a breakpoint inside the on_removeItemButton_clicked() slot I am certain that you will see it gets called every time you click the button.

Because you have slots named "on_<buttonName>_clicked()", Qt's MOC automatically connects those slots to the corresponding buttons' "clicked()" signals. If somewhere in your code you also connect the button signal and your slot manually, then the slot will be called twice for every click. Most developers have learned to not let this automatic connection happen by naming their slots to something other than "on_<buttonName>_clicked()" because at some point everyone makes the mistake of having double connections which lead to all sorts of behavior that is hard to debug.

Your call to takeItem() creates a memory leak. takeItem() returns a pointer to the QListWidgetItem instance in that row, and you are responsible for deleting it.

Your UI file has an empty vertical layout at the bottom. I am guessing that what you really want is to put your whole central widget inside this layout.

TravisLedo
16th August 2020, 17:44
For one thing, you aren't doing any error checking at all in your slots. You don't check the value of "currentRow()" and I would bet you real money that the first time you click, it has the value -1 because there is no current item. If you run your code in a debugger and set a breakpoint inside the on_removeItemButton_clicked() slot I am certain that you will see it gets called every time you click the button.

Because you have slots named "on_<buttonName>_clicked()", Qt's MOC automatically connects those slots to the corresponding buttons' "clicked()" signals. If somewhere in your code you also connect the button signal and your slot manually, then the slot will be called twice for every click. Most developers have learned to not let this automatic connection happen by naming their slots to something other than "on_<buttonName>_clicked()" because at some point everyone makes the mistake of having double connections which lead to all sorts of behavior that is hard to debug.

Your call to takeItem() creates a memory leak. takeItem() returns a pointer to the QListWidgetItem instance in that row, and you are responsible for deleting it.

Your UI file has an empty vertical layout at the bottom. I am guessing that what you really want is to put your whole central widget inside this layout.



Your responses are about the slots. It happens if I don't touch the code at all so I am sure the slots are not causing the issue. The central widget cant be moved, thats the main grid. I took out the extra vertical layout but it still happens. The only difference now is it happens after clicking the button next to the remove button and then back to the add. No slots in any of them. They are just blank buttons. I am just watching the color of the button when clicking. And just to get your mind off the slots i commented them out too.




What else can it be? It happens more and more, the more widgets and layouts I start adding. But this example is pretty darn simple, this shouldn't be happening at all.




EDIT: To make it even more simple. I took out the listview widget. So now it's just literally 3 buttons inside 2 different horizontal layouts. It still happens.








#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:

//void on_removeItemButton_clicked();

//void on_addItemButton_clicked();

private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H



#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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


//void MainWindow::on_removeItemButton_clicked()
//{
// ui->listWidget->takeItem(ui->listWidget->currentRow());

//}

//void MainWindow::on_addItemButton_clicked()
//{
// ui->listWidget->addItem("test");

//}





#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}






<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addItemButton">
<property name="text">
<string>Add Item</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="removeItemButton">
<property name="text">
<string>Remove Item</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>





Updated project file
13529

d_stranz
16th August 2020, 20:37
If you have commented out all of the slots that are connected to your buttons, then how can you tell that it takes two clicks on any button to get a response? What exactly are you doing to determine that?

TravisLedo
16th August 2020, 20:47
If you have commented out all of the slots that are connected to your buttons, then how can you tell that it takes two clicks on any button to get a response? What exactly are you doing to determine that?

When you click them they turn blue for a second or until you let go of the mouse. Does not happen on the first click when the problem arises. Also can't be a coincidence that both the click animation and slot are not getting triggered at the same time. It's def the button not receiving the click. I also could just add the slot back with just print statements. Same thing. Does not show click animation or call the function.

kyosold
25th August 2020, 08:47
Yes, I have this problem too, if i put the btn to layout, i must clicked twitce; if don't use QVBoxLayout it's work

But, If i set tabWidget is documentMode, It is work.

my system is OSX 10.15.6, Qt: 5.15



#include "preferencewidget.h"
#include "ui_preferencewidget.h"
#include <QTabWidget>
#include <QPushButton>
#include <QDebug>
#include <QLayout>
#include <QVBoxLayout>

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

QTabWidget *tab = new QTabWidget(this);

QWidget *browser_tab = new QWidget;
QWidget *users_tab = new QWidget;

tab->addTab(browser_tab, "Browser");
tab->addTab(users_tab, "Users");

tab->setGeometry(20, 20, 300, 250);

QPushButton *btn = new QPushButton("Btn1");
btn->setGeometry(10, 30, 100, 40);
btn->setParent(users_tab);

QVBoxLayout *vl = new QVBoxLayout(users_tab);
vl->addWidget(btn);
users_tab->setLayout(vl);

connect(btn, SIGNAL(clicked()), this, SLOT(clickedAlert()));
}

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


void PreferenceWidget::clickedAlert()
{
qDebug() << "Clicked";
}