I am working on a code that allows the user to control a piezo (PZ193E) in a MainWindow created with Qt Designer form.
However, when I call the function designed to connect the piezo to the computer (from an external library given by the constructor) my UI freeze until the connection is established.
I am trying to display a QDialog with a QLabel in it, telling the user to wait while the connection is processing, but when I do so, the QDialog shows up but without the label. It is only displayed when the connection is established and when the QDialog can close.
Here is how I coded my dialog :
In the .h :
QDialog *_waitQD = new QDialog;
QVBoxLayout *_waitQVBL = new QVBoxLayout;
QLabel *_waitQL = new QLabel("Loading...");
In the .cpp :
_waitQD->setMinimumSize(QSize(95,35));
_waitQVBL->addWidget(_waitQL);
_waitQD->setLayout(_waitQVBL);
And then I call :
_waitQD->show();
if (_piezo.connected()) // bool funtion that return true if the connection is established
_waitQD->close();
This is what it looks like:
The ideal solution is not blocking the main thread while establishing the connection; the workaround is adding QApplication::processEvents(); after the call to show
you need to call app.exec()
#include <QApplication>
#include <QDialog>
#include <QVBoxLayout>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDialog *_waitQD = new QDialog;
QVBoxLayout *_waitQVBL = new QVBoxLayout;
QLabel *_waitQL = new QLabel("Loading...");
_waitQD->setMinimumSize(QSize(95,35));
_waitQVBL->addWidget(_waitQL);
_waitQD->setLayout(_waitQVBL);
_waitQD->show();
return app.exec();
}
Related
I have the following Problem:
I have a Qt MainWindow which starts several Dialogs. Through an external source, I can hide and show the MainWindow. If a dialog is open, only the MainWindow is hidden, but the dialog is still visible. This is not nice but not my main problem. The main problem is, if i close the dialog while the MainWindow is hidden, the whole Application terminates. I do not want that, because I can make my main window visible again by external source.
I know it has something to do with QApplication quitOnLastWindowClosed. But if i set it true, my Application doesn't terminate if i normaly press "X".
Here is an example:
// MainApp.h
#include <QMainWindow>
#include "ui_MainWindow.h"
class MainApp : public QObject {
Q_OBJECT
public:
MainApp(QObject *parent = nullptr);
private slots:
void slotOpenDialog();
private:
QMainWindow mMainWindow;
Ui::MainWindow mUi;
};
// MainApp.cpp
#include "MainApp.h"
#include <QTimer>
#include <QMessageBox>
MainApp::MainApp(QObject *parent) {
mUi.setupUi(&mMainWindow);
mMainWindow.show();
connect(mUi.pushButton, &QPushButton::clicked, this, &MainApp::slotOpenDialog);
// simulate external hide and show mechanism
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout,
[=] {
if(mMainWindow.isHidden()) mMainWindow.show();
else mMainWindow.hide();
});
timer->start(3000);
}
void MainApp::slotOpenDialog() {
QMessageBox::information(nullptr, "Info", "text");
}
// main.cpp
#include <QApplication>
#include "MainApp.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainApp* mApp = new MainApp;
// if set true, I can't exit the application with "X"
//a.setQuitOnLastWindowClosed(false);
int error = a.exec();
delete mApp;
return error;
}
How can I prevent the program from quitting when it is hidden and a still visible dialog has been closed and how can I make it exit normally when the window is visible?
QApplication emits a signal "lastWindowClosed" and it has a quit() slot. As mentioned in the comments, the problem can be solved by connecting your own slot onLastWindowClosed() to that signal and quitting only when you want to.
So I am quite new to qt, and am trying to open a desktop app with a child dialog, and when I click a button it points to the parent dialog. I managed to do that, but whenever I run it and click 'go' it points me to my parent window and then crashes! I got the code from this link. the first answer was what got it to work, and the second one didn't work at all. my MainWindow (parent) dialog is survey and my child dialog is global. (I know I named them weird. Still learning).
my main.cpp
#include "survey.h"
#include <QApplication>
#include "global.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget survey;
survey.show();
global popup(&survey);
popup.show();
/*
survey w;
w.show();
*/
return a.exec();
}
my global.cpp
#include "global.h"
#include "ui_global.h"
#include "survey.h"
global::global(QWidget *parent) :
QDialog(parent),
ui(new Ui::global)
{
ui->setupUi(this);
}
global::~global()
{
delete ui;
}
void global::on_Go_clicked()
{
//survey *nWin;
auto win = new survey();
win->setAttribute(Qt::WA_DeleteOnClose);
win->show();
deleteLater();
}
What do I need to change so my desktop app doesn't crash when I run it??
You're calling deleteLater on a global instance, which you did not instantiated with new, it's in your main:
global popup(&survey);
When delete is called, your application crashes.
No need to call deleteLater in your slot.
Here is a "hello world" button that display a window and button. I would like to do a cout or any other custom functionality when the button is clicked but I'm stuck.
#include <QApplication>
#include <QPushButton>
#include <iostream>
int main(int argc, char **argv){
// create app
QApplication app (argc, argv);
// create window
QWidget window;
window.setWindowTitle("MyWindow");
window.setFixedSize(600, 480);
// create button
QPushButton *button = new QPushButton(&window);
button->setGeometry(10, 10, 100, 35);
button->setText("hello!");
// event handling
// HERE IS THE PROBLEM
QObject::connect(button, SIGNAL(clicked()), ???, SLOT(???));
// show window
window.show();
}
How can I append a custom function to the SLOT? So I can console log stuff and handle the event on my own way? I can connect it to a QMediaPlayer for example to start/stop but I'm still very confused on how to use the signal/slot.
You need do all this things inside QObject subclass, or you can use new syntax of signal and slot and in this case you will be able to do this in main() function, use lambdas and so on. But it can be done only in Qt5.
QObject::connect(button, &QPushButton::clicked, someFunction);
If you want do this with old syntax then you need create some subclass and then create custom slots. The most common example you can find here: http://qt-project.org/doc/qt-4.8/mainwindows-application.html
What I'm trying to do is launch a program within another program using QProcess and then save the output from the launched program into a QTextEdit of the launcher program. Every time I launch this program I want it to add more text to the QTextEdit. Now I get the program to launch but then after the text is supposed to be written it crashes. Here is the code:
#include <QWidget>
#include <QPushButton>
#include <QTextEdit>
#include <QProcess>
#include <QVBoxLayout>
#include <QApplication>
class Widget : public QWidget
{
Q_OBJECT
QTextEdit* text;
public:
Widget() : text(new QTextEdit) {
QPushButton* addBtn = new QPushButton("Add Module");
text->setReadOnly(true);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(addBtn,0);
layout->addWidget(text);
connect(addBtn,SIGNAL(clicked()),SLOT(launchModule()));
}
Q_SLOT void launchModule() {
QString program = "C:/A2Q2-build-desktop/debug/A2Q1.exe";
QProcess *myProcess = new QProcess(this);
connect(myProcess, SIGNAL(finished(int)), SLOT(finished()));
connect(myProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(finished()));
myProcess->start(program);
}
Q_SLOT void finished() {
QProcess *process = qobject_cast<QProcess*>(sender());
QString out = process->readAllStandardOutput(); // will be empty if the process failed to start
text->append(out);
delete process;
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Widget w;
w.show();
app.exec();
}
#include "main.moc"
It's crashing because you're deleting the sender object while inside a slot. Instead of delete process, you should
process->deleteLater();
For logging purposes you should be using QPlainTextEdit instead of a QTextEdit. The former is faster. You're prematurely pessimizing by using the latter. Alas, even QPlainTextEdit becomes abysmally slow if you're sending about 100 lines/s (at least on Qt 4.8). If you want a really fast log view, you'll need to use QListWidget, with a caveat, or roll your own.
I have a complete example of how to send to and receive from a process in another answer.
The process is crashing because you're deleting the parent from within the finished slot.
Also, it's probably easier to do something like this:
QObject::connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(getOutput()));
instead of using the finished() slot. But that's more personal preference than anything.
I'm trying to write a simple Qt program which takes text inside a QLineEdit and appends it into a QTextEdit object when the return key is pressed.
Here is the code for my program:
#include <QApplication>
#include <QtGui>
#define WIDTH 640
#define HEIGHT 480
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QTextEdit textArea;
textArea.setReadOnly(true);
QLineEdit lineEdit;
QPushButton quit("Quit");
QObject::connect(&quit, SIGNAL(clicked()), qApp, SLOT(quit()));
QHBoxLayout hLayout;
hLayout.addWidget(&lineEdit);
hLayout.addWidget(&quit);
QVBoxLayout vLayout;
vLayout.addWidget(&textArea);
vLayout.addLayout(&hLayout);
QWidget window;
window.setBaseSize(WIDTH, HEIGHT);
window.setLayout(&vLayout);
window.show();
//This is the line I can not get to work
QObject::connect(&lineEdit, SIGNAL(returnPressed()), &textArea, SLOT(append(lineEdit.text())));
return app.exec();
}
Essentially, the problem is connecting the QLineEdit returnPressed() SIGNAL to the QTextEdit append() SLOT. I am hoping someone can point out what is wrong with my code.
Thank you very much in advance for your time.
When you run your program, you should notice on the console the following Qt error output..
Object::connect: No such slot QTextEdit::append(lineEdit.text()) in ..
You would need to qualify the append reference in your call to connect with the QTextEdit variable name textArea.
But that's not going to help much because you can only specify signal and slot method names and parameter types when calling connect so you can't specify lineEdit.text() in there.
Since the append() slot expects a QString, ideally you would want to connect a signal that includes a QString but there is no such signal for QLineEdits.
You pretty much have to write a slot yourself that you can connect to returnPressed() and call textArea.append(lineEdit.text()) from there. You will need to subclass a QObject of some kind to write a slot which would usually mean subclassing QWidget and putting all of your UI building code in its constructor.
You might also notice that your program crashes when you close it. Since Qt likes to manage the destruction of most QObjects itself, it is usually best to allocate all QObject instances on the heap with new. This isn't technically necessary all the time but it is much easier :)
QObject::connect(&lineEdit, SIGNAL(returnPressed()), &textArea, SLOT(append(lineEdit.text())));
returnPressed() doesn't take any arguments, but append(QString) does take one argument; a QString. Thus, if this would work, you would theoretically call append(""), meaning you wouldn't append anything. Using lineEdit.text() wouldn't work either at this place.
I would recommend you to create a class for the widget:
class Widget : public QWidget
{
public:
Widget(QWidget parent = 0);
//Other public functions
private:
//Private functions and variables
public slots:
void boom();
};
Then you can just use
Widget w(0);
w.show();
in your main function.
void boom() would be called by returnPressed(), and it would take lineEdit.text() and append it to the QTextEdit.
I hope this helps.
here is the code it might be helpful.....
#include "hwidget.h"
Hwidget::Hwidget(QWidget *parent) :
QWidget(parent)
{
}
void Hwidget::mainform_init(void)
{
lineeditp = new QLineEdit;
quitp = new QPushButton("&Exit");
hboxlayoutp = new QHBoxLayout;
hboxlayoutp->addWidget(lineeditp);
hboxlayoutp->addWidget(quitp,0,0);
vboxlayoutp = new QVBoxLayout;
texteditp = new QTextEdit;
texteditp->setReadOnly(true);
vboxlayoutp->addWidget(texteditp,0,0);
vboxlayoutp->addLayout(hboxlayoutp);
QWidget *mywin = new QWidget;
mywin->setLayout(vboxlayoutp);
mywin->setWindowTitle("My Sig and Slot");
mywin->show();
lineeditp->setFocus();
}
void Hwidget::mcopy(void)
{
qDebug() <<"i am your copy slot";
texteditp->setText(lineeditp->text());
lineeditp->clear();
}
#include <QApplication>
#include "hwidget.h"
int main (int argc, char *argv[])
{
QApplication app(argc,argv);
Hwidget *hwin = new Hwidget;
hwin->mainform_init();
hwin->connect(hwin->quitp,SIGNAL(pressed()),
qApp,SLOT(quit()));
hwin->connect(hwin->lineeditp,SIGNAL(returnPressed()),
hwin,SLOT(mcopy()));
return app.exec();
return 0;
}
#ifndef HWIDGET_H
#define HWIDGET_H
#include <QWidget>
#include <QTextEdit>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QObject>
#include <QString>
#include <QDebug>
class Hwidget : public QWidget
{
Q_OBJECT
public:
explicit Hwidget(QWidget *parent = 0);
void mainform_init(void);
signals:
public slots:
void mcopy(void);
private:
QHBoxLayout *hboxlayoutp;
QVBoxLayout *vboxlayoutp;
public:
QPushButton *quitp;
QLineEdit *lineeditp;
QTextEdit *texteditp;
};
#endif // HWIDGET_H