nube: stdio to QTextedit - qt

I've read lots of similar threads to this one but im not such a great programmer that i can make sense of it all. Im using qtcreator to make life simple and want to maka a program that can trigger another process, monitor its stdout and then kill it if necessary.
What I assume i want to do is create a QTextedit in the designer and plug a signal into it that updates the contained text whenever the stream updates, so far so good, but thats where i get fuzzy. My initial thought was to create a subclass of QObject that starts the process as a QProcess and whenever the stdout updates the QObject and appends new data to the QTextedit box.
So my program structure would run like this:
on button press create new QObject derived class.
The QObject derived class constructor starts a QProcess and connects the readyReadStdout() signal to the derived qObject class slot.
When the derived QObject is triggered it takes readyReadStdout() and appends any new data to the QTetEdit box.
on button press, call the derived QObject destructor and which kills the process.
Has anybody done something similar? Like i say ive read similar posts but sometimes it takes asking a question in your own words to be able to understand it
Thanks everyone (also my forst post, woo:)
Ok so heres my update:
I have added an instance of QProcess class (named proc) to my mainWindow class and also new instance of a QObject derived class (named procLog) to which I added a slot. I want this slot to take the readyReadStandardOutput() signal as a trigger to call readAllStandardOutput() and emit the new line to a new signal in procLog, I'm having trouble connecting the QProcess slot to the QObject derived class. heres what I'm trying:
connect(proc, SIGNAL(readyReadStandardOutput ()), procLog, SLOT(logReady()));
I get, error: QObject::connect: Cannot connect (null)::readyReadStandardOutput () to (null)::logReady()
Do you know why this is. Aslo is there a way to add code blocks to text in the comments?
thanks!

Related

how to access Qt MainWindow members

In my project, I want to call a variable QImage image generated in the mainwindow.h, in other class files, e.g., called SegSetupDialog.h. Here the image is loaded by clicking a pushbutton in mainwindow.ui, and the SegSetupDialog is a QDialog, which pops up by clicking one pushbutton in mainwindow.ui.
I tried to use a signal-slot connection to send qimage of mainwindow to SegSetupDialog as follows.
For Class MainWindow:
SegSetupDialog *segsetup;
if(image.isNull()==false)
{
emit sendImgData(image);
qDebug()<<"sendImgData emitted!";
if(segsetup==NULL) segsetup = new SegSetupDialog();
connect(this, SIGNAL(sendImgData(QImage)),segsetup,SLOT(getImgData(QImage)),Qt::QueuedConnection);
}
In SegSetupDialog::getImgData
void SegSetupDialog::getImgData(QImage qimage)
{
qImg = qimage;
qDebug()<<"qimage received!";
}
The above connection seems not to work since the qDebug message in getImgData is not printed out. Anyone can help check something wrong with codes, or suggest other methods for accessing image of mainwindow? Thanks!!
You need to do the signal/slot connection before you emit the signal. Connections are done once, usually in the constructor.
However, you should probably do the connect() in the constructor of SegSetupDialog instead of the MainWindow one. It's SegSetupDialog that wants to be notified about image data updates, so you should establish the connection there.
Also, to make sure the signals and slots are specified correctly, don't use Qt 4 connect() calls. Use Qt 5 ones that are checked at compile-time:
connect(this, &MainWindow::sendImgData,
segsetup, &SegSetupDialog::getImgData, Qt::QueuedConnection);
(Of course change it appropriately if you move it to the SegSetupDialog constructor.)

Function connected to the button is called twice after one click

I have a problem with slots and signals. I created buttons and connected them to the clicked() slot. Then i decided to connect signals and slots manually and since then when I click the button it calls its function twice.
connect(ui->okButton, SIGNAL(clicked()), this, SLOT(on_okButton_clicked()));
void settingswindow::on_okButton_clicked()
{
qDebug() << "ok clicked";
this->close();
}
I was looking for the answer on google, but all i found was this: Where is the generated code of qt signals slots editor but my *.ui file looks like this: pastebin to the code. As you can see there's only one line with and nothing more. I can't find where the information about signals and slots is saved. Rebuild and clean options won't help.
This is not a bug in Qt. If you look at the generated code for your ui_*.h file, you'll notice that the last statement executed in the setupUi() function is a call to QMetaObject::connectSlotsByName().
Since your slot already conforms to the naming convention that this function is looking for, your slot is automatically connected to the signal.
By manually connecting the signal to the slot, in your settingswindow class, you effectively duplicate the connection.
As #Devopia mentioned, this is a documented feature.

How to send signals to a qt class from a not qt class?

