SLOT problem / C++ - c++

Im trying to figure this error out. I have a simple application made with Qt Creator.
I have three buttons and 2 of them are not enabled. Then when push the first button i want to make them visible, but when i push the button, windows error occures : "program stopped working". the program compiles and does everything else.
QPushButton *dealButton = new QPushButton(tr("Deal cards"));
dealButton->show();
QPushButton *hitButton = new QPushButton(tr("HIT"));
hitButton->show();
hitButton->setEnabled(false);
QPushButton *standButton = new QPushButton(tr("STAND"));
standButton->show();
standButton->setEnabled(false);
...
connect(dealButton, SIGNAL(clicked()), this, SLOT(dealCards()));
...
void MainWindow::dealCards()
{
hitButton->setEnabled(true);
standButton->setEnabled(true);
}
thats the code.

The problem is that you are re-declaring dealButton and the others in your constructor (or whatever function it is that has the new calls you're showing).
You should have in your class definition:
private: // probably
QPushButton *dealButton;
And in your constructor or gui init code:
dealButton = new QPushButton(...); // note: not QPushButton *dealButton = ...
What you have now is creating a new variable called dealButton that is local to that scope (function). That variable is hiding (masking) the class's member.

Related

Qt Change ComboBox2 based on ComboBox1

Hi I am fairly new to Qt scene and I'm having trouble updating my comboBox2 based on comboBox1 selection.
Everytime I make a change in comboBox1, my app crashed, saying access violation. It's probably very straightforward but here's my code: In this case, the initial comboBox1 has "Car" and "Food". Whenever I switch to "Food", I want my comboBox2 to populate the item "Egg".
Any idea what went wrong ?
main.h
class main:
{
Q_OBJECT
public:
main() {}
public slots :
private slots:
void onComboBoxIndexChanged();
private:
QComboBox* comboBox2;
void run();
};
main.cpp
void main::run()
{
QWidget *w = new QWidget();
QComboBox *comboBox1 = new QComboBox();
QComboBox *comboBox2 = new QComboBox();
comboBox1->addItem("Car");
comboBox1->addItem("Food");
connect(comboBox1, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxIndexChanged()));
...
}
void main::onComboBoxIndexChanged()
{
QComboBox* combo = dynamic_cast<QComboBox*>(sender());
if (combo == nullptr)
{
return;
}
comboBox2->addItem("Egg");
}
You didn't fix your typo correctly. There's three things I see wrong, and I would've thought the third one would prevent this from compiling.
First, main.h says that your class name is "main", but in main.cpp, your class is WIPGui. Clearly one of those files isn't the right one. I'm going to proceed assuming that your actual main.h file defines the WIPGui class, but otherwise looks the same.
Second, as Mike tried to point out, in your run function, you have this:
QComboBox *comboBox2 = new QComboBox();
That's creating a local variable in your "run" method; it is not assigning to your class member variable comboBox2. What you want is:
comboBox2 = new QComboBox();
Third, your connect statement shouldn't compile based on the code we're seeing:
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxIndexChanged()));
The "comboBox" variable doesn't exist anywhere in this code. If you've actually used "comboBox1" in the connect statement, but this is just another typo in the code you've presented here, then the connect statement is fine. If this is a cut-and-paste as-is, then I don't see how this compiles.
Assuming that you've used "comboBox1" in the connect statement, then the real problem is that you're never assigning to the member variable "comboBox2" and when your slot tries to use it, you get a crash.

Why is the recommended QDialog instantiation the way it is?

I have a Qt Widgets application, created and edited in Qt-Creator.
The main window (MainWindow class) has a menubar, with a button to open a small dialog (with text or widgets for settings).
To create a new "window" I open the "create new file" dialog in Qt-Creator and select Qt Designer Form Class, which creates the needed header, source, and ui files (dialogabout.h, dialogabout.cpp, dialogabout.ui).
If I follow along with the docs, I then open the QDialog like so:
QDialog * widget = new QDialog;
Ui::DialogAbout about_ui;
about_ui.setupUi(widget);
widget->exec();
This works, but if I modify the new dialog's instantiator to connect a pushbutton to the close signal, the connect statement (along with any other code there) is never reached.
DialogAbout::DialogAbout(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogAbout)
{
ui->setupUi(this);
qDebug() << "I'm alive!"; // No output happens
connect(ui->pushButton_close, SIGNAL(clicked(bool)), this, SIGNAL(please_close())); // No signal created on pushbutton click.
}
I suspect that this is because I haven't explicitly done widget = new DialogAbout(this). If I instead instantiate the new dialog this different way:
DialogAbout * newwindow;
newwindow = new DialogAbout(this);
newwindow->exec();
Then the connect statement and qDebug work.
My question is: what are the pitfalls of deviating from the documentation's recommended way to create dialogs? Is there a way to get this functionality with the prior instantiation method?
Note that DialogAbout is not the same as Ui::DialogAbout. Ui::DialogAbout is a class of build placed in the UI namespace, created automatically by uic. In your project, the name of this file should be "ui_dialogabout h".
class Ui_DialogAbout
{
public:
QPushButton *pushButton_close;
void setupUi(QDialog *DialogAbout)
{
...
} // setupUi
void retranslateUi(QDialog *DialogAbout)
{
...
} // retranslateUi
};
namespace Ui {
class DialogAbout: public Ui_DialogAbout {};
} // namespace Ui
Here you use a class QDialog and uses the Ui::DialogAbout to build a layout in it. Note that Ui::DialogAbout has the function to create the components in QDialog.
QDialog * widget = new QDialog;
Ui::DialogAbout about_ui;
about_ui.setupUi(widget);
widget->exec();
If you specialize QDialog for DialogAbout your code should look like this:
DialogAbout * widget = new DialogAbout();
Ui::DialogAbout about_ui;
about_ui.setupUi(widget);
widget->exec();
But as setupUi() is already within DialogAbout, you cannot call again, resulting in:
DialogAbout * widget = new DialogAbout();
widget->exec();

