How to connect focus event from QLineEdit? - c++

I have to connect focus event from some QLineEdit element (ui->lineEdit) to the method focus(). How can I do this?

There is no signal emitted when a QLineEdit gets the focus. So the notion of connecting a method to the focus event is not directly appropriate.
If you want to have a focused signal, you will have to derive the QLineEdit class. Here is a sample of how this can be achieved.
In the myLineEdit.h file you have:
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
MyLineEdit(QWidget *parent = 0);
~MyLineEdit();
signals:
void focussed(bool hasFocus);
protected:
virtual void focusInEvent(QFocusEvent *e);
virtual void focusOutEvent(QFocusEvent *e);
};
In the myLineEdit.cpp file you have :
MyLineEdit::MyLineEdit(QWidget *parent)
: QLineEdit(parent)
{}
MyLineEdit::~MyLineEdit()
{}
void MyLineEdit::focusInEvent(QFocusEvent *e)
{
QLineEdit::focusInEvent(e);
emit(focussed(true));
}
void MyLineEdit::focusOutEvent(QFocusEvent *e)
{
QLineEdit::focusOutEvent(e);
emit(focussed(false));
}
You can now connect the MyLineEdit::focussed() signal to your focus() method (slot).

I assume you mean connect as in signals/slots, focus event isn't a signal it's a virtual method you have to override in order to change the behavior:
http://doc.qt.io/qt-5/qlineedit.html#focusInEvent

Related

Qt/C++ - Call of overriden method from derived class

I have the following code:
void AppMPhase::closeEvent(QCloseEvent *closeEvent) {
QMessageBox* dialog = new QMessageBox(this);
dialog->setText("Warning: Initial configuration changed\nDo you want to restore it ?");
dialog->setIcon(QMessageBox::Warning);
dialog->addButton(QMessageBox::Yes);
dialog->addButton(QMessageBox::No);
connect(dialog, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(restoreInitialConfig(QAbstractButton*)));
dialog->exec();
}
void AppMPhase::restoreInitialConfig(QAbstractButton *button) {
if(!button->text().compare(QString("Yes"))) {
// restore Config
}
else {
// don't restore
}
MainWindow::closeEvent(closeEvent);
}
with AppMPhase the derived class of MainWindow
I would like to call the method closeEvent of the base class MainWindow in the "restoreInitialConfig" method, to close the window after we restore the config.
Is it possible ? it's different from the other questions I have seen because the method closeEvent is overriden in the AppMPhase class.
the AppMPhase class:
class AppMPhase : public QtUi::MainWindow
{
Q_OBJECT
public:
AppMPhase(QWidget *const parent = Q_NULLPTR, const Qt::WindowFlags flags = 0);
~AppMPhase();
int readConfigFromExternFile(QString path);
int readCalibrationDate(QString path);
QSize sizeHint() const Q_DECL_OVERRIDE;
QtWrapperTestManager * testManager;
public Q_SLOTS:
void show();
public slots:
void currentTestFinished();
void createTest(unsigned int,QString);
void restoreInitialConfig(QAbstractButton* button);
signals:
void notifyPageTestCurrentTestFinished();
private:
enum AppPage
{
PAGE_START,
PAGE_ABOUT
};
bool isTestMangaerCreated;
std::map<QString, std::map<std::string, std::string> > conversion_Table_Cable_Ref_sensorParamMap;
Pages::GenericAppPage * appPage(const int index) const;
QToolButton * appPageButton(const int index) const;
virtual void closeEvent(QCloseEvent *closeEvent) Q_DECL_OVERRIDE;
The MainWindow class:
class SHARED_EXPORT_LIB_QT_UI MainWindow : public QMainWindow
{
Q_OBJECT
signals:
void aboutToClose();
public slots:
virtual void show();
private slots:
void changeLanguage(const QString &language);
public:
MainWindow(QWidget *const parent = Q_NULLPTR, const Qt::WindowFlags flags = 0);
virtual ~MainWindow();
protected:
void showCopyright(const QString &copyRightHeader);
void showLanguageSelector(const QStringList &languages);
void setupUi(const MainPageList &pageList);
void setupUi(QWidget *centerWidget = Q_NULLPTR);
virtual void closeEvent(QCloseEvent *closeEvent) Q_DECL_OVERRIDE;
const Ui::MainWindow *const _ui;
MainPageItemList _mainPageItemList;
};
Thanks in advance.
Flo
There is a far easier way to achieve what you're wanting to do, without having to use signals and slots, and call base class functions from your slot.
It is possible to do the restoration directly from within your closeEvent handler.
This is made possible by the fact that QMessageBox::exec returns an integer code which matches one of the values in the StandardButton enum, depending on what button was pressed.
That then allows you to call restoreInitialConfig directly from within your closeEvent handler, as you know which button was pressed.
void AppMPhase::closeEvent(QCloseEvent* ev)
{
int res = QMessageBox(
QMessageBox::Icon::Warning,
"Restore configuration?",
"Warning: Initial configuration changed\nDo you want to restore it?",
QMessageBox::Yes | QMessageBox::No,
this).exec();
if (res == QMessageBox::Yes)
restoreInitialConfig();
MainWindow::closeEvent(ev);
}
Note that this also simplifies your restoreInitialConfig function, as there is no need to check button text, you know the answer was yes.
Note also I made use of this QMessageBox constructor which makes it very easy to create simple message boxes.

Using the autogenerated Ui for both sender and receiver with qt

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).

Signal from subclassed QGraphicsView not being recognized in SLOT

