Unknown ouput with qdebugstream and qtextedit - c++

The first output in the textedit is a number 3, I don't know why that number is coming form Qt::LogText. This question is based from a previous question I had asked, I'm using the same qdebugstream header file from the link below.
Redirect std::cout to a QTextEdit
The new project below is a QT Gui Application that will redirect the cout to a textedit. Also, since settextformat() is no longer a member of QTextEdit, I converted Qt::LogText into a string.
This was based on another post but I did not understand the solution.
QTextEdit::setTextFormat(Qt::LogText) does not exist anymore, what else can I use to log?.
Can someone provide more information on this?
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->textEdit->setReadOnly(true);
ui->textEdit->setText(QString("%1").arg(Qt::LogText));
QDebugStream qout(std::cout, ui->textEdit);
cout << "Send this to the Text Edit!" << endl;
}
MainWindow::~MainWindow()
{
delete ui;
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qdebugstream.h"
#include "stdio.h"
#include "iostream"
using namespace std;
namespace Ui {
class MainWindow;
}
class QtextEdit;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

You should use QPlainTextEdit in Qt 4.x which seems to be equivalent using Q3TextEdit(QTextEdit in Qt 3.x) with text format of Qt::LogText.
For QPlainTextEdit version of QDebugStream might be like followings.(you may be noticed that append() mem func is renamed into addPlainText() and that's it viola). Hope this helps.
#ifndef QDEBUGSTREAM_H
#define QDEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QPlainTextEdit>
class QDebugStream : public std::basic_streambuf<char>
{
public:
QDebugStream(std::ostream &stream, QPlainTextEdit* text_edit)
: m_stream(stream)
{
log_window = text_edit;
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~QDebugStream()
{
// output anything that is left
if (!m_string.empty())
log_window->appendPlainText(m_string.c_str());
m_stream.rdbuf(m_old_buf);
}
protected:
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
log_window->appendPlainText(m_string.c_str());
m_string.erase(m_string.begin(), m_string.end());
}
else
m_string += v;
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
m_string.append(p, p + n);
int pos = 0;
while (pos != std::string::npos)
{
pos = m_string.find('\n');
if (pos != std::string::npos)
{
std::string tmp(m_string.begin(), m_string.begin() + pos);
log_window->appendPlainText(tmp.c_str());
m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
}
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
std::string m_string;
QPlainTextEdit* log_window;
};
#endif

Related

Why can't I construct my subclass in QT C++? [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 months ago.
I am working on a project that utilizes a whole suite of custom widget that my company uses.
I am trying to subclass the QLineEdit QWidget so that I can override the default arrow key behavior. It should just behave like a regular QLineEdit.
I then want to use this custom QLineEdit (that I named DataLineEdit), in place of the standard QLineEdits that I dynamically created in another Widget, DataWidget.
I have followed tutorial after tutorial on subclassing, but cannot avoid the error:
undefined reference to "DataLineEdit::DataLineEdit(QWidget*)
My code is below.
datalineedit.h
#ifndef DATALINEEDIT_H
#define DATALINEEDIT_H
#include <QLineEdit>
#include <QWidget>
class DataLineEdit: public QLineEdit
{
Q_OBJECT
public:
explicit DataLineEdit(QWidget *parent = 0);
~DataLineEdit();
protected:
void keyPressEvent(QKeyEvent* event);
signals:
void leftRightOverrideKeyPress(int state);
private:
};
#endif // CUSTOMLINEEDIT_H
datalineedit.cpp
#include "datalineedit.h"
#include<QKeyEvent>
DataLineEdit::DataLineEdit(QWidget*parent) : QLineEdit(parent)
{
}
DataLineEdit::~DataLineEdit()
{
}
void DataLineEdit::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Left && this->cursorPosition() == 0)
{
emit leftRightOverrideKeyPress(0);
}
else if(event->key() == Qt::Key_Right && this->cursorPosition() == 2)
{
emit leftRightOverrideKeyPress(1);
}
else
{
QLineEdit::keyPressEvent(event);
}
}
datawidget.h
#define DATAWIDGET_H
#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include <QMessageBox>
#include <QLineEdit>
#include <QObject>
#include <QtCore>
#include <QtGui>
#include <QKeyEvent>
#include <QMainWindow>
#include "datalineedit.h"
extern int focusRow;
extern int focusCol;
extern int numRows;
extern int numBottomRowCols;
extern QLineEdit *focusedLineEdit;
namespace Ui{
class DataWidget;
}
class QLineEdit;
class QLabel;
class DataWidget : public QWidget
{
Q_OBJECT
public:
explicit DataWidget(QWidget *parent = 0);
~DataWidget();
QString data;
protected:
bool eventFilter(QObject *object, QEvent *event);
public slots:
void focusChanged(QWidget *old, QWidget *now);
void arrowKeyNavigation(int state);
void on_applyChangePushButton_clicked();
void setData(QString text);
QString getData();
private slots:
void updateDataGridVisibility();
void on_payloadLineEdit_textChanged(const QString &arg1);
void on_savePushButton_clicked();
void on_openPushButton_clicked();
void on_presetComboBox_currentIndexChanged(int index);
private:
Ui::DataWidget *ui;
QString currentFile = "";
};
#endif // DATAWIDGET_H
datawidget.cpp
#include "datawidget.h"
#include "datawidget.h"
#include "datalineedit.h"
#include <QGridLayout>
#include <QLineEdit>
#include <QGroupBox>
#include <QKeyEvent>
#include <QIntValidator>
int focusRow;
int focusCol;
int numRows;
int numBottomRowCols;
QLineEdit *focusedLineEdit;
enum key_directions
{
arrowLeft = 0,
arrowRight = 1,
arrowUp = 2,
arrowDown = 3
};
enum presets
{
preset1 = 0,
preset2 = 1,
preset3 = 2,
preset4 = 3,
preset5 = 4,
clean = 5,
zeroes = 6
};
DataWidget::DataWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::DataWidget)
{
ui->setupUi(this);
this->installEventFilter(this);
connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(focusChanged(QWidget*,QWidget*)));
//payloadLineEdit
ui->payloadLineEdit->setValidator(new QIntValidator(0,64, this));
ui->payloadLineEdit->setFixedSize(20,20);
ui->payloadLineEdit->setTextMargins(0,0,0,0);
//dataGridLayout
ui->dataGridLayout->setAlignment(Qt::AlignLeft);
ui->dataGridLayout->setAlignment(Qt::AlignTop);
for(int i=0; i<4; i++)
{
for(int j=0; j<16; j++)
{
DataLineEdit *lineEdit = new DataLineEdit();
lineEdit->setText("00");//set data default
lineEdit->setInputMask("Hh");//limit to hex values
lineEdit->setFixedSize(20,20);
lineEdit->setTextMargins(0,0,0,0);
lineEdit->setAlignment(Qt::AlignCenter);
lineEdit->setAlignment(Qt::AlignCenter);
connect(lineEdit, SIGNAL(leftRightOverrideKeyPress(int)), this, SLOT(arrowKeyNavigation(int)));
ui->dataGridLayout->addWidget(lineEdit, i, j);
}
}
updateDataGridVisibility();
}
DataWidget::~DataWidget()
{
delete ui;
}
void DataWidget::arrowKeyNavigation(int state)
{
//does something
}
You could edit the class in the following form:
class DataLineEdit: public QLineEdit
{
Q_OBJECT
public:
explicit DataLineEdit(QWidget* parent = 0);
...
and
DataLineEdit::DataLineEdit(QWidget* parent) : QLineEdit(parent)
{
}
Thank you for all the help, it was definitely a linker issue but since I am working within a much larger project, I didn't want to mess with imports or .pro files too much. DataLineEdit is specific to DataWidget, so I simply moved the entire datalineedit.h file into the datawidget.h file at the bottom, and the same for the .cpp files. This avoids any linking all together and keeps things tidier based on the project's file hierarchy.

How to display a QChartView inside a QStackedWidget?

I want my form to have a QStackedWidget with 2 (at least) pages and each of them has a QChartView.
In the form editor, through the 'promote' menu, I made a QChartView from QGraphicView. (screenshoot (so far there is only 1 QChartView on it - so that i can see which page is open)).
From the main window, when one of the buttons is pressed, I want to open the above windows in a loop:
void Widget::ShowStudioCharts() noexcept
{
for(auto & e : this->userInfoVector){
Form *pForm = new Form();
pForm->provideStudioData(&e.studiosStats, e.nickname);
pForm->processStudioStats();
pForm->show();
}
}
I tried to do it like this:
Form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QPieSeries>
#include <QChart>
#include <QChartView>
#include <QGridLayout>
#include <vector>
#include <map>
#include <QStackedWidget>
#include <QtGlobal>
#include <QRectF>
#include <QRect>
#include <QPushButton>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr);
~Form();
void provideStudioData(std::map<std::string, std::size_t> *studiosStats, const std::string &nickname) noexcept;
void processStudioStats() noexcept;
private slots:
void on_pushButton_2_clicked();
private:
std::vector<std::map<std::string, size_t>*> stats;
std::vector<std::string> nicknames;
Ui::Form *ui;
};
#endif // FORM_H
Form.cpp
#include "form.h"
#include "ui_form.h"
#include <QPieSeries>
#include <QPieSlice>
#include <QChart>
using namespace QtCharts;
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
void Form::provideStudioData(std::map<std::string, size_t> *studiosStats, const std::string &nickname) noexcept
{
this->stats.push_back(studiosStats);
this->nicknames.push_back(nickname);
}
void Form::processStudioStats() noexcept
{
srand(time(0));
QPieSeries *series = new QPieSeries();
// for (const auto & e : this->stats ){
// //QBarSet *set0 = new QBarSet("1");
// for ( const auto & a : *e){
// //*set0 << a.second;
// qDebug( (a.first + " " + std::to_string(a.second)).c_str());
// }
// }
for ( const auto & a : *this->stats[0]){
QPieSlice * slice = new QPieSlice();
slice->setColor(QColor(rand()%255, rand()%255, rand()%255));
slice->setValue(a.second);
slice->setLabel(a.first.c_str());
series->append(slice);
}
QChart *chart = new QChart();
chart->setAnimationOptions(QChart::AnimationOption::AllAnimations);
chart->addSeries(series);
//chart->setPlotArea(QRectF(200,0,1400,1100));
//chart->legend()->detachFromChart();
chart->legend()->setBackgroundVisible(true);
chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
//chart->legend()->setGeometry(QRectF(20,20,200,1000));
chart->setTitle(QString::fromStdString(this->nicknames[0]));
this->setWindowTitle(QString::fromStdString(this->nicknames[0]));
chart->legend()->setAlignment(Qt::AlignLeft);
ui->graphicsView = new QChartView(chart);
ui->graphicsView->show();
//ui->stackedWidget->show();
}
void Form::on_pushButton_2_clicked()
{
if(0 == this->ui->stackedWidget->currentIndex())
this->ui->stackedWidget->setCurrentIndex(1);
else if(1 == this->ui->stackedWidget->currentIndex())
this->ui->stackedWidget->setCurrentIndex(0);
}
The code is compiled, windows are opened. But the problem is that my chart is displayed in another window above the opened one.
This is obviously the result of
ui->graphicsView->show();
But if i remove this line, then the graph is not visible at all.
Help please, thanks in advance.
Doing ui->graphicsView = new QChartView(chart); does not replace the QChartView, you are just assigning the pointer. The solution is to reuse the existing QChartView so it changes to: ui->graphicsView->setChart(chart);.

