C++ Qt Segmentation fault when trying to access method of an object - c++

I am learning Qt, and I have come up with a problem. I would like some help, here as I tried changing variables and debugging it, but haven't come up with a solution. I'll provide some code to understand the problem i have
In my ColorButton.h class file
class ColorButton : public QToolButton
{
Q_OBJECT
public:
explicit ColorButton(const QColor &color, QWidget *parent = 0);
void testMethod();
};
My ColorButton.cpp file is like this
ColorButton::ColorButton(const QColor &color, QWidget *parent)
{
//some code
}
void ColorButton::testMethod()
{
//This is
//a test method
}
I am trying to access this testMethod() from another class.
From this class, header file is Toolbar.h
class ToolBar : public QToolBar
{
Q_OBJECT
public:
explicit ToolBar(const QMap<ToolsEnum, QAction*> &actionMap, QWidget *parent = 0);
private:
void setToolbar(); //initialize items
ColorButton *test; //-----
public slots:
void setMainColorView();
}
The Toolbar.cpp file is like this
ToolBar::ToolBar(const QMap<ToolsEnum, QAction *> &actionMap, QWidget *parent) :
QToolBar(tr("Tools"),parent), actionMapVar(actionMap)
{
setToolbar();
}
void ToolBar::setToolbar()
{
test = new ColorButton(QColor("#8C001A"));
}
void ToolBar::setMainColorView()
{
test->testMethod();
}
}
The program works when i put test->testMethod(); into setToolbar() , but I want to create the object in setToolbar() and call the method in setMainColorView().
So far I have tried making the Color button variable public,
I have also tried initializing the object called test in the constructor, but both don't work.
Right now, with this code the error I get is
"The inferior stopped because it received a signal from the operating system.
Signal name: SIGSEGV
Signal meaning: Segmentation fault"
with an arrow pointing at test->testMethod(). I have no clue how to solve it, any help would be appreciated

I was looking at the wrong place the entire time. I solved this by passing my toolbar object into the class i was calling setMainColorView() from. In that class i made a local variable of the toolbar object, assigned this. And then it worked.

Related

Connect slots from another class not working in Qt

I have this class in button.h:
class Buttons : public QObject
{
Q_OBJECT
public:
Buttons();
QVector<QPushButton*> buttons;
public slots:
void getBtnInfo();
};
and in mainwindow.cpp, I connect like this:
Buttons mButtons;
for(int i = 0; i < mButtons.buttons.size(); i++) {
mButtons.buttons[i] = new QPushButton(mCentralWidget);
...
connect(mButtons.buttons[i], SIGNAL(clicked(bool)), &mButtons, SLOT(getBtnInfo()));
}
It runs without any errors; but the getBtnInfo() slot seems like not do anything. Because I tried simply just debug in this slot, not working.
But if I declare getBtnInfo() slot in mainwindow.h and connect like this:
connect(mButtons.buttons[i], SIGNAL(clicked(bool)), this, SLOT(getBtnInfo()));
then it works.
I wonder why? And how do I solve the problem above?
Thanks.
If a variable is created in a function it only exists in that function, then it will not be accessible, and that is what I think is happening, I recommend you to make mButtons a member of the class.
*.h
private:
Buttons mButtons;

Qt pass variables between forms

I want to pass a string from a form that is opened by the first form to the first form.
I am new to C++.
Here is my code.
Form1.h // main form
#include "dialog.h"
namespace Ui {
class Form1;
}
class Form1 : public QMainWindow
{
Q_OBJECT
public:
explicit Form1(QWidget *parent = 0);
~Form1();
void refresh(QString str_local);
private slots:
void on_pushButton_clicked();
private:
Ui::Form1 *ui;
Dialog *dialog1;
};
// form1.cpp
void Form1::on_pushButton_clicked()
{
dialog1= new Dialog; //Create new form with other class
dialog1->show();
QObject::connect(dialog1, SIGNAL(change(str_remote)), this, SLOT(refresh(str_local))); //Connect when is emit signal cambia in the child form and pass the string to local function
}
void Form1::refresh(QString str_local)
{
qDebug() << "Back to main" << str_local;
ui->label->setText(str_local);
}
// dialog.h the second form that should pass the value to main form
...
class Dialog : public QDialog
{
Q_OBJECT
signals:
void change(QString s);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
};
// dialog.cpp
...
void Dialog::on_pushButton_clicked()
{
QString name;
name = ui->lineEdit->text();
emit change(name);
this->close();
}
I get the error:
No such signal Dialog::change(str_remote) in ../Format/form1.cpp:22 .
You have some strange code in here:
QObject::connect(dialog1, SIGNAL(change(str_remote)), this, SLOT(refresh(str_local)));
Since your class already inherits QObject indirectly, you can simply drop the scope specifier.
You probably aim for using the new compilation-time syntax signal-slot mechanism.
You have not marked your slot as slot in the header file.
You are trying to use the old signal/slot syntax with variable names for the signal and slot as opposed to the types.
Your signal is not using the good practice of const T& (i.e. constant reference).
You are specifying this explicitly, whereas it can be dropped. This is just admittedly personal taste.
You do not follow the Qt signal/slot naming convention, e.g. your signal is a verb rather adjective. It is also too generic, rather than "fooChanged" as the good practice goes.
There are other issues in your code as well, but this time I only focused on that one line. I would use this line with modern Qt and C++ programming principles in mind:
connect(dialog1, &Dialog::changed, (=)[const auto &myString] {
ui->label->setText(myString);
});
However, since this requires CONFIG += c++14, if your compiler does not support that (e.g. VS2010), you can go for this:
connect(dialog1, SIGNAL(change(const QString&)), this, SLOT(refresh(const QString&)));