I have a subclass of QGraphicsView to recognize mouse events, and it does. But when those mouse events happen, I need to call some other function in a different class, to handle how the mouse event interacts with the scene.
//Subclass
class Drawspace : public QGraphicsView {
public:
Drawspace(QGraphicsScene * scene, QWidget * parent) : QGraphicsView(scene, parent) {}
Drawspace(QWidget* parent) : QGraphicsView(parent) {}
void mousePressEvent(QMouseEvent * event) {
QMessageBox::information(this, tr("Dialog"), "You clicked the board (from QGraphicsView)");
QWidget::mousePressEvent(event);
}
};
//mainwindow code (my subclass is called "board")
mainwindow::mainwindow(QWidget *parent)
: QMainWindow(parent) {
//Initialize other stuff
ui.setupUi(this);
//Problem here
connect(ui.board, SIGNAL(Drawspace::mousePressEvent(QMouseEvent*)), this, SLOT(on_click(QMouseEvent*)));
}
void mainwindow::on_click(QMouseEvent * event) {
QMessageBox::information(this, tr("Dialog"), "You clicked the screen");
//Do stuff here
}
It builds fine, and when I click the drawspace, I get a dialog that says "You clicked the board (from QGraphicsView)", but I don't get the second from "You clicked the screen".
And yes, the header file for mainwindow has the Q_OBJECT macro
EDIT: Can be fixed by manually defining your own signal, calling that, and changing the connection to use Qt5 syntax. See my answer for code
OP here, the problem can be fixed by defining a signal, calling emit on it and changing the connection to use Qt5 syntax.
//New drawspace: Added signal definition and called emit on it from mousePressEvent
class Drawspace : public QGraphicsView, public QObject {
Q_OBJECT
public:
Drawspace(QGraphicsScene * scene, QWidget * parent) : QGraphicsView(scene, parent) {}
Drawspace(QWidget* parent) : QGraphicsView(parent) {}
void setObjectName(QString str) { QGraphicsView::setObjectName(str); }
void mousePressEvent(QMouseEvent * event) {
QMessageBox::information(this, tr("Dialog"), "Detected click in Drawspace");
emit clicked(event);
}
Q_SIGNALS:
void clicked(QMouseEvent * event);
};
//Used Qt5 syntax, this will automatically pass arguments
connect(ui.board, &Drawspace::clicked, this, &mainwindow::on_click);
mousePressEvent() is not a signal. It is a member function. You cannot connect() a function to a function like you can connect a signal to a signal.
Qt signals are declared as functions, but they get some special treatment. You'd need to use Qt's keywords to signify a signal so it can get the treatment that will make it work.
Make the mousePressEvent virtual, or you are creating a NEW method:
virtual void mousePressEvent(QMouseEvent * event)
and say it is overriden (depending on your compiler:)
virtual void mousePressEvent(QMouseEvent * event) override (Q_DECL_OVERRIDE)

Connect enterPressed() in QMainWindow to Button clicked()

How can I connect a key enterPressed() event in my main GUI window to a specific button (also in main GUI)?
Usecase:
User starts the application, enter some data and press the Enter button and will be bypassed to a "Start" button is clicked.
My idea:
connect(this, SIGNAL(returnPressed()), ui.btn_Start, SLOT(clicked()));
class ClassA : QMainWindow
{
Q_OBJECT
// ...
private:
Ui::ClassAClass ui;
// ...
};
You can connect signals to other signals:
connect(this, &MainWindow::returnPressed, ui.btn_Start, &QPushButton::released);
And that is it. The signal is forwarded to QPushButton's instance signal emitting it so whatever is connected to it will be invoked. Additionally (you talk about events) in QMainWindow::keyPressEvent you re-implement:
class MainWindow : public QMainWindow
{
//...
signals:
void returnPressed() const;
protected:
void keyPressEvent(QKeyEvent *event);
};
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Return)
emit returnPressed();
QMainWindow::keyReleaseEvent(event);
}

QT extend MainWindow to other class or diffrent way

I have class printrectangle
class PrintRectangle : public QWidget
{
Q_OBJECT
public:
explicit PrintRectangle(QWidget *parent = 0);
private:
void resetClickedIndex();
void updateIndexFromPoint( const QPoint& point);
public:
int mXIndex;
int mYIndex;
QVector<QPoint> points;
bool clicked[5][5] = {};
teacher tech;
perceptron p[5][5];
double techconst = 0.1;
signals:
public slots:
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *eventPress);
};
and MainWindow
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_learn_clicked();
void on_classify_clicked();
private:
Ui::MainWindow *ui;
};
When I click button I call to on_learn_clicked() function. I would like to transfer clicked[5][5] array into on_learn_clicked becasue I send this array to other object when user click button. How to do this?
It is not clear what is exactly the relation between MainWindow and the PrintRectangle widget. I suppose the button signal and PrintRectangle slot are connected somewhere in the MainWindow implementation.
One way to solve the problem would be to use to use the QSignalMapper as #Noidea stated.
Another way would be to use a lambda as a slot when connecting. This way you could capture the sender/receiver or other objects in scope and use their members.
You can find some information about the connect syntax in New Signal Slot Syntax
But basically you could write something like:
connect(button, &QPushButton::clicked, this, [this, printRectangle]()
{
// do smth with clicked[5][5] from printRectangle or just
// retrieve it and call another method like:
// this->processClicked(printRectangle->clicked);
// or pass it to another object
}
This way you could modify your on_classify_clicked slot to a regular method with bool[5][5] argument to do the processing.