Redirect qDebug to an emitted signal

I've successfully redirected qDebug() output to a QTextEdit widget. For several reasons, I'd like every qDebug() message to be included in an emitted signal. One reason is that the object which shall receive the output isn't available. Another reason is that I want to redirect the output to different objects depending on which activity is active at the moment (using connect/disconnect of the signal to different slots).
I've made a working example code that redirects qDebug to a QTextEdit widget. Can someone please help me to get this code to emit a signal which includes the qDebug message?
I'm not sure if its possible to have Q_DebugStream emit a signal (I've tried and failed to make a Qt Class out of it).
It must be possible to pass a pointer to a function/slot instead of a pointer to a QTextEdit when calling Q_DebugStream, but I'm not sure how this is done.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void logSignal(QString);
public slots:
void logSlot(QString);
private:
QTextEdit *logView;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "q_debugstream.h"
#include <QGridLayout>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *mainWidget = new QWidget(this);
setCentralWidget(mainWidget);
logView = new QTextEdit;
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(logView,0,0,1,1);
mainWidget->setLayout(mainLayout);
connect(this, SIGNAL(logSignal(QString)),
this, SLOT(logSlot(QString)));
emit logSignal("Message from a signal\n");
new Q_DebugStream(std::cout, logView); //Redirect Console output to QTextEdit
Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit
qDebug() << "DEBUG MODE ACTIVE";
}
MainWindow::~MainWindow(){}
void MainWindow::logSlot(QString log) {
logView->append(log);
}
q_debugstream.h
//As per forum:
//http://www.qtforum.org/article/39768/redirecting-std-cout-std-cerf-qdebug-to-qtextedit.html
//A couple of lines added to ensure newlines go between each call.
//Thanks, James!
#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QTextEdit>
class Q_DebugStream : public std::basic_streambuf<char>
{
public:
Q_DebugStream(std::ostream &stream, QTextEdit* text_edit) : m_stream(stream)
{
log_window = text_edit;
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~Q_DebugStream()
{
m_stream.rdbuf(m_old_buf);
}
static void registerQDebugMessageHandler(){
qInstallMessageHandler(myQDebugMessageHandler);
}
private:
static void myQDebugMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
{
std::cout << msg.toStdString().c_str();
}
protected:
//This is called when a std::endl has been inserted into the stream
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
log_window->append("");
}
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
QString str(p);
if(str.contains("\n")){
QStringList strSplitted = str.split("\n");
log_window->moveCursor (QTextCursor::End);
log_window->insertPlainText (strSplitted.at(0)); //Index 0 is still on the same old line
for(int i = 1; i < strSplitted.size(); i++){
log_window->append(strSplitted.at(i));
log_window->append("\n");
}
}else{
log_window->moveCursor (QTextCursor::End);
log_window->insertPlainText (str);
log_window->insertPlainText ("\n");
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
QTextEdit* log_window;
};
#endif // Q_DEBUGSTREAM_H
When application is started, I get both messages in my QTextEdit:
"Message from a signal"
"DEBUG MODE ACTIVE"
(This answer extracted from an edit to the question - now rolled back).
Here's how I solved this:
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void logSignal(QString);
public slots:
void logSlot(QString);
private:
void dbgMsg(QString);
QTextEdit *logView;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "q_debugstream.h"
#include <QGridLayout>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *mainWidget = new QWidget(this);
setCentralWidget(mainWidget);
logView = new QTextEdit;
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(logView,0,0,1,1);
mainWidget->setLayout(mainLayout);
connect(this, SIGNAL(logSignal(QString)),
this, SLOT(logSlot(QString)));
emit logSignal("Now call Q_DebugStream");
//Redirect qDebug() output to dbgMsg(QString)
new Q_DebugStream(std::cout, this, &MainWindow::dbgMsg);
Q_DebugStream::registerQDebugMessageHandler();
qDebug() << "Debug message";
qWarning() << "Warning!";
qCritical() << "Critical issue!";
qInfo() << "Information";
qDebug() << "This\nis\na\nlong\none.";
}
MainWindow::~MainWindow(){}
void MainWindow::logSlot(QString log) {
logView->append(log);
}
void MainWindow::dbgMsg(QString log) {
emit logSignal(log);
}
q_debugstream.h
#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QString>
#include "mainwindow.h"
class Q_DebugStream : public std::basic_streambuf<char> {
public:
Q_DebugStream(std::ostream &stream, MainWindow* obj, void (MainWindow::*dbgMsgPtr)(QString log)): m_stream(stream) {
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
msgObj = obj;
msgHandler = dbgMsgPtr;
}
~Q_DebugStream() {
m_stream.rdbuf(m_old_buf);
}
static void registerQDebugMessageHandler() {
qInstallMessageHandler(myQDebugMessageHandler);
}
private:
static void myQDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
QString message = msg;
switch (type) {
case QtDebugMsg:
message.prepend("qDbg(): ");
break;
case QtWarningMsg:
message.prepend("qWarn(): ");
break;
case QtCriticalMsg:
message.prepend("qCrit(): ");
break;
case QtInfoMsg:
message.prepend("qInfo(): ");
break;
case QtFatalMsg:
message.prepend("qFatal(): ");
abort();
break;
}
message.append(" (" + QString::fromUtf8(context.file) + ")");
message.append(" line: " + QString::number(context.line));
std::cout << message.toStdString().c_str();
}
protected:
//This is called when a std::endl has been inserted into the stream
virtual int_type overflow(int_type v) {
if (v == '\n') {
(msgObj->*msgHandler)("\n");
}
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n) {
QString str(p);
if(str.contains("\n")) {
QStringList strSplitted = str.split("\n");
(msgObj->*msgHandler)(strSplitted.at(0)); //Index 0 is still on the same old line
for(int i = 1; i < strSplitted.size(); i++) {
(msgObj->*msgHandler)("\\ " + strSplitted.at(i));
}
} else {
(msgObj->*msgHandler)(str);
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
MainWindow* msgObj;
void (MainWindow::*msgHandler)(QString);
};
#endif // Q_DEBUGSTREAM_H
When application is started, I get these messages in my QTextEdit:
Now call Q_DebugStream
qDbg(): Debug message (..\qDebugFetch\mainwindow.cpp) line: 25
qWarn(): Warning! (..\qDebugFetch\mainwindow.cpp) line: 26
qCrit(): Critical issue! (..\qDebugFetch\mainwindow.cpp) line: 27
qInfo(): Information (..\qDebugFetch\mainwindow.cpp) line: 28
qDbg(): This
\ is
\ a
\ long
\ one. (..\qDebugFetch\mainwindow.cpp) line: 29

QTextEdit promoted to Construct a Console Window

I try to construct a promoted QTextEdit Console widget for my Gui in which i redirect all std::cout. For the redirection i mostly followed this tutorial:
My code looks like this:
myConsoleStream.cpp:
#include "myconsolestream.h"
myConsoleStream::myConsoleStream(std::ostream &stream, QTextEdit* text_edit,QWidget *parent)
:std::basic_streambuf<char>()
,m_stream(stream)
,myConsole(parent)
{
this->log_window = text_edit;
this->m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
myConsoleStream::~myConsoleStream()
{
this->m_stream.rdbuf(this->m_old_buf);
}
void myConsoleStream::registerMyConsoleMessageHandler()
{
qInstallMessageHandler(myConsoleMessageHandler);
}
void myConsoleStream::myConsoleMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
{
std::cout << msg.toStdString().c_str();
}
std::streamsize myConsoleStream::xsputn(const char *p, std::streamsize n)
{
QString str(p);
if(str.contains("\n"))
{
QStringList strSplitted = str.split("\n");
this->log_window->moveCursor (QTextCursor::End);
this->log_window->insertPlainText (strSplitted.at(0)); //Index 0 immer noch auf der alten Zeile
for(int i = 1; i < strSplitted.size(); i++)
{
this->log_window->append(strSplitted.at(i));
}
}
else
{
log_window->moveCursor (QTextCursor::End);
log_window->insertPlainText (str);
}
return n;
}
myConsoleStream.h:
#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QObject>
#include <QWidget>
#include "QTextEdit"
#include <QApplication>
#include "myconsole.h"
class myConsoleStream : public std::basic_streambuf<char>, myConsole
{
public:
myConsoleStream(std::ostream &stream, QTextEdit* text_edit, QWidget *parent);
virtual ~myConsoleStream();
static void registerMyConsoleMessageHandler();
private:
static void myConsoleMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg);
protected:
// Diese Funktion wird aufgerufen wenn std::endl im Stream erscheint
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
log_window->append("");
}
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n);
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
QTextEdit* log_window;
};
#endif // Q_DEBUGSTREAM_H
I tried to make this class a subclass of an additional class to which I promoted the QTextEdit to.Which looks like this:
#include "myconsole.h"
myConsole::myConsole(QWidget *parent)
:QTextEdit(parent)
{
}
myConsole::~myConsole()
{
}
Last but not least my Mainwindow Class looks like this:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBoxLayout>
#include <QTimer>
#include "myconsolestream.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
new myConsoleStream(std::cout, this->ui->Console,this);//Redirect Console output to QTextEdit
myConsoleStream::registerMyConsoleMessageHandler(); //Redirect qDebug() output to QTextEdit
std::cout << "Hallo" << std::endl;
}
MainWindow::~MainWindow()
{
delete ui;
}
If I execute this there appears a second QTextEdit in the left upperhand corner of my Mainwindow, which I dont want to have there. And I cant figure out why this is appearing or where this is created?
Btw I am using qt5.5 and QtCreator for that matter.
It looks like you create your own QTextEdit with the myConsole class and you also redirect your output to this->ui->Console which I guess is created with the UI designer and also an instance of QTextEdit. myConsole in then displayed in the top left of your window because you don't provide it with any layout information and just a parent widget.
To clarifiy, your myConsoleStream is derived from myConsole which in term is derived from QTextEdit, so your myConsoleStream is also an object of type QTextEdit itself.
If you follow the example provided in your link you don't have to create another QTextEdit, if you want to do that you also have to place it in your UI etc..

