Is there another way besides declaring a static method inside a class to call it from outside the class ?
Here is my code (See the question marked as comment )
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
_stdcall BOOL EnumWindowsProc(HWND hw,LPARAM lp)
{
char title[255];
memset(title,0,255);
GetWindowTextA(hw,title,255);
qDebug() << title << endl;
// How can I access class MainWindow from this function ?
return true;
}
void MainWindow::on_pushButton_clicked()
{
EnumWindows(&EnumWindowsProc,0);
}
The typical way of doing this in the Windows world is to pass a pointer to the Enum function, like this:
void MainWindow::on_pushButton_clicked()
{
EnumWindows(&EnumWindowsProc,reinterpret_cast<void*>(this));
}
...and then cast it back in the callback:
_stdcall BOOL EnumWindowsProc(HWND hw,LPARAM lp)
{
char title[255];
memset(title,0,255);
GetWindowTextA(hw,title,255);
qDebug() << title << endl;
// How can I access class MainWindow from this function ?
MainWindow* that = reinterpret_cast<MainWindow*>(lp);
return true;
}
Related
I am quite new to programming, so hopefully someone can help me out. After calculating a value with a function and storing it into the variable with a setter, I want to call it in my viswindow.cpp to visualize it in a Graph. In the mainwindow the right value is calculated and stored by pressing a button, which also opens the viswindow. I tried to pass it with a pointer or with signals and slots, but it wouldn't work.
mainwindow.cpp:
double MainWindow::berechneFussabdruck(double strecke, int anzahl, double sfcWert)
{
if(strecke <= 1500 && strecke > 0){
double aequivalente_Co2 = (((sfcWert*3.116*50*(((0.0011235955)*(strecke-2*48.42))+0.233))*0.001)/anzahl);
setAequivalente(aequivalente_Co2);
}
else{
double aequivalente_Co2 = (((sfcWert*3.116*75*(((0.0011235955)*(strecke-2*208))+0.833))*0.001)/anzahl);
setAequivalente(aequivalente_Co2);
}
return aequivalente_Co2;
}
Button to open viswindow:
void MainWindow::on_pushButton_clicked()
{
MainWindow::berechneFussabdruck(strecke, anzahl, sfcWert);
visWindow = new VisWindow(this);
visWindow->show();
}
viswindow.cpp:
VisWindow::VisWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::VisWindow)
{
ui->setupUi(this);
...
*set0 << aequivalente_Co2 << aequivalente_Co2;
*set1 << 11.07 << 0;
*set2 << 0 << 0.49;
...
}
Thanks for helping!
Here are examples of:
Single time value transfer from MainWindow to VisWindow in constructor parameter.
Value update from MainWindow to VisWindow by slot-signal chain.
Value update from MainWindow to VisWindow by direct call of VisWindow->updateValue() slot as regular function.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "viswindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
signals:
void updatevalue(const double value);
private:
Ui::MainWindow *ui;
VisWindow * m_viswindow;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::on_pushButton_clicked() {
m_viswindow = new VisWindow(12.34, nullptr);
connect(this, &MainWindow::updatevalue,
m_viswindow, &VisWindow::updateValue);
m_viswindow->show();
}
void MainWindow::on_pushButton_2_clicked() {
emit updatevalue(23.45);
}
void MainWindow::on_pushButton_3_clicked() {
m_viswindow->updateValue(45.67);
}
viswindow.h
#ifndef VISWINDOW_H
#define VISWINDOW_H
#include <QWidget>
namespace Ui {
class VisWindow;
}
class VisWindow : public QWidget
{
Q_OBJECT
public:
explicit VisWindow(const double value, QWidget *parent = nullptr);
~VisWindow();
public slots:
void updateValue(const double value);
private:
Ui::VisWindow *ui;
};
#endif // VISWINDOW_H
viswindow.cpp
#include "viswindow.h"
#include "ui_viswindow.h"
VisWindow::VisWindow(const double value, QWidget *parent) :
QWidget(parent),
ui(new Ui::VisWindow)
{
ui->setupUi(this);
ui->lblValue->setText(QString::number(value,'f',2));
this->setWindowTitle("VisWindow");
}
VisWindow::~VisWindow() {
delete ui;
}
void VisWindow::updateValue(const double value) {
ui->lblValue->setText(QString::number(value,'f',2));
}
//Work.h
#ifndef WORK_H
#define WORK_H
#include <QDebug>
#include <QObject>
#include <QThread>
class Work : public QObject {
Q_OBJECT
public:
explicit Work(QObject *parent = nullptr);
public slots:
void snap();
void setStatus();
signals:
private:
bool status;
};
#endif // WORK_H
//Work.cpp
#include "Work.h"
Work::Work(QObject *parent) : QObject(parent) { status = true; }
void Work::snap() {
status = true;
while (true) {
if (status) {
qDebug() << "Work thread: " << QThread::currentThreadId();
} else {
qDebug() << "STOP";
break;
}
}
}
void Work::setStatus() { status = false; }
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include "Work.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
Work *work;
QThread thread;
};
#endif // MAINWINDOW_H
//MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
work = new Work();
work->moveToThread(&thread);
thread.start();
connect(ui->startButton, SIGNAL(clicked()), work, SLOT(snap()));
connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));
}
MainWindow::~MainWindow() {
thread.terminate();
delete ui;
}
//main.cpp
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
qDebug() << QThread::currentThreadId();
w.show();
return a.exec();
}
I use MainWindow to display, Work to do something. And I use work->moveToThread(&thread).
Click start button to execute snap function in Work, what I want to do is when I click stop button, the snap function output STOP. And I can still start and stop whenever I like.
But I fail. It seems impossible to change the status during the while loop. Work doesn't get the stopButton clicked signal. Is it because of priority?
Could anyone give me some advices?
Firstly consider your Work::snap implementation...
void Work::snap() {
status = true;
while (true) {
if (status) {
qDebug() << "Work thread: " << QThread::currentThreadId();
} else {
qDebug() << "STOP";
break;
}
}
}
Once started it never yields control to the Qt event loop. Now consider the connect call...
connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));
Since ui->stopButton and work have different thread affinities this is effectively a queued connection and requires the receiver to have an active event loop. Hence the call to setStatus will remain pending forever.
A better way to achieve your goal might be to make use of a simple atomic bool...
std::atomic<bool> status;
and change the connect call to modify status directly using a lambda (untested)...
connect(ui->stopButton, &QPushButton::clicked, [this]{ work->setStatus(); });
I solve it.
I add a slot and a signal in MainWindow and change stop slot.
connect(ui->startButton, &QPushButton::clicked, this, &MainWindow::start);
connect(this, &MainWindow::startSnap, work, &Work::snap);
// start slot
void MainWindow::start() {
thread.start();
emit startSnap();
}
void MainWindow::stop() {
if (thread.isRunning()) {
thread.requestInterruption();
}
}
And change the codes in Work::snap
void Work::snap() {
while (true) {
if (QThread::currentThread()->isInterruptionRequested()) {
qDebug() << "STOP";
QThread::currentThread()->exit();
return;
} else {
qDebug() << "Work thread: " << QThread::currentThreadId();
}
}
}
The key codes are:
thread.requestInterruption();(MainWindow::stop)
QThread::currentThread()->exit();(Work::snap)
thread.start();(MainWindow::start)
I am trying to capture the text output and input of child QProcess, now I need that whenever child use system("cls") I get notified so that I can clear my QTextEdit for displaying and taking child output
editProcess.h
#ifndef EDITPROCESS_H
#define EDITPROCESS_H
#include <QPointer>
#include <QProcess>
#include <memory>
class QPlainTextEdit;
// a Process with plainTextEdit as output and input window
class EditProcess : public QProcess {
Q_OBJECT
public:
explicit EditProcess(QWidget *parent = nullptr);
QPointer<QPlainTextEdit> edit() { return m_textEdit; }
~EditProcess();
signals:
public slots:
private:
QPointer<QPlainTextEdit> m_textEdit;
protected:
bool eventFilter(QObject *, QEvent *event) override;
};
#endif // EDITPROCESS_H
editProcess.cpp
#include "editprocess.h"
#include <QDebug>
#include <QKeyEvent>
#include <QPlainTextEdit>
EditProcess::EditProcess(QWidget *parent)
: QProcess(parent), m_textEdit{new QPlainTextEdit}
// zm_textEdit(std::make_shared<QPlainTextEdit>(parent))
{
QObject::connect(this, &EditProcess::readyReadStandardOutput, [this]() {
m_textEdit->insertPlainText(readAllStandardOutput());
});
QObject::connect(this, &EditProcess::readyReadStandardError, [this]() {
m_textEdit->insertPlainText(readAllStandardError());
});
QObject::connect(
this,
static_cast<void (EditProcess::*)(int, QProcess::ExitStatus)>(
&EditProcess::finished),
[this](int exitCode, QProcess::ExitStatus) -> void {
m_textEdit->insertPlainText(readAllStandardOutput());
m_textEdit->insertPlainText(
QString("\nProgram Finished with exit code: %1").arg(exitCode));
});
m_textEdit->installEventFilter(this);
}
EditProcess::~EditProcess() { kill(); }
bool EditProcess::eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::KeyPress) {
auto keyEvent = dynamic_cast<QKeyEvent *>(event);
if (keyEvent->modifiers() == Qt::CTRL && keyEvent->key() == Qt::Key_C)
kill();
else
write(keyEvent->text().toUtf8());
}
return false;
}
mainwidow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
auto p = new EditProcess(parent);
p->edit()->setParent(centralWidget());
p->setProgram(
"test.exe");
p->start();
qDebug() << p->errorString();
}
if I call system("cls") from child process now, nothing happens, QTextEdit remains same, I didn't notice any change
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
#include <iostream>
char * ip_ch;
void test(const char* a)
{
qDebug()<<"test is "<<a;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_lineEdit_editingFinished()
{
QString st_ip_ch=ui->lineEdit->text();
QByteArray ip_ch_temp = st_ip_ch.toLatin1();
ip_ch = ip_ch_temp.data();
qDebug()<<"ip_ch is "<<ip_ch;
test(ip_ch);
}
void MainWindow::on_pushButton_clicked()
{
qDebug()<<"when push button ";
test(ip_ch);
}
The code uses the following UI. I want to type some string in the line input widget like this, and then push the button.
It prints out this:
ip_ch is 123
test is 123
When button is clicked, it prints:
test is `??`
Why does ip_ch point to garbage?
ip_ch becomes a dangling pointer as soon as on_lineEdit_editingFinished() returns. That's because you're making it point to a temporary buffer ip_ch_temp that goes out of scope:
ip_ch = ip_ch_temp.data(); // Don't do that!
Since you're coding in C++, you shouldn't be writing C. Store your Latin1 representation by value:
class MainWindow : public QMainWindow {
QByteArray ip_ch;
Ui::MainWindow ui;
public:
MainWindow(QWidget * parent = 0) {
ui.setupUi(this);
}
// no explicit destructor needed!
void test(const QByteArray & data) { qDebug() << "test:" << data; }
void on_lineEdit_editingFinished()
{
ip_ch = ui.lineEdit->test().toLatin1();
qDebug() << "ip_ch is" << ip_ch;
test(ip_ch);
}
void on_pushButton_clicked()
{
qDebug() << "button was pushed";
test(ip_ch);
}
};
Other problems with your code:
#include <QDebug>, not <QtDebug>
#include <QMainWindow>, not <qmainwindow.h>
Most likely, you don't need to derive your dialog from QMainWindow; derive from a QDialog instead.
Don't use a pointer to ui; store it by value instead. That way you have less code that can go wrong: let the compiler manage memory for you. That's what it's for!
This error;
C:\Users\Seb\Desktop\SDIcw2\widget.cpp:6: error: uninitialized reference member 'Widget::handler' [-fpermissive]
Widget::Widget(QWidget *parent) :
^
has occurs after I added an event handler for my combination box. Does anyone know why? The widget ran fine before so im not sure as to why!
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QString>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::getList(SDI::shipHandler& shipHandler)
{
handler = shipHandler;
}
void Widget::populateCombo()
{
ui->comboBox->addItem("Select Vessel...");
for(std::vector<SDI::navalVessels*>::const_iterator i = handler.ships.begin(); i != handler.ships.end(); ++i)
{
SDI::navalVessels* ship = *i;
QString qstr = QString::fromStdString(ship->name);
ui->comboBox->addItem(qstr);
}
}
void Widget::on_comboBox_currentIndexChanged(int index)
{
for(std::vector<SDI::navalVessels*>::const_iterator i = handler.ships.begin(); i != handler.ships.end(); ++i)
{
SDI::navalVessels* ship = *i;
QString qstr = QString::fromStdString(ship->name);
QString str = ui->comboBox->currentText();
if (str == qstr)
{
//do something here
}
}
}
trying to change the values of boxes depending on whats selected in the combo box.
You haven't shown widget.h, but presumably you have a private section that looks something like:
private:
Ui::Widget *ui;
ShipHandler *handler;
Your compiler is reminding you that uninitialized pointers can be dangerous, so you need to make sure you change your constructor to initialize them:
Widget::Widget(QWidget *parent)
: QWidget(parent),
ui(new Ui::Widget),
handler(0)
{
ui->setupUi(this);
}