QMainWindow - wait until 'show' function is done - qt

Is there a signal that tells when 'show' function finishes?
I have a problem in my code: If I write:
QMainWinObj.show();
QMainWinObj.someGuiFunc();
the code doesn't work. But, if I write:
QMainWinObj.show();
sleep(3000);
QMainWinObj.someGuiFunc();
It does.
So I think the problem is that 'show' dosn't finish its jub before I call 'someGuiFunc'. That's why I want to have some kind of a sign that 'show' is finished..

This may be a bit dated but since nobody else answered it except the one:
Since there is no "Show" signal I suggest overriding the show event like this:
In your mainwindow.cpp file:
void MainWindow::show()
{
QMainWindow::show();
QApplication::processEvents();
emit windowShown();
}
In your mainwindow.h file, somewhere in MainWindow's declaration:
...
class MainWindow: public QMainWindow
{
...
signals:
void windowShown();
...
}
...
Then, when you go to the designer, right click on the main window (very top of the object tree), and select "Change signals/slots". In the "Signals" frame, click the "+" button, and you will need to add "windowShown()" and then press enter, and then the OK button (note that the elipses "..." denote other code that is already in your header).
That's it -- you can now use the signals/slots editor to link slots up to the 'windowShown' signal whenever you want. Now if you want something more like Microsoft's "Loaded" event which I think is used in .NET you will need to create some instance variable and flag it so that every time the window is shown, it isnt emitted, for example:
void MainWindow::show()
{
QMainWindow::show();
QApplication::processEvents();
emit windowShown();
if (firstTimeShown == true)
{
emit windowLoaded();
firstTimeShown = false;
}
}
Also, don't forget to initialize the variable to 'true' in your constructor:
MainWindow::MainWindow(QObject* parent)
...
{
firstTimeShown = true; // put this somewhere before ui->setupUi()
}
If you decide to put it in the initializer list however, make sure it is in proper order. The compiler will complain if the variables are not instantiated in a top-to-bottom fashion as declared in the class' header.
Now, make sure when you define firstTimeShown in your header, that you make it private. And lets not forget the added signals:
class MainWindow : public QMainWindow
{
...
signals:
void windowLoaded();
void windowShown();
private:
bool firstTimeShown;
...
That's about it. With the flexibility of signals and slots, its pretty easy to mimic any event that you might find from windows forms or from MFC. It just takes a little effort on the programmer's part. Once you get the hang of it however it it'll be like second nature.
note: there probably are optimizations or better and more precise ways of making the "Loaded" and "Shown" signals perform but I have left things like this out for simplicity's sake. And to come back to the question at hand, calling QApplication::processEvents() is most likely what you want to do instead of waiting a fixed amount of time because who knows how long it will take if the user is running 100 other things on top of it, etc, etc. Hope that helped, the extra explanation was included hoping that it might give you a better way to do the things that you want to do instead of waiting for something to be done, 'knowing' it is done is a much better alternative.

There is no such signal, but having QMainWindow subclassed you can override showEvent event.
void MainWindow::showEvent(QShowEvent *){
//your code
}
More info here: http://qt-project.org/doc/qt-4.8/qwidget.html#showEvent
Be aware it's called every time your window is about to be displayed.

Problem can decide without subclassing, just installing event filter like this:
class CWidgetIsPainting_EF : public QObject
{
bool m_bIsPainted = false;
public:
CWidgetIsPainting_EF( QObject * parent = 0 ) : QObject (parent) { }
inline bool IsPainted() const { return m_bIsPainted; }
inline void setIsPainted( bool bIsPainted ) { m_bIsPainted = bIsPainted; }
protected:
bool eventFilter( QObject * obj, QEvent *event )
{
if (event->type() == QEvent::Paint)
{
m_bIsPainted = true;
return true;
};
return QObject::eventFilter(obj, event);
}
};
...
...
CWidgetIsPainting_EF * pPaintingEF = new CWidgetIsPainting_EF( m_pWidget );
m_pWidget->installEventFilter( pPaintingEF );
...
...
while ( !pPaintingEF->IsPainted() )
QApplication::processEvents();

Override bool event(QEvent *event) and catch the Paint event. Works for me at least on Windows.
// MainWindow.h
class MainWindow : public QMainWindow
{
...
bool event(QEvent *event) override;
void functionAfterShown();
...
bool functionAfterShownCalled = false;
...
}
// MainWindow.cpp
bool MainWindow::event(QEvent *event)
{
const bool ret_val = QMainWindow::event(event);
if(!functionAfterShownCalled && event->type() == QEvent::Paint)
{
functionAfterShown();
functionAfterShownCalled = true;
}
return ret_val;
}

Related

keyPressEvent denies writing to QLineEdit

I faced an error and I didn't found any solutions for this problem. So I have made a subclass from QLineEdit, and overrided a keyPressEvent method. Now if I try to write something it doesn't allow it, but it triggers the event. Any advices?
.h
class PlayerQLineEdit : public QLineEdit
{
public:
PlayerQLineEdit();
void keyPressEvent(QKeyEvent *);
};
.cpp
PlayerQLineEdit::PlayerQLineEdit()
{
setDisabled(false);
}
void PlayerQLineEdit::keyPressEvent(QKeyEvent *)
{
}
You have to call the base class event handler. Otherwise the line edit can't get any key presses!
void PlayerQLineEdit::keyPressEvent(QKeyEvent *event)
{
// ... do stuff
// optionally return before calling base class handler to suppress key strokes.
QLineEdit::keyPressEvent(event);
// ... do stuff
}

How can I avoid infinite loop when modifying textboxes (QLineEdit) that change related item info?

I have several fields in a widget, that each can affect the behavior of an item, and changing some of them will change others.
I read somewhere that the editingFinished() signal of a line edit is triggered only by user actions - and not by code changes... Is that true ?
connect(m_lineEdit1, SIGNAL(editingFinished()), this, SLOT(m_lineEdit1Changed()));
connect(m_lineEdit2, SIGNAL(editingFinished()), this, SLOT(m_lineEdit2Changed()));
connect(this, SIGNAL(someSignal()), this, SLOT(updateData()));
void m_lineEdit1Changed()
{
changedata1();
emit someSignal();
}
void m_lineEdit2Changed()
{
changedata2();
emit someSignal();
}
void updateData()
{
m_lineEdit1.setText(fromdata);
m_lineEdit2.setText(fromdata);
}
If I change m_lineEdit1, and update the entire widget (which changes, through code, m_lineEdit2), I hit a breakpoint in m_lineEdit2Changed()
This leads to an infinite loop of updates...
What can I do to get around it ?
Blocking signals is a bit of a sledgehammer of an approach. You can use a sentinel class to explicitly prevent recursion:
#define SENTINEL_STRINGIFY(x) #x
#define SENTINEL_TOSTRING(x) SENTINEL_STRINGIFY(x)
#define SENTINEL_AT __FILE__ ":" SENTINEL_TOSTRING(__LINE__)
class Sentinel {
Q_DISABLE_COPY(Sentinel);
static QMutex m_mutex;
static QSet<QString> m_sentinels;
QString const m_sentinel;
bool const m_ok;
static bool checkAndSet(const QString & sentinel) {
QMutexLocker lock(&m_mutex);
if (m_sentinels.contains(sentinel)) return false;
m_sentinels.insert(sentinel);
return true;
}
public:
explicit Sentinel(const char * sentinel) :
m_sentinel(sentinel), m_ok(checkAndSet(m_sentinel)) {}
~Sentinel() {
if (!m_ok) return;
QMutexLocker lock(&m_mutex);
m_sentinels.remove(m_sentinel);
}
bool operator()() const { return m_ok; }
};
QMutex Sentinel::m_mutex;
QSet<QString> Sentinel::m_sentinels;
...
void Foo::m_lineEdit1Changed()
{
Sentinel s(SENTINEL_AT);
if (!s) return; // exit if this method is on the call stack
...
changedata1();
emit someSignal();
}
This is thread-safe and can be used from any thread.
A technique to avoid this problem is to use the QObject::blockSignals() function.
In your example you would do:
void updateData()
{
m_lineEdit1.blockSignals(true);
m_lineEdit1.setText(fromdata);
m_lineEdit1.setText(fromdata);
m_lineEdit1.blockSignals(false);
}
The blockSignals() call prevents the object sending any signals while you are changing the data in the line edit.

How do you suppress a Qt main menu keyboard shortcut?

For example, consider a main menu item that has the Delete key as a shortcut (with Qt::WindowShortcut as context). I want another QWidget to handle the Delete key when focused. This is not possible because the Delete key is processed by the main menu. I've tried grabbing the keyboard on QWidget focus but that doesn't do anything. Is this event possible?
I was able to get the behavior I wanted by installing an event filter on qApp when the QWidget is focused (remove it when losing focus), and returning true for all QEvent::Shortcut types.
void MyWidget::focusInEvent( QFocusEvent *event )
{
qApp->installEventFilter(this);
}
void MyWidget::focusOutEvent( QFocusEvent *event )
{
qApp->removeEventFilter(this);
}
bool MyWidget::eventFilter( QObject *target, QEvent *event )
{
if (event->type() == QEvent::Shortcut)
{
// If I care about this shortcut, then return true to intercept
// Else, return false to let the application process it
}
return false;
}
If there's a better way, I'd love to hear it!

What is the signal for when a widget loses focus?

In a dialog, when the tab key is pressed, the focus changes to another widget. In Qt, is there any signal for when a widget loses its focus? Can I use it to check if the input is valid or not? If not, can I set the focus back and ask the user to re-input?
There's no signal but if you want to know when your widget has lost focus, override and reimplement void QWidget::focusOutEvent(QFocusEvent* event) in your widget. It will be called whenever your widget has lost focus. To give focus to a widget, use QWidget::setFocus(Qt::FocusReason).
To validate input in a QLineEdit or QComboBox you can subclass QValidator and implement your own validator, or use one of the existing subclasses, QIntValidator, QDoubleValidator, or QRegExpValidator. Set the validator with QLineEdit::setValidator(const QValidator*) and QComboBox::setValidator(const QValidator*) respectively.
If you want to validate the contents of a modal dialog box, one way would be to override QDialog::exec() with an implementation like this:
int MyDialog::exec() {
while (true) {
if (QDialog::exec() == QDialog::Rejected) {
return QDialog::Rejected;
}
if (validate()) {
return QDialog::Accepted;
}
}
}
bool MyDialog::validate() {
if (lineEdit->text().isEmpty()) {
QMessageBox::critical(this, "Invalid value", "The specified value is not valid");
lineEdit->setFocus();
lineEdit->selectAll();
return false;
}
return true;
}
It will not allow the user to close the dialog with the OK button or any other button with the Accepted role unless the contents of the dialog is successfully validated. In this example I assume the dialog has a QLineEdit named lineEdit and the validate function will make sure that its content is not empty. If it is, it will set the focus to the QLineEdit and show the dialog again.
It is also possible (and easier) to create the signal yourself
In the .cpp (do not forget to include the moc)
class FocusWatcher : public QObject
{
Q_OBJECT
public:
explicit FocusWatcher(QObject* parent = nullptr) : QObject(parent)
{
if (parent)
parent->installEventFilter(this);
}
virtual bool eventFilter(QObject *obj, QEvent *event) override
{
Q_UNUSED(obj)
if (event->type() == QEvent::FocusIn)
emit focusChanged(true);
else if (event->type() == QEvent::FocusOut)
emit focusChanged(false);
return false;
}
Q_SIGNALS:
void focusChanged(bool in);
};
And to connect it:
connect(new FocusWatcher(myWidget), &FocusWatcher::focusChanged, this, &View::doSomething);

QT EventTransition implementation

I am trying to build an QT State Maschine. I have some States, and for those States i need Transition that alter the Graphics on my gui.
The Problem i having and the only reason i am asking, i am Stuck and Point 1.
The compiler cant identifie the QTEventTransition. I have QT 4.6 wroking with QT Creator on Windows.
The compiler does not find Header #include < QtEventTransition >
This is what i did i never did this bevor but i think it should be correct, I have A Header File where i have my Transitions Declareted like this:
class validateBoatTransition : public QtEventTransition
{
public:
validateBoatTransition(Widget *widget,ServerSkeleton* server);
protected:
bool eventTest(QEvent *e);
void onTransition(QEvent *);
private:
Chart* ourChart;
Message current;
BarelySocket* myBarelySocket;
};
Than i have my Cpp File where i have this:
validateBoatTransition::validateBoatTransition(Widget *widget,ServerSkeleton* server)
{
}
void validateBoatTransition::onTransition(QEvent *e)
{
/*
My Logik should go here
*/
}
What i want is that if the Transition is activated by an Button (clicked) it should fire this transition!
I searched the net, but cant find an solution. Can i do that? I should i think.
Yours Thomas
Maybe you should take a look to signals/slot mechanism. I think this is what you need to achieve what you want.
Make your onTransition function a slot instead of an event handler and connect it to the signal clicked of the button.
class validateBoatTransition : public QtEventTransition
{
...
public slots:
void onTransition();
...
}
Somewhere in your code, connect the button to the slot:
QObject::connect(myButton, signal(clicked()), myValidateBoatTransition, slot(onTransition());
Each time the button will be clicked the execution will go through the onTransition function.
I think you're trying to use wrong classes/mechanisms to achieve your goals. If I understand you correctly, you have some GUI and after clicking some button you want to validate some stuff and if this validation is successful the state machine should change it's state. I'd write it this way:
Create some class to handle validation:
class BoatValidator : public QObject
{
Q_OBJECT
// boring stuff like constructor, etc.
public slots:
void validate()
{
if ( /*your validation logic goes here*/ ) {
emit boatTransition();
}
}
signals:
void boatTransition(); // emitted if validation is succesful
};
Then you connect your QPushButton::clicked() to BoatValidator::validate() and use BoatValidator::boatTransition() signal to drive the state machine:
QStateMachine machine;
QState *state1 = new QState(&machine);
QState *state2 = new QState(&machine);
// more state machine setup
// connect validator and button
QPushButton button;
BoatValidator validator;
connect(&button, SIGNAL(clicked()), &validator, SLOT(validate()));
// use validator to change states
state1->addTransition(&validator, SIGNAL(boatTransition()), state2);
Generally I'd use signal to drive state machine, unless some transitions are obviously event driven (for example some QEvent::Enter/QEvent::Leave on GUI widgets, etc.).
What i wanted to do is build a Qt State Machine. The Problem was that i could not trigger my own Transitions (let alone with my own Events). The answers given are good but would lead to a messy code. Why should i use a QT State Machine if i could not use the QT Transitions?
The First Problem above is solved, if you create a new Project. QT Creater is very annoying.
But here now my solution , may it help others.
First my State:
class ServerState : public QState
{
Q_OBJECT
public:
ServerState(QPushButton * pushButton);
~ServerState();
public slots:
void buttonWasClicked();
protected:
void onEntry(QEvent *e);
void onExit(QEvent *e);
private:
QPushButton * pushButton;
};
Normal, but you see i added an Slot. This slot enables me to connect a bottom signal or a Widget Mouse Press Signal to it !
Like this:
QStateMachine *machine = new QStateMachine(this);
ServerState *s1 = new ServerState(connectButton);
connect(connectButton, SIGNAL(clicked()), s1, SLOT(buttonWasClicked()));
machine->addState(s1);
s1->addTransition(connectTransition);
all i needed to to is now fire a declared Event like this one :
#define RegisterToServerEventIndex User+5
class ConnectToServerEvent : public QEvent
{
public:
ConnectToServerEvent() : QEvent(QEvent::Type(QEvent::ConnectToServerEventIndex))
{}
};
when the slot was called:
void ServerState::buttonWasClicked()
{
this->machine()->postEvent(new ConnectToServerEvent());
qDebug("ServerState::buttonWasClicked");
}
The QT State Machine would now call all the Transitions , link with this state:
ConnectToServerTransition::ConnectToServerTransition(QPushButton * pushButtonB,ServerSkeleton* serverSkeleton)
{
this->pushButtonB = pushButtonB;
this->pushButtonB->hide();
this->serverSkeleton = serverSkeleton;
qDebug("ConnectToServerTransition::ConnectToServerTransition");
}
bool ConnectToServerTransition::eventTest(QEvent *e)
{
return (e->type() == QEvent::ConnectToServerEventIndex);
}
void ConnectToServerTransition::onTransition(QEvent *e)
{
if (true == this->serverSkeleton->initalisieren())
{
this->pushButtonB->show();
}else{
qDebug("Conection to Server faild");
}
emit kill();
return;
}
Whats so great that i dare to post?
Well first you can link a Qt SM to a widget where a mouse press event , or somthing else, is called and process the raw data to a an level you need later in your program. All you then need to do is, to emit the singal:
void Widget::mousePressEvent(QMouseEvent *event){
Coordinates current;
current.line = 0;
current.row = A;
current.row = (Row) (event->x() / 30); // 30 = breite von einen Feld
current.line = event->y() / 30; // 30 = länge von einen Feld
emit this->clicked(current);
return;
}
Then this enhenced information (current) is passed to the slot at my state, where i chose to call the correct transition that does the work. You could link more transitions to it, if you need it.
But most importend you dont need to reprogramm the Transition, a think i realy disliked.
Thank you for your help , i could not done it alone.

Resources