Qt5 Signal and slots does not seem to work - c++

I am trying to change a label's text to a slider's value when the slider moves. My slider is named sld_bet and my label is lbl_bet. sld_bet_changed() is a function that only has a breakpoint in it, and will eventually contain lbl_bet's modifying code.
The breakpoint is never reached, and I do not understand why.
app::app(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.sld_bet, SIGNAL(ui.sld_bet->sliderMoved()),
this, SLOT(sld_bet_changed()));
}

change to
connect(ui.sld_bet, SIGNAL(sliderMoved()), this, SLOT(sld_bet_changed()));

If you are using Qt 5, use the new connect syntax. That way the compiler will throw an error if something is not correct.
connect(ui.sld_bet, &QSlider::sliderMoved, this, &app::sld_bet_changed);

Related

Slot doesnt exist in connect function in C++/Qt project? (already reran make)

I am adding a slider bar to easyPaint, which will enable a zoom function.
I have the slider appearing where I want it on the screen, and the function I built for it shouldn't have any issues, but when I run it, I get a runtime error that the slot doesn't exist, when it clearly does.
I have already tried cleaning the solution, rerunning CMake, and rebuilding, and still get the "slot does not exist" error every time.
Can anyone else think of any other reason why I would get this issue?
Here is the setup of the dock with slider, within the mainwindow class:
dock = new QDockWidget(tr("Zoom"));
slider = new QSlider(dock);
addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setWidget(slider);
dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
slider->setOrientation(Qt::Horizontal);
slider->setMinimum(0);
slider->setMaximum(16);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(zoomBarAct(slider->value())));
Here is the zoom function, which I have declared within the private slots section in the header file:
void MainWindow::zoomBarAct(int zoom)
{
float factor = static_cast<float>(zoom) / 4;
getCurrentImageArea()->zoomImage(factor);
getCurrentImageArea()->setZoomFactor(factor);
}
edit for function declaration (other functions after private slots omitted):
private slots:
void zoomBarAct(int zoom);
This:
SLOT(zoomBarAct(slider->value()))
doesn't make sense. You need to specify the name of the slot:
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(zoomBarAct(int));
However, you are using Qt4-style signal/slot connections. If you switch to modern, Qt5-style syntax, these errors will be caught at compile time. Use this instead, which is much safer and guaranteed to never produce these types of runtime errors, since everything is checked during compilation:
connect(slider, &QSlider::valueChanged, this, &MainWindow::zoomBarAct);

Qt action won't connect to slot

Writing a school project in c++ and qt. It is supposed to be a block editor (like draw.io). I generate blocks as a buttons and setting them to a grid. Each button is supposed to have own menu to be able to get edited, deleted, etc. (image example:
We are encountering a problem, that our action won't connect to a slot. Function akceAkce is supposed only to print 1 onto output (via qInfo). But when I click on the menu button, it does nothing. Any suggestions appreciated. Thanks!
void BlockItem::createButton() {
this->button = new QPushButton("+");
this->buttonMenu = new QMenu(this->button);
this->connectBlocks = new QAction(tr("Connect"), this->buttonMenu);
connect(this->connectBlocks, &QAction::triggered, this, &BlockItem::akceAkce);
this->buttonMenu->addAction(this->connectBlocks);
this->button->setMenu(this->buttonMenu);
}
void BlockItem::akceAkce() {
qInfo("1");
}
I would suggest a possible explanation: you put the BlockItem instance on the stack, and it's going out of scope somewhere in your code, and destroyed consequently, while the push button, menu and action all survive it, since they're instantiated with new, thus they live on the heap.
Something like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
BlockItem blockitem;
blockitem.createButton();
ui->gridLayout->addWidget(blockitem.getButton());
}
In the sample code above, blockitem goes out of scope at the end of the method, so it is destroyed and the connection loses its receiver side (i.e. breaks).
The same would happen if you instantiate a BlockItem object on the heap, using new, but accidentally delete it somewhere. Again, the signal sender (the QAction object) survives the receiver and the connection is broken.

QWidget winId crashing if called from constructor

