Qt - two signals and modal dialog window - qt

I have a QDialog based class.
I have one QEditLine *editLine and QButton *button.
I use clicked() signal of button. And editingFinished() signal of editLine.
When I change the text in the editLine and press the button firstly editingFinished() signal is emitted. In the slot method I call QMessageBox::question().
After that I can't receive clicked() signal of my button.
I tried to use Qt::QueuedConnection for connect method, but it does not help.
How to solve my problem?

I think the issue is that the event loop for the message box is blocking the main event loop so your button's signal is not emitted. But how do you plan to click the button anyway if you have a modal dialog open?

Here is the code:
Window::Window(QWidget *parent)
: QDialog(parent)
{
setupUi(this);
appPath = QApplication::applicationDirPath();
connect(pButton, SIGNAL(clicked()), this, SLOT(build()), Qt::QueuedConnection);
connect(pLineEdit, SIGNAL(editingFinished()), this, SLOT(pathChanged()), Qt::QueuedConnection);
}
void Window::pathChanged()
{
QString path = pLineEdit->text();
if(createPath(path))
updatePath(path);
}
bool Window::createPath(QString path)
{
if(!QDir(path).exists())
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, tr("Folder is not exist"), "Folder " + path + " is not exist. Do you want to create it?", QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes)
{
QDir dir;
dir.mkpath(path);
}
}
return true;
}
class Window : public QDialog, public Ui::GLConverterDialogUI
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
~Window(void);
......
}

I have the same problem in another application. I use some library. I guess that this library use pressed() signal of QAbstractButton instead of clicked(). And when I call QFileDialog::getSaveFileName() after button is pressed it seems that mouseReleaseEvent() is also not called. So after closing of dialog button is still pressed and I have to send MouseButtonRealese event manually.
Maybe I should call dialog with some special parameters?

Related

QTimer activeChanged signal

In the documentation of QTimer there is a Properties-section, containing the active-property.
This made me believe, there might be something like a activeChanged-signal, I could connect to.
For IMHO unapparent reasons
QObject::connect(m_timer, &QTimer::activeChanged, this, &MyObject::mySlot);
failes, stating activeChanged is no member of QTimer.
Basically, I want to do something, when the timer gets initially started (so not on restart) or finally stopped. When the signal activeChanged does not exist, has anyone knowledge:
Why it is a property at all?
If there are some other signals to connect to, to do this?
Any way to hook in, and do something when the timer is started or stopped?
test in main.cpp
QTimer* tim = new QTimer;
QObject::connect(tim, &QTimer::activeChanged, qApp, [tim](){qDebug() << "Active changed" << tim->isActive(); });
tim->start(40000); // I want to get a signal
tim->start(100); // I don't want to get a signal
tim->stop(); // I want to get a signal
Create your own timer class and encapsulate QTimer:
class Timer : public QObject
{
Q_OBJECT
QTimer m_timer;
public:
Timer ()
{
connect(&m_timer, &QTimer::timeout, this, &Timer::timeout);
}
void start(int msec)
{
if (m_timer.isActive())
{
// Restart detected -> block signal
m_timer.blockSignals(true);
m_timer.start(msec);
m_timer.blockSignals(false);
}
else
{
m_timer.start(msec);
}
}
}
Since the class Timer has the full control and knowledge of the QTimer, you can have any apparent behavior you want.

Qt connect mainwindow and dialog using signal and slot

I am trying to connect mainwindow and dialog using signal and slot. I am very new to qt. I have a lineEdit and a pushButton in mainwindow.ui, a lineEdit in dialog.ui. And I have those very basic code:
mainwindow.h:
signals:
void sendString(QString);
mainwindow.cpp:
void MainWindow::on_pushButton_clicked()
{
Dialog *mDialog = new Dialog(this);
emit sendString(ui->lineEdit->text());
connect(this, SIGNAL(sendString(QString)), mDialog, SLOT(showString(QString)));
mDialog->show();
}
dialog.h:
private slots:
void showString(QString);
dialog.cpp:
void Dialog::showString(QString str)
{
ui->lineEdit->setText(str);
}
But after I clicked the pushButton, the dialog showed, but nothing changed in the lineEdit.I hope I explain this clearly enough?
Can someone explain to me why and how to solve this? Thanks.
emit signal after connect
void MainWindow::on_pushButton_clicked()
{
Dialog *mDialog = new Dialog(this);
connect(this, SIGNAL(sendString(QString)), mDialog, SLOT(showString(QString)));
mDialog->show();
emit sendString(ui->lineEdit->text());
}
You have to create the connection before the emit.
But in your case you dont need the signal of the of the mainwindow at all. You invoke the showString method directly.

How to get the result of QDialog::show()?

