I am trying to subclass QEditLine so that I can define a new SIGNAL that sends an object identifier. At the moment, I connect a parent signal to a slot in the new class and from that slot I emits a proper new signal with the additional object identifier.
I cannot understand one thing. The problem is I don't know how to define a new signal function itself. I don't know what I should put there. I mean I know its arguments but I don't know what it shpould do as a function. I am doing this for the first time and it may looks very silly ;p but I really stuck there >.<.
Can anybody please provide some clues. It is probably a very easy problem.
Thanks
// myqeditline.h
#ifndef MYQEDITLINE_H
#define MYQEDITLINE_H
#include <QWidget>
#include <QLineEdit>
#include <QString>
class MyQEditLine : public QLineEdit
{
Q_OBJECT
public:
explicit MyQEditLine(const QString& n, QWidget *parent = 0);
protected:
QString name;
signals:
void textChanged(QString textCHanged, QString sender);
protected slots:
public slots:
void myTextChanged(QString textChanged);
};
#endif // MYQEDITLINE_H
// myqeditline.cpp
#include "myqeditline.h"
MyQEditLine::MyQEditLine(const QString &n, QWidget *parent)
: QLineEdit(parent),name(n) {
connect(this,SIGNAL(textChanged(QString)),this,SLOT(myTextChanged(QString)));
}
void MyQEditLine::myTextChanged(QString textChanged) {
emit textChanged(QString textChanged, QString name);
}
I just realised that the answer to my question is on this Qt Project website, in section regarding "Signals", in 4th paragraph. It says: "Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void)."
Related
I have a MainWindow class which is declared in mainwindow.h and defined in mainwindow.cpp respectively like this:
In mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
...
void addNewTab(QString fullFilePath, QString textString="");
public slots:
void disableMenuItem();
...
private:
...
};
In mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
...
connect(this, &MainWindow::addNewTab, this, &MainWindow::disableMenuItem);
...
}
void MainWindow::addNewTab(QString fullFilePath, QString textString)
{
...
}
void MainWindow::disableMenuItem()
{
...
}
Everything compiles and run fine except for the following message on the console:
QObject::connect: signal not found in MainWindow
The message come from the connect call in the constructor above. What does that message mean in my case, and where am I doing wrong?
As drescherjm and Learner mentioned, you forgot to add a signals: section to your header file, and declare your signal within it.
Qt connects signals to slots at runtime, not at compile time, so mis-connected signals and slots cannot be detected until the program is actually run; that's why this problem is reported when it is.
Qt uses the moc preprocessor to turn signals and slots into standard c++, so that's why the signals: and slots: sections of your header will not cause problems when compiling.
Signals are fully defined by moc, so you do not need to define them in your .cpp file, but they still need to be in the header so moc knows to create them.
EDIT:
It appears that you are trying to use a signal with the name of one of your class functions. I don't think that's going to work. the documentation for the new signal/slot syntax indicates that you can connect TO anything, it doesn't have to be a slot, but I believe you still need to define your signal as a signal.
I'm having trouble moving from VC++ to Qt-style programming with slots/signals. I wanted to create a button with an image that, when clicked, changed to another image, and when released, changed back to its original. I created a class called ClickableQLabel that inherits from QLabel, but it's telling me that certain functions are re-defined. Specifically, the ones that are emitted.
MainProgram.cpp
#include "MainProgram.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
CodeVault w;
w.show();
return a.exec();
}
MainProgram.h
#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H
#include <QMainWindow>
#include "clickableqlabel.h"
namespace Ui {
class MainProgram;
}
class MainProgram : public QMainWindow
{
Q_OBJECT
public:
explicit MainProgram(QWidget *parent = 0);
~MainProgram();
private:
Ui::MainProgram *ui;
};
#endif // MAINPROGRAM_H
clickableqlabel.h
#ifndef CLICKABLEQLABEL_H
#define CLICKABLEQLABEL_H
#include <QLabel>
#include <QMouseEvent>
using namespace Qt;
class ClickableQLabel : public QLabel {
Q_OBJECT
QPixmap pushed;
QPixmap unpushed;
public:
ClickableQLabel(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *eve );
void mouseReleaseEvent(QMouseEvent *eve );
void setPushed(QPixmap &p);
void setUnpushed(QPixmap &p);
signals:
void leftButtonPressed(ClickableQLabel* sender);
void leftButtonReleased(ClickableQLabel* sender);
};
#endif // CLICKABLEQLABEL_H
clickableqlabel.cpp
#include "clickableqlabel.h"
ClickableQLabel::ClickableQLabel(QWidget *parent) : QLabel(parent){
// set up qlabel
}
void ClickableQLabel::setPushed(QPixmap &p){
pushed = p;
}
void ClickableQLabel::setUnpushed(QPixmap &p){
unpushed = p;
}
void ClickableQLabel::leftButtonPressed(ClickableQLabel* sender){
if(!pushed.isNull())
sender->setPixmap(pushed.scaledToWidth(sender->width()));
}
void ClickableQLabel::leftButtonReleased(ClickableQLabel* sender){
if(!unpushed.isNull())
sender->setPixmap(unpushed.scaledToWidth(sender->width()));
}
void ClickableQLabel::mousePressEvent(QMouseEvent *eve ){
if(eve->button() == Qt::LeftButton){
emit leftButtonPressed(this);
}
}
void ClickableQLabel::mouseReleaseEvent(QMouseEvent *eve ){
if(eve->button() == Qt::LeftButton){
emit leftButtonReleased(this);
}
}
What I receive is the following 3 errors:
moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonPressed(class ClickableQLabel *)" (?leftButtonPressed#ClickableQLabel##QEAAXPEAV1##Z) already defined in clickableqlabel.obj
moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonReleased(class ClickableQLabel *)" (?leftButtonReleased#ClickableQLabel##QEAAXPEAV1##Z) already defined in clickableqlabel.obj
debug\CodeVault.exe:-1: error: LNK1169: one or more multiply defined symbols found
The two functions that are causing the errors are the two signals in the clickableqlabel.h file. How am I supposed to set up the connect function and where?
You shouldn't provide an implementation for your signals. You just declare signals in the class header. the Qt moc provides an implementation that is responsible to call the slots connected to the signal when it is emitted, see this. Because you are providing an implementation and Qt moc is providing another one, you end up with two different implementations and the linker complains.
so, to make some piece of code execute when a signal is emitted, you can put it in some slot that is connected to that signal, or you can execute it manually before emitting the signal. . .
Another thing to note is that your signals have a parameter named sender. normally there is no need to do this, QObject::sender() provides similar functionality.
How am I supposed to set up the connect function and where?
When you instantiate your ClickableQLabel in your MainProgram window for example (You can do this by using ClickableQLabel in a .ui form file), you can connect its signals to slots of the MainProgram, like this.
mainprogram.h
#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H
#include <QMainWindow>
#include "clickableqlabel.h"
namespace Ui {
class MainProgram;
}
class MainProgram : public QMainWindow
{
Q_OBJECT
public:
explicit MainProgram(QWidget *parent = 0);
~MainProgram();
public slots:
void labelPressed();
void labelReleased();
private:
Ui::MainProgram *ui;
};
#endif // MAINPROGRAM_H
then in the constructor connect the ClickableQLabel's signals to the MainProgram's slots , something like this:
connect(clickableLabel, SIGNAL(leftButtonPressed()), this, SLOT(labelPressed()));
where clickableLabel is your ClickableQLabel object.
You should not explicitly define signal "functions" - they are simply emitted (as you do in the mousePressEvent() and mouseReleaseEvent() functions).
If you want some action performed (such as setPixmap), you would either do that in the slot functions that are connected to those signals, or perhaps directly in the mousePressEvent and mouseReleaseEvent functions.
Unrelated, but you may also need to do something like qRegisterMetaType<ClickableQLabel>() to use that data type with the signal/slot mechanism.
You don't need to subclass QLabel to achieve this: put an onLabelButtonClicked slot (method) in your MainWindow class, which is connected to the QPushButton clicked() signal, and which calls setText / setIcon as required.
If you want to re-use this clickable element you can of course encapsulate it in a class, but subclassing and handling raw-events is only required in Qt when defining new kinds of widget; if you're simply composing standard functionality (being clicked, adjusting appearance) then slots on your main window / dialog class are usually sufficient.
I need to know what am I doing wrong.
I tried researching about it but I can't really find anything that it's related to my case. I am new to QT and debugging signal and slots is kinda technical for me.
What I wanted to do is just simple: make a thread that will continuously send signal to my QProgressBar widget.
Here's my essential code snippets:
thread.h
class MyThread : public QThread
{
public:
MyThread(QWidget * parent = 0);
signals:
void valueChanged(int value);
protected:
void run();
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyThread * test = new MyThread(this);
connect(test,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
test->start();
}
thread.cpp
MyThread::MyThread(QWidget * parent)
{
}
void MyThread::run(){
emit valueChanged(10); //for simplicity
}
void MyThread::valueChanged(int value){
}
I only have a single progressBar on my UI and my main is the same as the default.
Anyway, upon running of the code. I kept on getting this no such signal from my thread class. May I know what am I doing wrong?. I would also like to clarify if my understanding is right regarding signals and slots in my own words: it means that the slot will be triggered everytime the signal is called.
I believe the error message is due to a missing Q_OBJECT macro at the top of your MyThread declaration. The documentation at http://doc.qt.io/qt-5/signalsandslots.html explains this is necessary for any class that wants to declare signals and slots.
Change your class definition to:
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QWidget * parent = 0);
signals:
void valueChanged(int value);
protected:
void run();
};
Take a look at the linked documentation, specifically the A Small Example section, for a complete explanation why this is needed.
You must not implement a signal in a .cpp file. MOC will do that and there must only be one implementation.
Just delete this part:
void MyThread::valueChanged(int value){
}
If your code works, that might be luck because the linker throws away the right implementation. You should not rely on that.
I am trying to add property title into the main window of my application. But when I try to compile it, the compiler gives me this error:
mainwindow.cpp:19: undefined reference to `MainWindow::titleChanged(QString const&)'
I tried it on mingw and msvc2013 both fails on the same line with this error. The header/source files:
mainwindow.h:
#ifndef MAINWINDOW
#define MAINWINDOW
#include <QObject>
#include <QString>
class MainWindow : public QObject {
QOBJECT_H
Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
public:
MainWindow();
QString getTitle();
public slots:
void setTitle(const QString& title);
signals:
void titleChanged(const QString& title);
private:
QString title_;
};
#endif // MAINWINDOW
mainwindow.cpp:
#include "mainwindow.h"
#include <QString>
MainWindow::MainWindow()
{
}
QString MainWindow::getTitle()
{
return title_;
}
void MainWindow::setTitle(const QString& title)
{
if (title_ != title) {
title_ = title;
emit titleChanged(title);
}
}
If I add the method below to the end of mainwindow.cpp file, then the application compiles and runs, but the signal isn't emitted:
void MainWindow::titleChanged(const QString&)
{
}
I tried to cleaning out the project's build folders, it doesn't help :(. I am using QT 5.4 and working on QT Creator.
This question was already answered in comments by someone else. I just wanted to highlight the answer. The error in my case was in the header file
mainwindow.h:
class MainWindow : public QObject {
QOBJECT_H // This should be Q_OBJECT
...
I confused the QOBJECT_H macro used in QObject.h header file as an include guard with the Q_OBJECT macro used by QT's moc tool. Since the intellisense will offer you both options, they are easy to confuse.
I also got pointed to a good reading about common problems with signals/slots worth for reading: My signal / slot connection does not work
I want to read a 50MB file and send it over tcp. The file contains only floats. First I created only a Mainwindow, witch reads one line and sends it to the Server, but the gui got frozen. So I created a class that depends on QThread called QSendThread. Here is the Code for the class QThread:
#ifndef QSENDTHREAD_H
#define QSENDTHREAD_H
#include <QThread>
#include <QLabel>
#include <QFile>
#include <QMessageBox>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QHostAddress>
class QSendThread : public QThread
{
Q_OBJECT
public:
QSendThread(QTcpSocket* qtcpso, QLabel* qlbl, QFile* qfiel, QObject *parent = NULL);
~QSendThread();
protected:
void run(void);
private:
QTcpSocket* qtcpsoDest;
QLabel* qlblRef;
QFile* qfileRef;
signals:
void error(QString qstrError);
};
#endif // QSENDTHREAD_H
#include "qsendthread.h"
QSendThread::QSendThread(QTcpSocket* qtcpso, QLabel* qlbl, QFile* qfile, QObject *parent)
: QThread(parent)
{
qtcpsoDest = qtcpso;
qlblRef = qlbl;
qfileRef = qfile;
}
QSendThread::~QSendThread()
{
}
void QSendThread::run(void)
{
int iLine = 0;
do
{
QByteArray qbarrBlock;
QDataStream qdstrmOut(&qbarrBlock, QIODevice::WriteOnly);
// show witch line is read
qlblRef->setText(tr("Reading Line: %1").arg(++iLine));
qdstrmOut.setVersion(QDataStream::Qt_4_6);
qdstrmOut << (quint16)0;
qdstrmOut << qfileRef->readLine().data();
qdstrmOut.device()->seek(0);
qdstrmOut << (quint16)(qbarrBlock.size() - sizeof(quint16));
qtcpsoDest->write(qbarrBlock);
qtcpsoDest->flush();
qbarrBlock.clear();
} while(!qfileRef->atEnd());
}
But the program crashing in the method qregion::qt_region_strictContains(const QRegion ®ion, const QRect &rect)
Is the method to read the file like I am doing wrong?
Thanks for Help.
First, you shouldn't really need to subclass QThread. The Qt documentation is misleading on this point. See this accepted answer for a similar question for lots of good info.
Second, you can only correctly access the gui from the main thread so your call qlblRef->setText() would be a problem. Accessing the gui from a thread other than the main one can be done using signals and slots or postEvent(). You can read up on events here.
Finally, this documentation is really required reading for working with threads in Qt. Pay particular attention to the section on threads and QObjects.
Addition:
To follow the advice above, you could certainly wrap your file reading code in a QObject subclass. An alternative (which I have little experience with myself) may be to try putting your code in QtConcurrent::run() and getting the result with a QFuture.