QT : Memory Leakage and SubClassing (Custom QWidget) Issue

I have an mainwindow app, with 3 main modules and each modules have 6 sub-modules. Each submodel consists of different kind of Gui widgets (like Qlineedit, Qlabel, QPushbutton,QGroupBox etc…).
I would subclass all each main and sub-modules (inheriths QWidget). Each main and sub module is created dynamically. For ex, when the 1st main module is constructed, it also allocates for the 6 submodules. But, when the app is closed, it doesn’t free all 6 submodules. There may be a leakage problem but I didn’t figure out. why. I think I have a problem with subclassing of my modules.
My app is too big to post here so I would post 2 benchmark codes. To show the issue, this mainwindow app has 100 my custom QLineEdit object (I know it is weird but it adresses my problem well). But when the app is closed, doesn’t free all the 100 custom Qlineedit objects. (Here, my custom QLineedit class represents my modules…)
I have tried 2 kind of subclassing to understand the problem. 1. BcInputBox inherits QLineEdit 2. BcInputBox inherits QWidget
I’ve tried both of them separately but the issue is the same. I’ve spent more than 1 week but I haven’t figured it out yet.
Which approach would be better? What is the mistake about my design?
1st Benchmark
// #####################################################
// Benchmark 1 //
// #####################################################
//
//BcInputBox.h
#ifndef BCINPUTBOX_H
#define BBCINPUTBOX_H
#include <QLineEdit>
namespace BC {
const bool ReadOnly = true;
const bool Edit = false;
const bool Double = true;
const bool Name = false;
}
class BcInputBox: public QWidget
{
Q_OBJECT
public:
explicit BcInputBox(QWidget *parent = 0, bool editInfo = BC::Edit, bool inputInfo = BC::Double);
~BcInputBox();
void setEditInfo(bool editInfo);
void setInputInfo(bool inputInfo);
QLineEdit *getInputBox() const;
static int objCounter;
private:
QLineEdit *inputBox;
};
#endif // BCINPUTBOX_H
//******************************************
//BcInputBox.cpp
#include <QDebug>
#include <QHBoxLayout>
#include <QValidator>
#include "BcInputBox.h"
#include "BcDoubleValidator.h"
int BcInputBox :: objCounter = 0;
BcInputBox::BcInputBox(QWidget *parent, bool editInfo, bool inputInfo):QWidget(parent)
{
QHBoxLayout *hlay = new QHBoxLayout(this);
inputBox = new QLineEdit(this);
setEditInfo(editInfo);
setInputInfo(inputInfo);
hlay -> addWidget(inputBox);
inputBox -> setStyleSheet("background-color: yellow;"
"border-radius: 8px;");
qDebug() << objCounter++ << "BcInputBox()";
}
BcInputBox :: ~BcInputBox()
{
//qDebug() << objCounter ;
qDebug() << "~BcInputBox";
delete inputBox;
}
void BcInputBox :: setEditInfo(bool editInfo)
{
inputBox -> setReadOnly(editInfo);
}
void BcInputBox :: setInputInfo(bool inputInfo)
{
if (!inputInfo){
QRegExp rExp ("[A-Za-z0-9]{1,16}");
inputBox -> setValidator(new QRegExpValidator(rExp, inputBox));
}
else {
inputBox -> setValidator( new BcDoubleValidator( 0.0, 1000, 3,inputBox));
}
}
QLineEdit *BcInputBox :: getInputBox() const
{
return inputBox;
}
//******************************************
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include "subconsmod1.h"
#include "BcInputBox.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
BcInputBox *subSection[100];
};
#endif // MAINWINDOW_H
//******************************************
//MainWindow.cpp
#include <QtCore>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout *hlay = new QVBoxLayout(ui->centralWidget);
for (int i = 0; i < 100; ++i ){
subSection[i] = new BcInputBox (ui->centralWidget);
hlay -> addWidget(subSection[i]);}
ui->centralWidget ->setLayout(hlay);
}
MainWindow::~MainWindow()
{
delete ui;
}
2nd Benchmark
// #####################################################
// Benchmark 2 //
// #####################################################
//
//BcInput.h
#ifndef BCINPUT_H
#define BCINPUT_H
#include <QLineEdit>
class BcInput : public QLineEdit
{
Q_OBJECT
public:
explicit BcInput(QWidget *parent = 0);
~BcInput();
static int counter;
signals:
public slots:
};
#endif // BCINPUT_H
//******************************************
//BcInput.cpp
#include <QDebug>
#include "bcinput.h"
int BcInput :: counter = 0;
BcInput::BcInput(QWidget *parent) :
QLineEdit(parent)
{
qDebug() << "BcInput()";
qDebug() << counter++;
}
BcInput :: ~BcInput()
{
qDebug() << "~BcInput()";
}
//******************************************
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "bcinput.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
BcInput *subSection[100];
};
#endif // MAINWINDOW_H
//******************************************
//MainWindow.cpp
#include <QtGui>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "bcinput.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout *hlay = new QVBoxLayout(ui->centralWidget);
for(int i = 0; i<100;i++){
subSection[i] = new BcInput(ui->centralWidget);
hlay->addWidget(subSection[i]);}
ui->centralWidget->setLayout(hlay);
}
MainWindow::~MainWindow()
{
for(int i = 0; i<100;i++)
delete subSection[i];
delete ui;
}