I want to convert exec usages to show method in my projects. Because, when I use the exec for windows (dialogs) I can not open another window. This is the basic difference between exec() and show() method.
The exec and show work in different ways and I am wondering how can I change the below code with using show() instead of exec().
For example:
int result = exampleWindow->exec();
if ( result == QDialogButtonBox::Ok )
{
exampleWindow->UpdateCalibrationData(&data);
exampleWindow->UpdateFilterData(&filterData);
exampleWindow();
}
show() shows a non-modal window;
exec() shows a modal window.
If you want to get the result of show(), then go with Qt signals/slots:
ExampleWindow::ExampleWindow(QWidget *parent) : QDialog(parent)
{
// Assuming the QDialogButtonBox name is "buttonBox":
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
MainWindow.h:
class MainWindow : public QMainWindow {
Q_OBJECT
private slots:
void updateData();
}
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
connect(exampleWindow, SIGNAL(accepted()), this, SLOT(updateData()));
}
void MainWindow::updateData()
{
// Your code:
exampleWindow->UpdateCalibrationData(&data);
exampleWindow->UpdateFilterData(&filterData);
exampleWindow();
}
show() simply makes the dialog window visible. It is a QWidget method.
exec(), when provided in a class, always spins an event loop. In case of dialogs specifically, it'll make the dialog visible before spinning the event loop.
You could implement a functionally equivalent exec() yourself, as follows:
void myExec(QDialog * dialog) {
QStateMachine sm;
QState s1(&sm), s2(&sm);
sm.setInitialState(&s1);
QEventTransition transition(dialog, QEvent::Close);
s2.addTransition(&transition);
QEventLoop loop;
QObject::connect(&s2, &QState::entered, &loop, &QEventLoop::quit);
sm.start();
dialog->show();
loop.exec();
}
Generally speaking, you should never use exec() to create a nested event loop, since you're exposing a lot of your own code to possible reentrancy requirements. In case of dialogs, it is always possible to show a modal dialog box without using exec(), so there's really no point to it.
exec() method shows modal dialog as described here
You can use for example closeEvent() of your dialog. In it you can write something like:
void ExmpleWin::closeEvent(QCloseEvent *event)
{
if (/*Your condition*/) {
emit signalUpdateMyData();
event->accept();
}
}
Also you have to connect signal signalUpdateMyData() with apropriate slot where you can make:
exampleWindow->UpdateCalibrationData(&data);
exampleWindow->UpdateFilterData(&filterData);
exampleWindow();

how to trigger a signal in Qt

I've got an easy GUI window: a QLineEdit with a QPushButton. I want to trigger a signal when when the push button is clicked AND the input is validated (it meets a conditional statement, nevermind the details).
Normally I would use connect (object, signal, subject, slot). I guess that QPushButton clicked should trigger the middle-signal which is handled inside the widget slot. And the widget slot could trigger another signal - to my destination point. But how?
You have to declare your signal in class:
class myClass
{
/* stuff */
public signals:
void mySignal();
}
and in your code after validation:
void myClass::dataValidation()
{
/*validate data*/
emit mySignal();
}

implement a progress dialog by QDialog

I'm using QT to implement some UI program.
In this program I need a progress dialog. I tried to use the build-in QProgressDialog, it works fine but in my case I need to confirm (with another dialog) when the "cancel button" is clicked.
In QProgressDialog once the cancel button is clicked, the progress dialog will be canceled, so, I tried to implement my own progress dialog (very simple, a dialog with progress bar). However, if I use my own progress dialog, there is some problems. It cannot be moved or clicked. Once I tried to move it and the dialog loss its focus, the progress bar won't update any more and it cannot gain the focus again. I tried to set different Modality, but either Qt::ApplicationModal or Qt::WindowModal has the same situation.
follows is my progress dialog class, if someone knows how to modify QProgressDialog to meet the confirm requirement or where is the problem in my code.
header:
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
void setRange(int minimum, int maximum);
void setValue(int value);
void setLabelText(QString labtext);
bool wasCanceled();
private:
Ui::Dialog *ui;
bool cancelStatus;
private slots:
void cancel();
};
Sourceļ¼š
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
cancelStatus = false;
ui->progressBar->setRange(0,1);
ui->progressBar->setValue(0);
//this->setWindowModality(Qt::WindowModal);
show();
}
Dialog::~Dialog(){
delete ui;
}
void Dialog::setRange(int minimum, int maximum){
ui->progressBar->setRange(minimum,maximum );
}
void Dialog::setValue(int value){
this->ui->progressBar->setValue(value);
}
void Dialog::setLabelText(QString labtext){
this->ui->label->setText(labtext);
}
void Dialog::cancel(){
// pop up the confirm dialog here
// cancelStatus = true if the confirm dialog is accepted, else do nothing .
}
bool Dialog::wasCanceled(){
return cancelStatus;
}
From the Qt Documentation: The signal QProgressDialog::canceled() is emitted when the cancel button is clicked and it is connected to the cancel() slot by default.
Did you try to connect the canceled signal to you own validation slot, and the cancel the dialog if the user confirm is choice?
Before, connecting your own slot, disconnect the canceled signal from the cancel slot using QObject::disconnect() : http://doc.qt.io/archives/qt-4.7/qobject.html#disconnect

Resources