Class inherited from QLabel, why custom slot is not called? - c++

I made class inherited from QLabel. This class also have public slot, that should change label caption. I "call" this SLOT with clicked() SIGNAL of button.
So nothing happened when I press the button.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
public:
Label(QString a) : QLabel(a){}
public slots:
void change()
{
this->setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked(bool)), lbl, SLOT(change()));
return a.exec();
}
What should I do to change caption from slot?

In order for the signals and slots to be recognized, the classes must use the Q_OBJECT macro in the private part.
Another thing to do is to include "main.moc", for more information on this point read this.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
Q_OBJECT
public:
Label(const QString &text, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
QLabel(text, parent, f){}
public slots:
void change()
{
setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked()), lbl, SLOT(change()));
return a.exec();
}
#include "main.moc"
At the end of making these changes you must execute the following:
Press clean all in the Build menu.
then run qmake in the same menu.
And you just compose your project.

Add Q_OBJECT after
class Label : public QLabel
{
and then you should
either place your Label class declaration to a .h file or write #include "main.moc" after main function declaration.

try to get the return value from your connect call an check it for true or false.
Add Q_OBJECT Macro to the beginning of your derived class.
Add some debug output to your slot like
qDebug()<<"This is my slot.";
Maybe this would help to get a little further.
Best regards

Related

How to know when down-arrow of Combo box is clicked?

I have a ComboBox and set it to be edited.
QComboBox *myCombo = new QComboBox(this);
myCombo->setEditable(true);
myCombo->setStyleSheet("QComboBox::down-arrow{image: url(:/bulb.png);}");
myCombo->setCursor( QCursor( Qt::PointingHandCursor ) );
So now when i click onto the editing field, nothing happen. But what I need is, when I click onto the bulb (which is the down-arrow), something (like a table or a dialog....) should be appeared. How can I recognize this click event in this case? I looked at the list of signals for combo box but could not find any signal for that.
By overwriting the mousePressEvent() method you must use hitTestComplexControl() method to know that QStyle::SubControl has been pressed by issuing a signal if it is QStyle::SC_ComboBoxArrow.
#include <QtWidgets>
class ComboBox: public QComboBox
{
Q_OBJECT
public:
using QComboBox::QComboBox;
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent *event) override{
QComboBox::mousePressEvent(event);
QStyleOptionComboBox opt;
initStyleOption(&opt);
QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, event->pos(), this);
if(sc == QStyle::SC_ComboBoxArrow)
emit clicked();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ComboBox w;
w.setEditable(true);
w.setStyleSheet("QComboBox::down-arrow{image: url(:/bulb.png);}");
QObject::connect(&w, &ComboBox::clicked, [](){
qDebug()<<"clicked";
});
w.show();
return a.exec();
}
#include "main.moc"
Although showPopup() is a possible option this can be called directly without the down-arrow being pressed, for example by calling it directly: myCombo->showPopup() so it is not the correct option.
A possible solution is to subclass QComboBox and reimplement showPopup() virtual method:
.h:
#ifndef COMBOBOXDROPDOWN_H
#define COMBOBOXDROPDOWN_H
#include <QComboBox>
#include <QDebug>
class ComboBoxDropDown : public QComboBox
{
public:
ComboBoxDropDown(QWidget *parent = nullptr);
void showPopup() override;
};
#endif // COMBOBOXDROPDOWN_H
.cpp:
#include "comboboxdropdown.h"
ComboBoxDropDown::ComboBoxDropDown(QWidget *parent)
: QComboBox (parent)
{
}
void ComboBoxDropDown::showPopup()
{
//QComboBox::showPopup();
qDebug() << "Do something";
}

A template issue when creating a slot in Qt 4

I'm trying to create a class for signal/slot connection (old syntax, Qt 4.8) and I am doing something wrong as I keep receiving a template error: invalid declaration of member template in local class... That has obviously something to do with the Q_OBJECT macro... What should I do? Here is a modeled program:
#include <QtGui>
#include <QtCore>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget mw;
mw.setWindowTitle("Main Window");
mw.resize(400, 400);
mw.show();
QLabel label ("Enter something:", &mw);
label.setAlignment(Qt::AlignHCenter);
label.show();
QLineEdit line (&mw);
line.show();
QString a = line.text();
QTextEdit text (&mw);
text.show();
class MyObject : public QObject
{
Q_OBJECT /* the problem is somewhere here... */
public:
QTextEdit text;
QString a;
public slots:
void onClicked() {
text.setText(a);
}
};
QPushButton btn ("Convert", &mw);
QObject::connect(
&btn,
SIGNAL(clicked()),
this,
SLOT(onClicked()));
btn.show();
QVBoxLayout layout_mw;
layout_mw.addWidget(&label);
layout_mw.addWidget(&line);
layout_mw.addWidget(&btn);
layout_mw.addWidget(&text);
mw.setLayout(&layout_mw);
return app.exec();
}
Qt's MOC can process neither nested classes nor local classes. You will have to move the class definition outside main. The documentation only mentions nested classes, but the limitation does apply to local classes too.

