I have inherited a class MainTree from QTreeview
maintree.cpp file
void MainTree::LaunchTree()
{
//Tree launching
connect(this, SIGNAL(customContextMenuRequested(const QPoint& )),this,SLOT(showCustomContextMenu(const QPoint&)));
}
void MainTree::showCustomContextMenu(const QPoint &pos)
{
//Add actions
}
But i get the following error
QObject::connect: No such slot QTreeView::showCustomContextMenu(const QPoint&)
I could not understand why, am i missing something ??
Definition of the class MainTree
class MainTree : public QTreeView
{
public:
MainTree();
MainTree(QWidget *parent = 0);
public slots:
private slots:
void showCustomContextMenu(const QPoint& pos);
private:
void launchTree();
};
You are missing the Q_OBJECT macro out, so try this:
class MainTree : public QTreeView
{
Q_OBJECT
// ^^^^^
public:
MainTree();
MainTree(QWidget *parent = 0);
public slots:
private slots:
void showCustomContextMenu(const QPoint& pos);
private:
void launchTree();
};
Do not forget to re-run qmake after this to regenerate the moc files properly. Make sure you have the moc include at the end of your source code, or you handle the moc generation without that.
Also, note that if you used Qt 5.2 or later with C++11 support, you would get a static assertion about the missing Q_OBJECT macro, so you would not get runtime issues anymore. I suggest to follow that if you can.
When referring to slot and signals you have to omnit all decoration: const & and so on (only star can remain).
connect(this, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(showCustomContextMenu(QPoint)))
Also you forgot about Q_OBJECT macro.
Related
class TDF : public QMainWindow
{
Q_OBJECT
public:
explicit TDF(QWidget *parent = nullptr);
~TDF();
private slots:
void on_umwelt_clicked();
void on_regional_clicked();
void on_pushButton_clicked();
void on_autofahrt_clicked();
void on_flugzeug_clicked();
void on_bestell_clicked();
int anzahl=3;
private:
Ui::TDF *ui;
};
#endif // TDF_H
This is my header. I tried starting the application, but it keeps saying Error: Not a signal or slot declaration.
Please help me :(
Solved the Problem. Int anzahl is not a slot but was in private slots as Seen above
I need to call a method after the ui has been shown,so i want to connect
the frame with itself,in particular using the show signal.
I've created a new form with auto generated code by qtcreator.This is the auto generated header.
#define STARTWINDOW_H
#include <QMainWindow>
namespace Ui {
class StartWindow;
}
class StartWindow : public QMainWindow
{
Q_OBJECT
public:
explicit StartWindow(QWidget *parent = 0);
~StartWindow();
private:
Ui::StartWindow *ui;
public slots:
void doSomething();
};
#endif // STARTWINDOW_H
in the cpp file no one of the following codes work
connect(ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(*ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(this->ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
What's the right way to do it?
That signal does not exist by default, we must create it, we can override the showEvent() method:
.h
protected:
void showEvent(QShowEvent *event);
signals:
void showSignal();
.cpp
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
void StartWindow::showEvent(QShowEvent *event)
{
emit showSignal();
QMainWindow::showEvent(event);
}
void StartWindow::doSomething()
{
qDebug()<<"show";
}
Or you can override the eventFilter method.
.h
protected:
bool eventFilter(QObject *watched, QEvent *event);
signals:
void showSignal();
.cpp
installEventFilter(this);
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
bool StartWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched==this && event->type() == QEvent::Show)
emit showSignal();
return QMainWindow::eventFilter(watched, event);
}
There are a few things wrong here:
There is no show() signal and
Even if there were, you aren't using connect correctly.
First, if your class were defined like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void someSignal();
public slots:
void doSomething() {}
private:
Ui::MainWindow *ui;
};
The appropriate call to connect in the constructor would be:
QWidget::connect(this, SIGNAL(someSignal()), this, SLOT(doSomething()));
Even if there were a show signal, you wouldn't get it from ui, you would get it from this. The UI classes are just dumb containers for widgets that you add through the designer.
To perform some action when your class is shown, you can either override
virtual void showEvent(QShowEvent *); (more robust, but slightly more complex)
or simply define your own show() slot that does what you want and calls QWidget::show() at the end of it. I prefer the latter, so I will show you that.
Start by defining your show slot like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void doSomething() {}
void show();
private:
Ui::MainWindow *ui;
};
Then, in your implementation file, do this:
void MainWindow::show()
{
doSomething();
QWidget::show();
}
I have worked with the Qt framework for quite some time now, and I have never needed to override the show event; it is simply not worth it for most use cases. If you really want a show signal that others can connect to, just add a custom signal for it and emit in in MainWindow::show(). Only resort to overriding event handlers if you can't make this work for what you are doing(very rarely necessary).
in my Qt program I need the dialog to send a signal to a slot in the mainwindow. I have set the connection up correctly to the best of my knowledge and it does not give me any errors during compile or run time but for some reason it just doesn't do anything when the button that is supposed to activate the signal is clicked. Why is this happening?
beastiary.h (mainwindow header)
namespace Ui {
class Beastiary;
}
class Beastiary : public QMainWindow
{
Q_OBJECT
public:
explicit Beastiary(QWidget *parent = 0);
Ui::Beastiary *ui;
QStringList MyList;
~Beastiary();
public slots:
void refresh();
private slots:
void on_pushButton_clicked();
void on_listWidget_itemClicked(QListWidgetItem);
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
beastiary.cpp (mainwindow cpp file)
Beastiary::Beastiary(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Beastiary)
{
ui->setupUi(this);
Dialog dialog;
connect(&dialog, SIGNAL(gorefresh()),this, SLOT(refresh())) ;
void Beastiary::refresh()
{
qDebug () << "recieved";
ui->listWidget->clear();
QString path = "C:/Program Files/Bargest/bin";
QDir myPath(path);
myPath.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
MyList = myPath.entryList();
ui->listWidget->addItems(MyList);
}
dialog.h
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
signals:
void gorefresh();
private slots:
void on_pushButton_done_clicked();
void on_pushButton_cancel_clicked();
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
dialog.cpp
void Dialog::on_pushButton_done_clicked()
{
emit gorefresh();
}
I did leave out large parts of the code that just have nothing to do with the actual signals and slots mechanism at play here.
You're only connecting the dialog instance you created locally in the Bestiary's constructor, which goes out of scope as the constructor finishes.
connect is connecting instances, not classes. That means you need to connect each created dialog:
void Beastiary::on_pushButton_clicked() {
Dialog* ad = new Dialog(this);
connect(ad, SIGNAL(gorefresh()), this, SLOT(refresh()));
ad->show();
}
While at it, you should seriously consider using the type-safe connect syntax that came with Qt 5:
void Beastiary::on_pushButton_clicked() {
Dialog* ad = new Dialog(this);
connect(ad, &Dialog::gorefresh, this, &Bestiary::refresh));
ad->show();
}
I have been reading about Qt signals and slots and I am trying to get this to work, but until now without success. I hope someone can point me in the right direction.
I have two files, homeCommand.cpp and messagelogcommand.cpp. I have a QPlainTextEdit object in messagelogcommand.cpp that I want to update from homeCommand.cpp.
How can I do this using signals and slots? My signal is being called, as my QDebug is being printed out once a second, however the widget does not update.
This is what I am trying to do:
In MessageLogCommand.h
class MessageLogCommand : public QWidget
{
Q_OBJECT
public:
explicit MessageLogCommand(QWidget *parent = 0);
QLabel *homeLabel;
QPlainTextEdit *messageLog;
public Q_SLOTS:
void updateWidgets(const QString &text);
};
homeCommand.h
class homeCommand : public QWidget
{
Q_OBJECT
Q_SIGNALS:
void textChanged(const QString &text);
public:
explicit homeCommand(QWidget *parent = 0);
public slots:
void run(void);
void getHealthStatusPacket(void);
homeCommand.cpp
homeCommand::homeCommand(QWidget *parent) : QWidget(parent)
{
...
//Timer
QTimer *timer = new QTimer(this);
timer->setSingleShot(false);
connect(timer, SIGNAL(timeout()), this, SLOT(run()));
timer->start(1000);
setLayout(layout);
}
void homeCommand::run(void)
{
getHealthStatusPacket();
}
void homeCommand::getHealthStatusPacket(void)
{
...
Q_EMIT textChanged("ZOMG");
}
In MessageLogCommand.cpp
MessageLogCommand::MessageLogCommand(QWidget *parent) : QWidget(parent)
{
QGridLayout *layout = new QGridLayout;
QWidget::setFixedHeight(600);
//Sub-system Label
homeLabel = new QLabel("GSS Message Log");
QFont subsystemFont = homeLabel->font();
subsystemFont.setPointSize(12);
subsystemFont.setBold(true);
homeLabel->setFont(subsystemFont);
layout->addWidget(homeLabel, 0, 0);
//Event Log
messageLog = new QPlainTextEdit();
messageLog->setFixedHeight(500);
messageLog->setFixedWidth(600);
layout->addWidget(messageLog, 2,0);
setLayout(layout);
}
void MessageLogCommand::updateWidgets(const QString &text)
{
qDebug() << "Here";
messageLog->appendPlainText(text);
}
In main.cpp
MessageLogCommand s;
homeCommand m;
QObject::connect(&m, SIGNAL(textChanged(QString)), &s, SLOT(updateWidgets(QString)));
A very basic example is:
class MainClass:public QObject //class must be derived from QObject!
{
Q_OBJECT //this macro must be in the class definition
//so the moc compiler can generate the necessary glue code
public:
void doSomething() {
...
Q_EMIT textChanged(someText);
}
Q_SIGNALS:
void textChanged(const QString &text);
};
class SubClass:public QObject
{
Q_OBJECT
public Q_SLOTS:
void onTextChanged(const QString &text) { //do not inline
//do something
}
};
int main()
{
QApplication a;
MainClass m;
SubClass s;
QObject::connect(&m, SIGNAL(textChanged(QString)),
&s, SLOT(onTextChanged(QString))); //const and & are removed from
//the arguments
return a.exec(); //run the event loop
}
So, there are 2 things important:
1. Signals and slots must be declared in a class derived from QObject
2. The classes containing signals and slots declarations must add the Q_OBJECT macro to the class declaration
To keep it simple for you: always declare your classes containing signals or slots in a header file (never in a .cpp file).
A very good starting point for signals and slots is: http://woboq.com/blog/how-qt-signals-slots-work.html but also the official Qt doc does it: http://qt-project.org/doc/qt-4.8/signalsandslots.html
Basically what happens: you declare some special methods (signals and slots), at the compilation phase Qt generates extra CPP files which take care of your methods (moc) then everything is compiled and linked together and at the end when Qt or someone else emits a signal it will go to the corresponding slot.
I try to explain it.
In main.h you should to declare a signal:
signals:
void textChanged(const QString& text);
And in messagelog.h you should to declare a slot:
public slots:
void updateWidgets(const QString& text);
In main.cpp you should emit this signal:
void TheMethod() {
emit this->textChanged("Your text/value");
}
In messagelog.cpp you should get this value:
// Note: Normalized signal/slot signatures drop the consts and references.
connect(&a, SIGNAL(textChanged(QString)), this, SLOT(updateWidgets(QString)));
void updateWidgets(const QString& text) {
messageLog = new QPlainTextEdit();
messageLog->setFixedHeight(500);
messageLog->setFixedWidth(600);
messageLog->setPlainText(text)
layout->addWidget(messageLog, 2,0);
}
I think it should works.
UPDATE:
Complete example: https://dl.dropboxusercontent.com/u/29647980/test.zip
I am a newbie in Qt and C++ programming. I have some problem in my program that i need a solution for.
I have two files MainWindow.h and ChatWindow.h, which contains two classes of MainWindow and ChatWindow.
This is chatwindow.h
namespace Ui {
class ChatWindow;
}
class ChatWindow : public QMainWindow
{
Q_OBJECT
public:
explicit ChatWindow(QWidget *parent=0);
~ChatWindow();
private slots:
void send_chat_fn(pjsua_call_id call_id);
void rcv_chat_fn(pjsua_call_id call_id);
void rcv_msg_fn(QString msg);
void on_pushButton_clicked();
void on_actionQuit_triggered();
private:
Ui::ChatWindow *ui;
};
And this is mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void add_item(QString buddy_uri);
signals:
void send_chat(pjsua_call_id call_id);
void rcv_chat(pjsua_call_id call_id);
void rcv_msg(QString msg);
private slots:
void on_actionAdd_Buddy_triggered();
void on_actionQuit_triggered();
void on_actionStatus_triggered();
void on_actionNew_Chat_triggered();
void on_action_Configuration_triggered();
void on_listWidget_doubleClicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
};
Now i want to connect signals from mainwindow.h to slots in chatwindow.h.
I have tried connection in the constructor of class ChatWindow, but it does not work (i think that is because connections work on instances not on classes). Instance of MainWindow class which i want to connect is in mainwindow.cpp. Defining instances of class ChatWindow in MainWindow gives error:
Cannot set parent, parent is in different thread
And if i create a new instance in Constructor of ChatWindow, then it doesnt connect to the desired instance.
Its a complete mess. Please help me through this.