No matching signal for QAction, no "go to slot" menu entry

I have problem with actually running QActions created with QtCreator. To run e.g. actionSystemSettings, I've added slot to MainWindows so it looks like this:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_menuWork_actionSystemSettings();
private:
Ui::MainWindow *ui;
};
And this:
void MainWindow::on_menuWork_actionSystemSettings() {
qDebug() << "Yay!";
}
It prompts:
QMetaObject::connectSlotsByName: No matching signal for
on_menuWork_actionSystemSettings()
I guess it's some dumb mistake and I just forgot about something but reading documentation gives me nothing. I have no "go to slot" menu entry which should auto-create some template... at least Visual Studio for C# did that.
When you're defining slots the correct way is:
on_<widget_name>_<signal>
for instance if you have to name your slot
private slots:
on_actionSystemSettings_triggered();
See QtAutoConnect
According to the documentation for QMetaObject::connectSlotsByName():
Searches recursively for all child objects of the given object, and
connects matching signals from them to slots of object that follow the
following form:
void on_object-name_signal-name(signal-parameters);
So, I think your slot should have the following signature:
void MainWindow::on_actionSystemSettings_triggered()
{
//
}

Adding custom QWidget during runtime

I'm trying to implement a custom widget hierarchy:
QMainWindow -> QFrame -> MyWidget -> QFrame -> MySubWidget
Here is how MyWidget class looks like:
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget *parent = 0, ...);
...
public slots:
void SlotFunction(int i);
...
private:
MySubWidget *sub_w;
QFrame *sub_frame;
...
}
If I try to create an MySubWidget during MyWidget constructor, then all MySubWidget elements are shown as intended:
MyWidget::MyWidget (...) : QWidget(parent) {
...
sub_frame = new QFrame(this);
...
sub_w = new MySubWidget(sub_frame); // commented out on a runtime test
}
But if I try to add subwidget during runtime, sub_frame remains blank. I.e. signal reaction:
void MyWidget::SlotFunction(int i) {
sub_w = new MySubWidget(sub_frame); // update, repaint, show and hide methods aren't helphul
}
I know this is an old question, but I was having a very similar issue and it turned out to be a lack of call to the QWidget::show(). Perhaps that was your problem as well?
My question here: Dynamically add instance inherited from QWidget
Cheers.
Are you reaching your function?
At the top of your function before making a new instance of MySubWidget put:
qDebug() << Q_FUNC_INFO;
Is the slot connected properly?
Qt will let you know if it is unable to connect a slot using a runtime warning. Look at the debug output that shows up in Qt Creator and it may mention a reason why the slot was never reached.
Is subframe visible?
If the parent of your object isn't visible, then showing or hiding the child object will only affect it when the parent is shown.
Hope that helps. Good luck.

How would you access a widget from a function in another file in Qt?

I'm developing a project, and I first began making it without GUI, but now I'm porting it to Qt, but I have a problem.
I have my "old" implementation in a separate file, and I try to access the MainWindow widget from it, in order to output to a QTextBrowser, but I'm not able to do so.
In mainwindow.cpp I have this:
void MainWindow::addString(char* text)
{
std::string input = text;
ui->textBrowser->append(QString::fromStdString(input));
return;
}
In mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_showWelcome_triggered();
void on_showArithmetic_triggered();
private:
Ui::MainWindow *ui;
public slots:
void btnResolveClicked();
void btnClearClicked();
void hideAll();
void addString(char* output);
};
#endif // MAINWINDOW_H
And in simple_mode.cpp:
void test()
{
MainWindow *gui = new MainWindow;
gui->addString("WORKS");
MainWindow:: = gui;
}
However this doesnt append "WORKS" to the textbrowser, which is what I need, I think it adds it to another instance of text browser which isnt the same as the mainwindow.
EDIT:
What I wanted to do was appending a line of text directly from simple_mode.cpp to the textbrowser.
By the way, simple_mode was written without any Qt aid, that's why I used std strings, and currently the textbrowser widget acts as a virtual terminal output screen, and instead of using printf like I did before, I wanted to append lines to the textbrowser. However I already found my way through, I don't need this now.
I needed help
It's really hard to tell what do you want to achieve and pieces of code do not cover all possible erroneous areas (i.e. where's the MainWindow constructor's definition?). Also, the formatting is terrible - please use idents and consistent bracing style.
My advice is simply call show on MainWindow instance. Unless you don't mess up ui initialization in MainWindow constructor, this snippet should be enough. If it is not - supply us with missing pieces of code.
void test()
{
MainWindow *gui = new MainWindow;
gui->addString("WORKS");
gui->show();
}
As a side note, your addString method should look like this:
void MainWindow::addString(char* text)
{
ui->textBrowser->append(QString::fromAscii(text));
}
Return statement is completely unnecessary, and assigning text to std::string is likely to cause unnecessary memory allocation. It's not like it is the end of the world, but it's really, really bad practice for a C++ programmer.