PDA

View Full Version : QCheckBox assignation fails for public member variable, but not for local variable



Bellaella
13th October 2017, 23:45
I am not a complete newbie to Qt, but I do have a potentially very simple, very perplexing issue.

I have my Main Window and a separate Dialog Window, both containing a checkbox. Same functionality. When one checkbox is checked, both should be checked. This "syncing" is triggered by a signal/slot mechanism, but as the dialog window is the child of the main window, the checked values are assigned as shown below.

This works for all checkboxes, all set up the same, except one.

In my dialog window's class, I have declared:


namespace Ui {
class DialogWinow;
}

class DialogWindow : public QWidget
{
...
public:

bool checked1;
bool checked2;
...

In my MainWindow class/constructor I have:


private:
DialogWindow *dialog_window;

And in the setup for the MainWindow/DialogWindow, I have these assignations:


dialog_window->checked1 = ui->checkBox1->isChecked();
dialog_window->checked2 = ui->checkBox2->isChecked();

The crazy thing is that the first one of these works just fine. The second one is not working (the value of dialog_window->checked2 remains the same), and even more strange, this works:


bool checked_temp = ui->checkBox2->isChecked();
dialog_window->checked2 = checked_temp;

I have tried a few variations, for example this does not work:


dialog_window->checked2 = (bool)ui->checkBox2->isChecked();

Could this bug be some quirk of Qt Designer? Have I checked some box for this QCheckBox in particular that is causing this assignation to fail? The settings for this QCheckBox seem to be the same as all my other (working) checkboxes.

Thanks in advance for any advice!

high_flyer
15th October 2017, 01:24
Hard to tell without seeing the real code.
If you have use this method on more than one checkbox and all are working except this one, to me it seems you might have a typo somewhere in a name of a variable.
So go through all your variables makes sure you don't have a typo.
Another possibly is that your boolean variables are being changed by a signal/slot triggered in a way you didn't anticipate (this seems to be likely the explanation to why the example with the temp works.

Your design is very much a spaghetti design and it begs to these kinds of problems.
A better approach would be to have a non ui object to contain the actual boolean value, and have it emit a signal when the value changes - which the checkboxes (or indeed any number of listeners) will connect to, and a slot for setting the value also each setting UI element can connect to.
This will allow you to have one central place managing the state of the boolean value - and much easier overview of what is happening, and if needed an easy way to debug.
This way the value is not kept by the checkboxex, but by a dedicated object, the checkboxes are only a UI element that can change it.
It frees you from the need to manage what each checkbox is doing and makes the UI just a UI not part of the business logic/data




class BooleanManager : public QObject
{
Q_OBJECT
public:
....//constructor etc

public Q_SIGNALS:
void valueToggled(bool);

public Q_SLOTS:
void onValueToggled(bool);
private:
bool m_boolVal;
};


EDIT:
Actually this is not a complete idea - the way it is posted here is problematic, since it can end in a signal endless loop.
To over come this you will have to put some guarding code in your onValueToggled() slot:
- only emit the valueToggled() signal if the value indeed toggled.

Bellaella
19th October 2017, 23:25
Thanks, high_flyer. I believe you are correct about the unexpected signal/slot behavior. I am still debugging, but using the local variable as a workaround for now.