Unable to focus and give input to widgets in Qt5

Issue Resolved: Q_OBJECT macro was necessary and proper signal slot declarations are also important for any other handles.
I am unable to focus on any input type widgets like QTextEdit,QListWidget etc.
Note: There are no compile time or runtime errors.
Update: QSplitter is working properly! I have a QListWidget, whose items I click but they are highlighted only when I make the next move with the splitter.
I have a MainWindow class derived from QMainWindow as declared in main_window.h:
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
//some other members like menu and statusbar here
}
I have another class called Stack derived from QWidget defined in stack.h:
class Stack: public QWidget{
public:
Stack(QWidget *parent=0);
//some other members
}
Constructor of Stack as in stack.cpp :
Stack::Stack(QWidget *parent):QWidget(parent){
main = new QHBoxLayout;
handle = new QSplitter;
setupList();
setupScreens();
//above functions add the widgets to the handle splitter
main->addWidget(handle);
setLayout(main);
}
If i open up this widget in a separate window from the MainWindow using test->show(), the things work as expected/as i want.
But doing this in the MainWindow constructor, renders it unclickable.
MainWindow::MainWindow(QWidget *parent):QMainWindow(parent){
Stack *test = new Stack(this);
//test->show();
setCentralWidget(test);
}
This is strange. Why am i not able to focus any widget that can take input e.g. QTextEdit,QListWidget or click any QPushButton widget?
Please compile following code, it was working..you are getting focus and edit on QTextEdit...
stack.h
#include <QWidget>
class Stack: public QWidget
{
Q_OBJECT
public:
Stack(QWidget *parent = 0);
~Stack(void);
};
stack.cpp
#include "Stack.h"
#include<QTextEdit>
#include<QHBoxLayout>
Stack::Stack(QWidget *parent):QWidget(parent){
QHBoxLayout* main = new QHBoxLayout;
QTextEdit *test = new QTextEdit;
main->addWidget(test);
//other things added to main layout
setLayout(main);
}
Stack::~Stack(void)
{
}
mainwindow1.h
#ifndef MAINWINDOW1_H
#define MAINWINDOW1_H
#include <QtGui/QMainWindow>
//#include "ui_mainwindow1.h"
class Mainwindow1 : public QMainWindow
{
Q_OBJECT
public:
Mainwindow1(QWidget *parent = 0, Qt::WFlags flags = 0);
~Mainwindow1();
private:
//Ui::Mainwindow1Class ui;
};
#endif // MAINWINDOW1_H
mainwindow1.cpp
#include "mainwindow1.h"
#include "Stack.h"
#include <QTextEdit>
Mainwindow1::Mainwindow1(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
Stack *test = new Stack;
setCentralWidget(test);
}
Mainwindow1::~Mainwindow1()
{
}
main.cpp
#include "mainwindow1.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Mainwindow1 w;
w.show();
return a.exec();
}
If some1 would find this looking for answer on how to set focus on input widget from UI in QT5 you can just use:
ui->plainTextEdit->setFocus();

Unable to connect signal to a function inside main()