I created a qt class only to make gui and displayed the data on gui.
i didn't want to freeze the gui that's why i created another non_qt class to perform the operation so i made a object in the gui class of non_qt class and pass the parameter in that and started it in a new thread.
now after completing the operation i want to notify the gui class so it can display the results.
i also want to access the status bar of gui class so when non_qt class is performing the operation it can display some message on gui..
(i tried it with qt class but it didn't work that's why i created non_qt class..with non_qt class threading part is working fine but signal part is not working so i'm not able to notify the gui class).
so please help me out how to send signal to a qt class from a not qt class????
The signal is a concept that only applies to classes that derive from QObject.
If you want to trigger a slot, you don't need a signal. If the receiving object lives in the same thread (and only then), you can call the slot method on the reciving object directly.
For example, given an instance of a GUI object with a slot:
MainWindow * mainWindow;
class MainWindow : public QWidget {
Q_OBJECT
...
Q_SLOT void setStatus(const QString &);
...
};
You can simply do:
// The assert is essential to prevent bad bugs. If it triggers,
// you must use `QMetaObject::invokeMethod` instead.
Q_ASSERT(mainWindow->thread() == QThread::currentThread());
mainWindow->setStatus("Finished");
If the receiving object may live in another thread, or if you don't want to worry about threading issues, then you must use QMetaObject::invokeMethod, as follows:
// This is always safe. No need for asserts.
QMetaObject::invokeMethod(mainWindow, "setStatus",
Q_ARG(QString, "Finished"));
This overload of invokeMethod will correctly choose the connection type depending on whether the receiving object runs in the same thread. If the receiver is in the same thread, the call is a direct call. If it runs in another thread, the call will be converted to a QMetaCallEvent and posted to the receving object. This is thread-safe and doesn't require the receving object's setStatus method to be thread-safe.

How to call plain function from exec()?

I have 2 classes: one maintains some loop (at leas for 2-3 minutes; and is inherited from QObject) and another shows up a progress dialog (inherited from QDialog).
I want to start the loop as soon as the dialog is shown. My first solution was:
int DialogClass::exec()
{
QTimer::singleShot(0, LoopClassPointer, SLOT(start()));
return __super::exec();
}
There is a problem with throwing exceptions from slots. so I considered a possibility to make public slot start() just a public function. But now I don't know how to make it works well. Things like this:
int DialogClass::exec()
{
LoopClassPointer->start();
QApplication::processEvents();
return __super::exec();
}
don't help. The dialog doesn't appears.
Is there a common approach to this kind of situations?
some details, according to questions:
I have to work with system with its own styles, so we have a common approach in creating any dialogs: to inherit them from stytle class, which is inherited from QDialog.
my 'LoopClassPointer' is an exported class from separate dll (there is no UI support in it).
I have a 'start' button in main app, which connected with a slot, which creates progress dialog and 'LoopClassPointer'. at the moment I send 'LoopClassPointer' instance in the dialog and don't whant to make significant changes in the architecture.
Take a look at QtDemo->Concurrent Programming->Run function
e.g. in Qt 4.8: http://qt-project.org/doc/qt-4.8/qtconcurrent-runfunction.html
In this situation, I recommend you separate the logic of the loop from the dialog. Gui elements should always be kept separate.
It's great that your worker class is derived from QObject because that means you can start it running on a separate thread: -
QThread* m_pWorkerThread = new QThread;
Worker* m_pWorkerObject = new Worker; // assuming this object runs the loop mentioned
// Qt 5 connect syntax
connect(m_pWorkerThread, &QThread::started, m_pWorkerObject, &WorkerObject::start);
connect(m_pWorkerThread, &QThread::finished, m_pWorkerThread, &QThread::deleteThis);
m_pWorkerObject->moveToThread(m_pWorkerThread);
m_pWorkerThread->start();
If you're not familiar with using QThread, then start by reading this.
The only other thing you require is to periodically send signals from your worker object with progress of its work and connect that to a slot in the dialog, which updates its display of the progress.

Passing a class through a signal/slot setup in Qt

I'm trying to get the information of several of a class' member variables on the receiving end of a slot/signal setup, so I'd like to pass the entire class through. Unfortunately, after the class has been passed, the member variables seem to be empty. Here's some code snippets:
This sets up the signal to pass the class
signals:
void selected(const ControlIcon *controlIcon);
this is the slot/signal connection
connect(controllerList->serialController, SIGNAL(selected(const ControlIcon*)),
infoView, SLOT(serialControllerSelected(const ControlIcon*)));
I emit the signal from within the class to be passed
emit selected(this);
Here's the code to call on the class' member data
QLabel *ASCIIStringHolder = new QLabel;
ASCIIStringHolder->setText(controlIcon->m_ASCIIString);
Nothing shows up in the label, and when I set a breakpoint, I can see that there's nothing inside m_ASCIIString.
I looked to make sure that it was being assigned some text in the first place, and that's not the problem. I also tried the signal/slot setup with and without const.
Any help would be appreciated.
Qt signal/slot mechanism needs metainformation about your custom types, to be able to send them in emitted signals.
To achieve that, register your type with qRegisterMetaType<MyDataType>("MyDataType");
Consult official QMetaType documentation for more information about this.
First, since you are using an auto connection, do both sender and receiver live in the same thread? If not, it could happen that the call is queued and when it arrives, the data in the sender was already modified. You could try to use a direct connection just to make sure this isn't the problem.
Second, just for the fun of it, did you try to access the sender by using qobject_cast<ControlIcon*>(sender()) within the slot? This is how it is usually done if the signal doesn't pass this as an argument. Like this:
QLabel *ASCIIStringHolder = new QLabel;
// this is instead of the argument to the slot:
ControlIcon *controlIcon = qobject_cast<ControlIcon*>(sender());
ASCIIStringHolder->setText(controlIcon->m_ASCIIString);
The signal can't be declared to be passing a class and then actually pass the child of that class. I changed the signal, slot, and connect() to be SerialController (the child of ControllerIcon), and everything worked fine.

Resources