Can field() be requested in a QWizard before initialization?

I am calling a QWizardPage from a function in the MainWindow
void MainWindow::NoiseFilling()
{
QWizard *wiz = new QWizard;
NoiseFillPage *pg = new NoiseFillPage(&data);
wiz->addPage(pg);
wiz->setWindowTitle("Noise Filling");
wiz->setOption(QWizard::NoBackButtonOnStartPage);
QVBoxLayout *ly = new QVBoxLayout;
QLabel *pb = new QLabel;
ly->addWidget(wiz);
ly->addWidget(pb);
connect(wiz,&QDialog::accepted,[&](){data.NoiseFill(wiz->field("percent").toInt(),wiz->field("factor").toString());});
connect(wiz,&QDialog::accepted,[&](){textEdit->setText("Dataset noise filled.\n");});
delete frame->layout(); // delete previous layout
frame->setLayout(ly);
wiz->show();
}
and the constructor of the WizardPage looks like that
NoiseFillPage::NoiseFillPage(DataFrame* df,QWidget* parent)
: QWizardPage(parent)
{
box = new QComboBox;
lab = new QLabel("Metadata factor");
lab_2 = new QLabel("% of missing values threshold to fill");
sb = new QSpinBox;
box->insertItem(0,*(df->className));
box->insertItems(1,*(df->namesMetaData));
sb->setMaximum(100);
sb->setMinimum(30);
sb->setValue(100);
QGridLayout *ly = new QGridLayout;
ly->addWidget(box,0,0);
ly->addWidget(lab,0,1);
ly->addWidget(sb,1,0);
ly->addWidget(lab_2,1,1);
setLayout(ly);
registerField("factor",box);
registerField("percent",sb);
}
I receive a segmentation fault when I accept (and therefore close) the dialog of the one-page wizard. The debugger stops on the connect instruction making me believe that the problem arises because I am requesting two fields which are not initialised in compile-time. It is also true that this connection would be made at run time so I am very confused. Does anybody have an idea of what is going on?
I figured out the problem. I was capturing by reference a local variable (wiz) in the lambda function which caused undefined behaviour even though the variable was still in scope when the lambda executed.

Working with two user interfaces - Qt 5.5

I have a simple MainWindow which has a button and an LineEdit. When I type something and click a button, a new Dialog appears with a label that is supposed to display the string I typed.
So basically, I have trouble sending information to another UI.
I tried working with the new class with a string variable, but it didn't work.
I will try to give an example of what I want to do.
//ui2 Dialog
ui2->label->setText(ui->LineEdit->text());
Ui is a an private variable, so it's not accessible from another class.
//mainwindow.cpp
MainWindow::MainWindow(QWidget*){
this->_dialog = new Dialog(this);
//...
}
MainWindow::on_pushButton_clicked(){
_dialog->_labe->setText(ui->lineEdit->text());
}
//dialog.h
class Dialog{
public:
QLabel* _label;
Dialog(QWidget* ){
_label = ui->label;
}
}

QtMenubar Call Slot

This is inside a Menu class. The problem is addAction. This works, but there is no connection to slot:
QMenu* menu2 = new QMenu("Test");
menu2->addAction("Test");
When I do this:
QMenu* menu2 = new QMenu("Test");
menu2->addAction("Test", Menu, test);
I get compiler error: "error: expected primary-expression before ',' token"
I mean to call the test() function in the Menu class. What am I doing wrong?
Well, the error comes from passing Menu as an argument. You say Menu is a class, and classes are not expressions on themselves.
If you need to call test on an instance of Menu, where Menu is not a derivate from QObject (ie. no slots available), then you can just create a slot in the widget that contains the QMenu itself (probably a QMainWindow), and implement the call in there!
Edit: to add an example.
class MainWindow : public QMainWindow {
Q_OBJECT
// Usual declarations...
private slots:
void myCustomSlot();
};
Now, say that you're populating the main window inside its constructor:
MainWindow::MainWindow(...) {
// Some initialization code
QMenu *menu2 = new QMenu("Test");
menu2->addAction("Test", this, SLOT(myCustomSlot));
// Some more initialization code
}
// ...
void MainWindow::myCustomSlot() {
instanceOfMenu->test();
}
Of course, if you're creating the menu outside that class, you'd need to make the slot public, but that's another issue