I'm writing a program, where i callQWidget::winId()in the constructor:
debug_window::debug_window(QWidget *parent) :
QDialog(parent),
ui(new Ui::debug_window),
hk(NULL)
{
this->ui->setupUi(this);
this->hk = new TestClass(this, this->winId())
}
But this will cause my program to crash, even before a window is created. I already figured out that the call of winId causes the crash, probably because at this time there is no window existing. (correct me if I'm wrong).
Sadly, there is no signal "windowCreated()" or something similar. So is there any way to find out that the window was created, or how to in general solve this problem?
Thanks for your help.
Create signal and emit him in the end of constructor.

Why is the signal for the QCheckBox not emitted?

I am trying to insert in my UI a check box which can set a boolean variable from another class true or false according to its checked status. The problem is that the signal is not emitted.
The variable is defined in the header file of my 1st class (renderarea.h) as public:
bool selectionMode;
The slot is defined in the 2nd class' header file as void
protected slots:
void setSelectionMode(bool mode);
And the signal is connected to the slot in my 2nd class source file in the constructor as:
PaintWidget::PaintWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PaintWidget)
{
connect(ui->selectionModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSelectionMode(bool)));
}
void PaintWidget::setSelectionMode(bool mode)
{
ui->displayWidget->selectionMode = mode;
QMessageBox msgbox;
if (ui->displayWidget->selectionMode == true)
msgbox.setText("selection mode is true");
else
msgbox.setText("selection mode is false");
}
I am using the QMessageBox here only for testing reasons. But when debugging I saw that the signal is not emitted. What am I doing wrong?
You'll want to make sure a number of things are in place:
setupUi
connect succeeded
checkbox value really changed
First, I don't see where you called setupUi. You'll want to do this in the constructor:
PaintWidget::PaintWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PaintWidget)
{
ui->setupUi(this);
connect(ui->selectionModeCheckBox,
SIGNAL(toggled(bool)), this, SLOT(setSelectionMode(bool)));
}
Second, make sure that the return value of connect indicates it succeeded.
Third, I presume you're manually clicking the checkbox, but for sake of testing you could do that after the connect in your constructor:
ui->selectionModeCheckBox->setChecked(true);
Just to clarify, when you say the slot is in the header file, you do mean after the slots: label, right?
You should rather use the stateChanged() signal, emitted by the checkbox when its status changes. It gives you an integer, because checkboxes can also be tristate (but you can just use that int value as a boolean, in your case).
well,I often use the checkbox in the Dialog(settingDialog, selectionDialog,etc), so signal-slot is not need in this situation,just check the checkbox state when the "OK" button is clicked, and deal with it in the accept function.In your situation, I don't think checkbox is a good choice.

setCentralWidget() causing the QMainWindow to crash.. Why?

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
this->setupUi(this);
this->setupActions();
this->setWindowTitle(tr("CuteEdit"));
label = new QLabel(tr("No Open Files"));
this->setCentralWidget(label);
label->setAlignment(Qt::AlignCenter);
}
By above code, I get a GUI like this(Its a screenshot of whole screen, Only observe the window displayed in middle of page of ebook). (I used QT Designer)
Now, i want user to select File->Open.. A Dialog appears and file gets selected.. Its contents are to be displayed in *textEdit widget..
Function for that is below..
void MainWindow::loadFile()
{
QString filename = QFileDialog::getOpenFileName(this);
QFile file(filename);
if (file.open(QIODevice::ReadOnly|QIODevice::Text))
{
label->hide();
textEdit->setPlainText(file.readAll());
mFilePath = filename;
QMainWindow::statusBar()->showMessage(tr("File successfully loaded."), 3000);
}
}
The window crashes at line:-
textEdit->setPlainText(file.readAll());
But if i comment the line:-
this->setCentralWidget(label);
i mean i remove label as being the central widget, the program runs as expected.. Why?
And also, I am not clear about the concept of CentralWidget. Pls guide.
JimDaniel is right in his last edit. Take a look at the source code of setCentralWidget():
void QMainWindow::setCentralWidget(QWidget *widget)
{
Q_D(QMainWindow);
if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
d->layout->centralWidget()->hide();
d->layout->centralWidget()->deleteLater();
}
d->layout->setCentralWidget(widget);
}
Do you see that if your MainWindow already had centralWidget() Qt schedules this object for deletion by deleteLater()?
And centralWidget() is the root widget for all layouts and other widgets in QMainWindow. Not the widget which is centered on window. So each QMainWindow produced by master in Qt Creator already has this root widget. (Take a look at your ui_mainwindow.h as JimDaniel proposed and you will see).
And you schedule this root widget for deletion in your window constructor! Nonsense! =)
I think for you it's a good idea to start new year by reading some book on Qt. =)
Happy New Year!
Are you sure it's not label->hide() that's crashing the app? Perhaps Qt doesn't like you hiding the central widget. I use Qt but I don't mess with QMainWindow that often.
EDIT: I compiled your code. I can help you a bit. Not sure what the ultimate reason is as I don't use the form generator, but you probably shouldn't be resetting the central widget to your label, as it's also set by the designer, if you open the ui_mainwindow.h file and look in setupGui() you can see that it has a widget called centralWidget that's already set. Since you have used the designer for your GUI, I would use it all the way and put the label widget in there as well. That will likely fix your problems. Maybe someone else can be of more help...
I'm not sure I understood your problem, neither what the guys above said (which I guess are valid information) and it seems to be an old topic.
However, I think I had a problem that looks like this and solved it, so I want to contribute my solution in case it helps anyone.
I was trying to "reset" central widget using QLabels. I had three different ones, switch from first to second, then to third and failed to switch back to the first one.
This is my solution that worked:
Header file
QLabel *imageLabel;
Constructor
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Reset
imageLabel = NULL;
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Hope that helps
Aris