I am aware that to use the signals and slots mechanism of Qt inside a class, the class must include the Q_OBJECT macro, but I am attempting to use signals and slots in main(), without using any class.
Here is my code so far:
#include <QApplication>
#include <QWidget>
#include <QTextEdit>
#include <QtGui>
void saveText();
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton saveButton("Save!");
QPushButton exitButton("Exit!");
QObject::connect(&exitButton,SIGNAL(clicked()),qApp,SLOT(quit()));
QObject::connect(&saveButton,SIGNAL(clicked()),qApp,SLOT(saveText()));
QVBoxLayout vlyt;
vlyt.addWidget(&textEdit);
vlyt.addWidget(&exitButton);
vlyt.addWidget(&saveButton);
QWidget mainWindow;
mainWindow.setLayout(&vlyt);
mainWindow.show();
return app.exec();
}
void saveText()
{
exit(0);
}
Here is the GUI window generated:
From the above code, the exit button is connected to quit(), which is a Qt function, when clicked it works. The save button assigned to the function saveText(), is configured to exit, but does not do so.
Please tell me where I have gone wrong in understanding signals and slots in Qt.
Qt4...
All classes that inherit from QObject or one of its subclasses (e.g.,
QWidget) can contain signals and slots.1
So, you can not use slots where placed outside of QObject children.
You can connect signals to the slots which are in classes where derived from QObject. Put your slot in a class which is in a separated .h/.cpp file:
class MyClass : public QObject
{
Q_OBJECT
...
public slots:
void saveText();
};
According to Qt5: New Signal Slot Syntax in Qt 5. You can connect to those type of global functions. (Thanks to #thuga's comments)
I'll just put example here.
main.cpp:
#include <QCoreApplication>
#include <iostream>
#include <QObject>
#include "siggen.h"
void handler(int val){
std::cout << "got signal: " << val << std::endl;
}
int main(int argc, char *argv[])
{
SigGen siggen;
QObject::connect(&siggen, &SigGen::sgAction, handler);
siggen.action();
QCoreApplication a(argc, argv);
std::cout << "main prog start" << std::endl;
return a.exec();
}
siggen.h:
#ifndef SIGGEN_H
#define SIGGEN_H
#include <QObject>
class SigGen : public QObject
{
Q_OBJECT
public:
explicit SigGen(QObject *parent = 0);
void action(void);
signals:
void sgAction(int value);
};
#endif // SIGGEN_H
siggen.cpp:
#include "siggen.h"
SigGen::SigGen(QObject *parent) : QObject(parent)
{}
void SigGen::action()
{
emit sgAction(42);
}
QObject::connect(&saveButton, &QPushButton::clicked, [](){saveText();}); // qt5.9.6
or as mentioned in the masoud's answer
QObject::connect(&saveButton, &QPushButton::clicked, saveText); // qt5.9.6
It is possible to connect a signal to function inside main function.
This has been tested in Qt5.15. Here is the simple example where the QPushButton 'Clicked' signal is used to trigger a function (here I used lamda's, but regular functions can also be used).
int main(int argc, char *argv[])
{
// Created QApplication
QApplication a(argc, argv);
// Created the splashscreen(which is QObject)
QPixmap pixmap(":/images/Sample.png");
QSplashScreen splash(pixmap);
// Created the pushbutton and added to splashscreen
QPushButton b(&splash);
b.setGeometry(50,50, 100, 50);
b.setText("FPS");
// variable to be modified inside a lamda function
int i = 0;
// Connection for button clicked signal executes lamda function
QObject::connect(&b, &QPushButton::clicked,
[i = static_cast<const int&>(i), &splash = static_cast<QSplashScreen&>(splash)]()mutable
{i = i+1; splash.showMessage("clicked: "+ QString::number(i));});
// Adding properties and displaying the splashscreen
splash.setGeometry(0,0, 1920, 1080);
splash.setEnabled(true);
splash.show();
a.processEvents();
return a.exec();
}

How can I put this qt program into one source code file

I want to have this code in one file, but can't figure out how to. I know it might not be good practice to do so but I am trying to learn qt, and would find it easier to understand the information if it were in one file.
This is the main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
This is the mainwindow.cpp
#include "mainwindow.h"
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
this is the mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
By just copying everything in one file.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
It is usually not a good idea to define new classes in same file as your main. Generally you want new classes each in their own file or you would want to put several related classes together in a seperate file. There are a tonne of resources you can google related to best practices for this. I'd suggest you spend some time reading.
But since you asked... below is how you would do it for your example. If you do not define your class above the main, the compiler will complain because it won't know what a "MainWindow" is.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
#include essentially takes the contents of whatever file you choose and copy/pastes it at that location. The compiler then starts at the top of the file and works its way down to the bottom.
Knowing that, you should be able to just copy-paste the contents of the files in the order they are included.
mainwindow.h
mainwindow.cpp
main.cpp
The short answer is don't do this, you should define a class in its own header file and #include it to the main when you want to run it in the main. This allows you to reuse the class as you see fit throughout the program, its one of the tenets of Object Oriented programming, reusable code. For example
class A
{
public:
A();
~A();
void somePublicMethod();
private:
void somePrivateMethod();
};
If you include that class in your main when you compile that class to object code(assuming you know about implementing that class in a .cpp file) then when all the object files are linked to create the program the linker basically makes one big file with all the object code included in file to be fully compiled. I suggest you read up more on compiling and linking, essentially it boils down to three phases, preprocessing, compiling and linking. Learn more about Object Oriented programming and read up why it's a bad idea to just shove them all into one file. Every class should be in its own self contained .h file(unless its a tightly coupled class) so you can include them as you see fit. Hope this helps, have fun with Qt :)