Is there in Qt something like Form.onChange in Delphi?
I found some changeEvent method but when I wrote connect
connect(this, SIGNAL(this->changeEvent),this, SLOT(checkIfSomethingChanged()));
and tried to check it like that
void importdb_module::checkIfSomethingChanged(){
QMessageBox::information(0, "", "Test");
}
I realized that it not works.
I want to check some condition everytime when something changed in my form, how to do that?
The changeEvent slot is a virtual, protected function found in QWidget. Therefore, if you inherit from QWidget or any QWidget derived class, you'll be able to override that function. For example: -
class MyForm : public QWidget
{
protected slots:
virtual void changeEvent(QEvent * event);
}
void MyForm::changeEvent(QEvent* event)
{
// Do something with the event
}
If you wanted to know outside of the event that the form has been changed, you can add a signal to the form and emit it from the changeEvent to pass the event on: -
class MyForm : public QWidget
{
signals:
void FormChanged(QEvent* event);
protected slots:
virtual void changeEvent(QEvent * event);
}
void MyForm::changeEvent(QEvent* event)
{
emit FormChanged(event);
}
Now connect another class to the new signal, using Qt 5 connect syntax: -
connect(myFormObject, &MyForm::FormChanged, someclassObject, &SomeClass::HandleFormChanged);
This cannot work, because you mixed up two concepts: events and signal/slots. To make it work, you need to override your class' changeEvent() virtual function. Something like this:
void MyWidget::changeEvent(QEvent *event)
{
QMessageBox::information(0, "", "Test");
}
Related
There is no signal as clicked for QlineEdit.
connect(w,SIGNAL(clicked()),this,SLOT());
There is no such signal in Qt widgets.
You need to derive QLineEdit class and implement void QLineEdit::mouseReleaseEvent(QMouseEvent *e), like this:
class MyLineEdit public QLineEdit {
...
virtual void mouseReleaseEvent(QMouseEvent *e) { emit clicked(); }
signals:
void clicked();
}
Later, you can promote QLineEdit in graphical editor to MyLineEdit class.
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)
I'm using QGraphicsScene and I would like to have some items which emit signals when they are moved around.
Unfortunately, QGraphicsPixmapItem doesn't have any signals, so I subclassed it:
class InteractiveGraphicsPixmapItem : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
InteractiveGraphicsPixmapItem();
InteractiveGraphicsPixmapItem(QPixmap pm) : QGraphicsPixmapItem(pm)
{
setFlag(QGraphicsItem::ItemIsMovable, true);
setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
}
private:
void mouseMoveEvent(QGraphicsSceneMouseEvent *);
signals:
void moved_by_mouse(QPointF newpos);
};
InteractiveGraphicsPixmapItem::InteractiveGraphicsPixmapItem()
{
}
void InteractiveGraphicsPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *)
{
emit moved_by_mouse(this->pos());
}
However, it is not movable.
If I change it back into a QGraphicsPixmapItem in the main program, and call item->setFlags(QGraphicsItem::ItemIsMovable); it becomes movable. For my custom class, it doesn't.
item = new InteractiveGraphicsPixmapItem(QPixmap(":/img/icon.png"));
scene->addItem(item);
item->setFlags(QGraphicsItem::ItemIsMovable);
A similar question was asked about selectability, and it was suggested that the setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton); must be added to the constructor. It didn't help in my case.
If you override the mouseMoveEvent, and don't call the base class's function, it won't move and you'll have to handle it yourself.
However, simply calling the base class function is all you need here
void InteractiveGraphicsPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent* evt)
{
QGraphicsPixmapItem::mouseMoveEvent(evt);
emit moved_by_mouse(this->pos());
}
Also note that if you override one of the mouse events (press / release / move) you should also handle the others too.
I have two widgets defined as follows
class mainWindow : public QWidget
{
Q_OBJECT
public:
mainWindow();
void readConfig();
private:
SWindow *config;
QVector <QString> filePath;
QVector <QLabel*> alias,procStatus;
QVector <int> delay;
QGridLayout *mainLayout;
QVector<QPushButton*> stopButton,restartButton;
QVector<QProcess*> proc;
QSignalMapper *stateSignalMapper, *stopSignalMapper, *restartSignalMapper;
public slots:
void openSettings();
void startRunning();
void statusChange(int);
void stopProc(int);
void restartProc(int);
void renew();
};
class SWindow : public QWidget
{
Q_OBJECT
public:
SWindow(QWidget *parent=0);
void readConfig();
void addLine(int);
private:
QVector<QPushButton*> selectButton;
QVector<QLabel*> filePath;
QVector<QLineEdit*> alias;
QSignalMapper *selectSignalMapper;
QVector<QSpinBox*> delay;
QGridLayout *mainLayout;
public slots:
void selectFile(int);
void saveFile();
void addLineSlot();
};
when i create and display SWindow object from mainWindow like this
void mainWindow::openSettings()
{
config = new SWindow();
config->show();
}
everything is ok, but now i need to access the mainWindow from SWindow, and
void mainWindow::openSettings()
{
config = new SWindow(this);
config->show();
}
doesn't display SWindow. How can i display SWindow?
How do i call a function on widget close?
By default a QWidget isn't a window. If it is not a window and you specify a parent, it will be displayed inside the parent (so in your case it is probably hidden by other widgets inside your mainWindow).
Look at windowFlags() too. Or you could make your SWindow inherit from QDialog, depending on what you use it for.
As for calling a function on widget close : you could reimplement closeEvent().
When you do config = new SWindow(this); you're setting the parent of config to be the instance of mainWindow.
This means config is no longer a top-level widget, therefore it won't display outside the mainWindow instance (specifically, it would need to be the central widget or inside the mainWindow instance's layout to be displayed).
EDIT: Sorry - I missed your last question; How do i call a function on widget close
You will want to override the QWidget::closeEvent(QCloseEvent *event) method. This gets called when you close a top-level widget. The most practical thing to do is emit() a signal so that another class can handle it having been closed.
As noted by Leiaz, you can use the windowsFlags flag when you create the widget. It would look like this:
void mainWindow::openSettings()
{
config = new SWindow(this, Qt::window);
config->show();
}
To reimplement the closeEvent:
header:
protected:
virtual void closeEvent ( QCloseEvent * event )
cpp:
void sWindow::closeEvent(QCloseEvent *event)
{
this->parentWidget()->SomeFunction();
qWidget::closeEvent(event);
}
However, its probably better to use signal/slots for your case here. Since you said you want to call the parent's renew method on some button click in sWindow, what you want is to EMIT a signal everytime the button is clicked, and connect this signal in the parent with the parent's refresh slot.
void sWindow::sWindow()
{
...
connect(ui.button, SIGNAL(clicked()), this, SLOT(btnClicked()));
}
void sWindow::btnClicked()
{
// whatever else the button is supposed to do
emit buttonClicked();
}
and in your parent class
void mainWindow::openSettings()
{
config = new SWindow(this, Qt::window);
connect(config, SIGNAL(buttonClicked()), this, SLOT(refresh()));
config->show();
}
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