Transferring data from one form to another in Qt? - c++

there was such problem. I have a main and auxiliary form. With the second form, I take two values: the index and the color. I'm transferring to the main form. I get the values ​​in the "setParametr" method. But I can not get them in the "paintEvent" method. QDebug show that the method "setParametr" got the values. When I check the values ​​in "on_pushButton_clicked()" values is 0. What could be the problem. Just started to study Qt
dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
void setcolor(int);
int getcolor();
void setindex(int);
int getindex();
private slots:
void ColorIndex();
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
int squareColor;
int Index;
};
dialog.cpp
#include "ui_dialog.h"
#include "dialog.h"
#include "mainwindow.h"
#include "QDebug"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
//connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(ColorIndex()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::setcolor(int color)
{
squareColor = color;
}
int Dialog::getcolor()
{
return squareColor;
}
void Dialog::setindex(int index)
{
Index = index;
}
int Dialog::getindex()
{
return Index;
}
void Dialog::on_pushButton_clicked()
{
MainWindow *main = new MainWindow();
if(ui->radioButton->isChecked()){
setcolor(1);
}
if(ui->radioButton_2->isChecked()){
setcolor(2);
}
if(ui->radioButton_3->isChecked()){
setcolor(3);
}
if(ui->comboBox->currentIndex()==0)
{
setindex(1);
}
if(ui->comboBox->currentIndex()==1)
{
setindex(2);
}
if(ui->comboBox->currentIndex()==2)
{
setindex(3);
}
if(ui->comboBox->currentIndex()==3)
{
setindex(4);
}
qDebug() << QString::number(getcolor());
qDebug() << QString::number(getindex());
main->SetParametr(getindex(),getcolor());
}
mainwindow.h
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QPainterPath>
#include <QColor>
#include <QColorDialog>
#include <QPushButton>
#include <QMainWindow>
#include "dialog.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setColor(int);
int getColor();
void setIndex(int);
int getIndex();
private:
Dialog *dial = new Dialog();
int fIndex;
int fColor;
private slots:
void on_actionMy_Dialog_triggered();
void paintEvent(QPaintEvent *event);
void on_pushButton_clicked();
signals:
void SetParametr(int index, int color);
private:
Ui::MainWindow *ui;
void onInit();
};
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
#include "dialog.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
fColor = 0;
fIndex =0;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::SetParametr(int index, int color)
{
fIndex = index;
fColor = color;
qDebug() << QString::number(fColor) + "s";
qDebug() << QString::number(fIndex);
}
/*void MainWindow::setColor(int _color)
{
fColor = _color;
}
int MainWindow::getColor()
{
return fColor;
}
void MainWindow::setIndex(int _index)
{
fIndex = _index;
}
int MainWindow::getIndex()
{
return fIndex;
}
*/
void MainWindow::paintEvent(QPaintEvent *event)
{
QColor red1;
if(fColor==1){
red1 = Qt::red;
}
if(fColor == 2){
red1 = Qt::blue;
}
if(fColor == 3){
red1 = Qt::green;
}
int index1;
if(fIndex == 0)
{
index1 = 0;
}
if(fIndex == 1)
{
index1 = 1;
}
if(fIndex == 2)
{
index1 = 2;
}
if(fIndex == 3)
{
index1 = 3;
}
Q_UNUSED(event);
QPainter painter(this);
if(index1 == 0)
{
painter.setBrush(QBrush(red1, Qt::SolidPattern));
painter.drawEllipse(100, 50, 150, 150);
}
if(index1 == 1)
{
painter.setBrush(QBrush(red1, Qt::SolidPattern));
painter.drawRect(50, 50, 250, 150);
}
if(index1 == 2)
{
painter.setBrush(QBrush(red1, Qt::SolidPattern));
QPolygon polygon;
polygon<<QPoint(175,50)<<QPoint(50,200)<<QPoint(300,200);
painter.drawPolygon(polygon);
}
if(index1 == 3)
{
painter.setBrush(QBrush(red1, Qt::SolidPattern));
painter.drawRect(100, 50, 150, 150);
}
}
void MainWindow::on_actionMy_Dialog_triggered()
{
dial->show();
}
void MainWindow::on_pushButton_clicked()
{
qDebug() << QString::number(fColor);
qDebug() << QString::number(fIndex);
}

Related

Segfault on clicking on QFrame

This topic might be little lengthy since I have to explain the premise before procceding with the probleme at hand.Firstly my main goal is to have this application in which the user is capable of drag-n-dropping commands from a toolbar in order to form workflows which are send and executed on a remote server.Currently i am working on the client part in qt and it is driving me nuts.
This is my code:
draglabel.h
#ifndef DRAGLABEL_H
#define DRAGLABEL_H
#include <QLabel>
class QDragEnterEvent;
class QDragMoveEvent;
class QFrame;
class DragLabel : public QLabel
{
public:
DragLabel(const QString &text, QWidget *parent);
QString labelText() const;
private:
QString m_labelText;
};
#endif // DRAGLABEL_H
draglabel.c
#include "draglabel.h"
#include <QtWidgets>
DragLabel::DragLabel(const QString &text, QWidget *parent)
: QLabel(parent)
{
QFontMetrics metric(font());
QSize size = metric.size(Qt::TextSingleLine, text);
QImage image(size.width() + 12, size.height() + 12, QImage::Format_ARGB32_Premultiplied);
image.fill(qRgba(0, 0, 0, 0));
QFont font;
font.setStyleStrategy(QFont::ForceOutline);
QLinearGradient gradient(0, 0, 0, image.height()-1);
gradient.setColorAt(0.0, Qt::white);
gradient.setColorAt(0.2, QColor(200, 200, 255));
gradient.setColorAt(0.8, QColor(200, 200, 255));
gradient.setColorAt(1.0, QColor(127, 127, 200));
QPainter painter;
painter.begin(&image);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(gradient);
painter.drawRoundedRect(QRectF(0.5, 0.5, image.width()-1, image.height()-1),
25, 25, Qt::RelativeSize);
painter.setFont(font);
painter.setBrush(Qt::black);
painter.drawText(QRect(QPoint(6, 6), size), Qt::AlignCenter, text);
painter.end();
setPixmap(QPixmap::fromImage(image));
m_labelText = text;
}
QString DragLabel::labelText() const
{
return m_labelText;
}
dragwidget.h
#ifndef DRAGWIDGET_H
#define DRAGWIDGET_H
#include <QWidget>
#include <QFrame>
#include <vector>
#include <set>
#include "draglabel.h"
using namespace std;
class QDragEnterEvent;
class QDropEvent;
class DragWidget : public QFrame
{
public:
DragWidget(QWidget *parent = nullptr);
void setMode(int desiredMode);
void changePairingMode();
void showAvailableCommands();
void initDrawingLayout();
vector<tuple<QString,QString>> actCommands;
vector<tuple<QString,QString>> execCommands;
vector<pair<int,int>>waitingForPair;
int pairingMode=0;
QFrame*drawingCon;
private:
int widgetMode=1;
protected:
void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE;
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
};
#endif // DRAGWIDGET_H
dragwidget.cpp
#include "draglabel.h"
#include "dragwidget.h"
#include "arrowhead.h"
#include <QtWidgets>
#include <QWidget>
#include <QFrame>
#include <QColor>
#include <tuple>
using namespace std;
static inline QString dndProcMimeType() { return QStringLiteral("application/x-fridgemagnet"); }
DragWidget::DragWidget(QWidget *parent)
: QFrame(parent)
{
drawingCon=new QFrame(this);
QPalette newPalette = palette();
newPalette.setColor(QPalette::Window, Qt::white);
setPalette(newPalette);
setWindowTitle(tr("Drag-and-Drop"));
setMinimumSize(300,300);
setAcceptDrops(true);
setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
drawingCon->setPalette(newPalette);
drawingCon->setWindowTitle(tr("Drag-and-Drop"));
drawingCon->setMinimumSize(350,350);
drawingCon->setAcceptDrops(false);
drawingCon->show();
}
void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(dndProcMimeType())) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void DragWidget::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat(dndProcMimeType())) {
if (children().contains(event->source())) {
if(widgetMode==1)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else {
event->ignore();
}
} else {
if(widgetMode==1)
{
event->acceptProposedAction();
}
else
{
if(widgetMode==1)
{
event->accept();
}
else {
event->ignore();
}
}
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void DragWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(dndProcMimeType())) {
const QMimeData *mime = event->mimeData();
QByteArray itemData = mime->data(dndProcMimeType());
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QString text;
QPoint offset;
dataStream >> text >> offset;
DragLabel *newLabel = new DragLabel(text, this);
newLabel->move(event->pos() - offset);
newLabel->show();
newLabel->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
tuple<QString,QString> addTest;
addTest=make_tuple(text,"");
actCommands.push_back(make_tuple(text,""));
for(auto it:actCommands)
qDebug()<<get<0>(it)<<" "<<get<1>(it);
event->acceptProposedAction();
}
} else {if (event->mimeData()->hasText()) {
if(widgetMode==1)
{
event->accept();
}
else {
event->ignore();
}
event->acceptProposedAction();
}
}
}
void DragWidget::mousePressEvent(QMouseEvent *event)
{
DragLabel *child = static_cast<DragLabel*>(childAt(event->pos()));
if(!pairingMode){
if (!child)
return;
QPoint hotSpot = event->pos() - child->pos();
if(widgetMode==1)
qDebug()<<child->labelText();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << child->labelText() << QPoint(hotSpot);
QMimeData *mimeData = new QMimeData;
mimeData->setData(dndProcMimeType(), itemData);
mimeData->setText(child->labelText());
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(*child->pixmap());
drag->setHotSpot(hotSpot);
child->hide();
if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
child->close();
else {
child->show();
}
}
else {
if(widgetMode==1)
{
DragLabel *child = static_cast<DragLabel*>(childAt(event->pos()));
if (!child)
return;
qDebug()<<"Facem pair cu:"<<child->labelText();
waitingForPair.push_back(make_pair(child->x(),child->y()));
if(waitingForPair.size()==2) {
ArrowHead *line=new ArrowHead(waitingForPair.at(0).first,waitingForPair.at(0).second,waitingForPair.at(1).first,waitingForPair.at(1).second,drawingCon);
line->show();
waitingForPair.erase(waitingForPair.begin(),waitingForPair.begin()+1);
qDebug()<<"Tragem linie";
}
}
}
}
void DragWidget::setMode(int desiredMode)
{
widgetMode=desiredMode;
}
void DragWidget::showAvailableCommands()
{
DragLabel*grep=new DragLabel("grep",this);
grep->move(this->x(),this->y());
grep->show();
DragLabel*cat=new DragLabel("cat",this);
grep->move(this->x()+40,this->y());
cat->show();
DragLabel*wc=new DragLabel("wc",this);
wc->move(this->x()+90,this->y());
wc->show();
}
void DragWidget::changePairingMode()
{
if(pairingMode==1)
pairingMode=0;
else {
pairingMode=1;
}
}
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>
#include "dragwidget.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
protected:
virtual void closeEvent(QCloseEvent *event) override;
private slots:
void handleButton();
void closeAppButton();
void pairButton();
private:
QPushButton *executeCode;
QPushButton *pairCommands;
QPushButton *closeApp;
QTextEdit *inputUser;
QTextEdit *outputServer;
DragWidget * commandLayout=new DragWidget();
DragWidget * availableLayout=new DragWidget();
};
#endif // MAINWINDOW_H
mainWindow.cpp
#include "mainwindow.h"
#include "draglabel.h"
#include "dragwidget.h"
#include <QCoreApplication>
#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QCloseEvent>
#include <QTextEdit>
#include <QFrame>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
executeCode=new QPushButton("Execute");
closeApp=new QPushButton("Close");
pairCommands=new QPushButton("Pair");
connect(closeApp, SIGNAL (released()), this, SLOT (closeAppButton()));
connect(pairCommands, SIGNAL (released()), this, SLOT (pairButton()));
void pairButton();
QHBoxLayout * horizontalLayout=new QHBoxLayout();
commandLayout->setMode(1);
availableLayout->setMode(2);
horizontalLayout->addWidget(commandLayout);
horizontalLayout->addWidget(availableLayout);
availableLayout->showAvailableCommands();
QVBoxLayout*inputBoxes=new QVBoxLayout();
inputUser=new QTextEdit();
outputServer=new QTextEdit();
inputBoxes->addWidget(inputUser);
inputBoxes->addWidget(outputServer);
horizontalLayout->addLayout(inputBoxes);
QVBoxLayout*withButtons=new QVBoxLayout();
withButtons->addLayout(horizontalLayout);
withButtons->addWidget(pairCommands);
withButtons->addWidget(executeCode);
withButtons->addWidget(closeApp);
withButtons->addWidget(new QFrame());
setCentralWidget(new QWidget);
centralWidget()->setLayout(withButtons);
}
void MainWindow::handleButton()
{
}
void MainWindow::closeEvent(QCloseEvent *event)
{
event->accept();
}
void MainWindow::closeAppButton()
{
exit(EXIT_SUCCESS);
}
void MainWindow::pairButton()
{
commandLayout->changePairingMode();
qDebug()<<commandLayout->pairingMode;
}
Note:It might seem idiotic but i have the same class for the "toolbar",from where you're supposed to drag commands and also for part where you are supposed to drag commands and pair them.
This is mostly modified code of the fridge-magnets example on the qt website.
The problem that is giving headaches is drawing lines between dragwidget, I have tried drawing everything in the same QFrame but that proved to be disastrous since the whole pixelMap of the instance dragWidget is overwritten at every draw.The solution with which i came up is to overlay a supplimentary QFrame over my dragWidget in order to draw lines there and everyone to be happy,but as always misfortune strikes at every step.When i am trying to click on the command widget everything's fine but clicking on anything other than a DragLabel results in a segfault due to clicking on the QFrame due to childAt() returning the address of the QFrame overlayed on the first instance of dragWdiget();
My main question is: How can i overcome this obstacle
You should use qobject_cast instead of static_cast.
Add Q_OBJECT macro in each class declaration:
class DragLabel : public QLabel
{
Q_OBJECT
public:
//... class declaration ...
}
class DragWidget : public QFrame
{
Q_OBJECT
public:
//... class declaration ...
}
Then use qobject_cast instead of static_cast for childAt(), for example :
DragLabel *child = qobject_cast<DragLabel*>(childAt(event->pos()));
if(!child){
....
}

How to do (dynamic) offscreen render with QOffscreenSurface in Qt5 correctly?

I am try to do some offscreen rendering jobs in Qt5.3 and I want to use QOpenGLFramebufferObject::toImage to output each pictures(I want to output a few pictures when render() draws different things).
Following the instructions of this, I succeeded in offscreen rendering my first pic and outputing it. So to future on, I write an example as the following code and here is a package in Google. I can get the first fbo content(and its output file correctly, but from the second time, the fbo was not re-render() and it always output the same pictures).
So I want to know what should I do after I finish one time offscreen render to make sure the next time would be correct in qt? Or is there anyone could tell me how to set animation correctly in QOffscreenSurface?
qtestofffscreen.h:
#ifndef QTESTOFFSCREEN_H
#define QTESTOFFSCREEN_H
#include <QOffscreenSurface>
#include <QWindow>
#include <QtGui/QOpenGLFunctions_3_3_Core>
#include <QImage>
#include <QGLFramebufferObject>
#include <QOpenGLPaintDevice>
#include <QOpenGLFunctions>
#include <QMutex>
#include <QMutexLocker>
class QTestOffScreen : public QOffscreenSurface,
protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit QTestOffScreen(
QScreen* targetScreen = nullptr,
const QSize& size = QSize (1, 1));
~QTestOffScreen();
virtual void render();
virtual void initialize();
void renderNow();
void setAnimating(bool animating);
bool event(QEvent *) override;
void renderLater();
int counts;
private:
QGLFramebufferObject *fbo;
bool m_animating;
bool m_update_pending;
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
QSize m_size;
QMutex mutex;
signals:
void doneImg(int index);
};
#endif // QTESTOFFSCREEN_H
qtestofffscreen.cpp:
#include "qtestoffscreen.h"
#include <QTime>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLFramebufferObject>
QTestOffScreen::QTestOffScreen(QScreen *targetScreen,
const QSize &size):
QOffscreenSurface(targetScreen),
m_size(size),
fbo(Q_NULLPTR),
m_context(Q_NULLPTR),
m_device(Q_NULLPTR),
counts(100)
{
requestedFormat().setVersion(3,3);
setFormat(requestedFormat());
create();
m_context = new QOpenGLContext(this);
m_context->setFormat(format());
if (m_context->create())
{
m_context->makeCurrent(this);
m_context->functions()->initializeOpenGLFunctions();
}else
{
delete m_context;
m_context = Q_NULLPTR;
throw ("Still wrong here");
}
//To make sure m_context was initialized
//in first time entering renderNow()
delete m_context;
m_context = Q_NULLPTR;
}
QTestOffScreen::~QTestOffScreen()
{
delete m_context;
delete m_device;
if (fbo)
delete fbo;
}
void QTestOffScreen::render()
{
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
| GL_TEXTURE_BIT);
glViewport(0,0,1920,1080);
glOrtho(0,1920,0,1080,0,1);
glColor3f(1.0,0.0,0.0);
float tmp = float(qrand()%1000);
float count = (float)counts * 10.0f;
glLineWidth(3.0f);
glBegin(GL_LINE_LOOP);
glVertex2f(count ,count );
glVertex2f(count + 100,count);
glVertex2f(count + 50,count + 100);
glEnd();
qDebug()<<QString("current tmp is %1").arg(count);
}
void QTestOffScreen::initialize()
{
if (!fbo)
{
fbo = new QGLFramebufferObject(1920,1080,GL_TEXTURE_2D);
}
fbo->bind();
}
void QTestOffScreen::renderNow()
{
bool needsInitialize = false;
if (!m_context)
{
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
if (m_context->isValid())
{
qDebug()<<"Right Here when creating m_context in renderNow";
}
needsInitialize = true;
}
if ( !m_context->makeCurrent(this) )
{
qDebug()<<"This fails in makeCurrent";
}
if (needsInitialize)
{
initializeOpenGLFunctions();
initialize();
}
render();
qDebug()<<counts;
counts--;
fbo->toImage().save(QString::number(counts) + QString(".png"));
m_context->doneCurrent();
if (counts >= 0)
{
m_update_pending = false;
emit doneImg(counts);
}
}
void QTestOffScreen::setAnimating(bool animating)
{
m_animating = animating;
m_update_pending = false;
if (m_animating)
renderLater();
}
bool QTestOffScreen::event(QEvent *event)
{
switch (event->type())
{
case QEvent::UpdateRequest:
m_update_pending = true;
renderNow();
return true;
default:
return QOffscreenSurface::event(event);
}
}
void QTestOffScreen::renderLater()
{
if (!m_update_pending)
{
m_update_pending = true;
QCoreApplication::postEvent(this,new QEvent(QEvent::UpdateRequest));
}
}
void QTestOffScreen::generateImg(QImage *tmp_img_pointer)
{
GLint viewPort[4]={0};
glGetIntegerv(GL_VIEWPORT,viewPort);
int win_width,win_height;
win_width = 1920;
win_height = 1080;
GLubyte *colorArr=new GLubyte[win_width*win_height*3];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadBuffer (GL_FRONT);
int tmp_x,tmp_y;
tmp_x = 0;
tmp_y = 0;
glReadPixels(tmp_x,tmp_y,win_width,win_height,
GL_RGB,GL_UNSIGNED_BYTE,colorArr);
int winrows = tmp_img_pointer->height();
int wincols = tmp_img_pointer->width ();
for(int ii=0; ii < winrows * wincols * 3; ii ++)
{
if((colorArr[ii] <0)|(colorArr[ii] >255))
{ colorArr[ii] = 255; }
}
for(int j=0;j<winrows;j++)
for(int i=0;i<wincols;i++)
{
int index=(j*wincols+i)*3;
QRgb value=qRgb(colorArr[index+2],
colorArr[index+1],
colorArr[index ]);
tmp_img_pointer->setPixel(i,winrows-j-1,value);
}
delete colorArr;
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qtestoffscreen.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QTestOffScreen *scr;
private slots:
void ReceiveCurrentIndex(int);
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSurfaceFormat format;
format.setSamples(1);
format.setRenderableType(QSurfaceFormat::OpenGL);
scr = new QTestOffScreen();
connect(scr,SIGNAL(doneImg(int)),this,SLOT(ReceiveCurrentIndex(int)));
scr->setFormat(format);
scr->setAnimating(true);//Start rendering animation here.
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ReceiveCurrentIndex(int)
{
Sleep(100);
scr->renderLater();
}

Qt Unresolved External Symbol

I have classes, ImageLabel, and ChoiceLabel. ChoiceLabel inherits from ImageLabel. When I try to make a new ChoiceLabel, I get an Unresolved External Symbol error. Here are the relevant files:
imagelabel.h
#ifndef IMAGELABEL_H
#define IMAGELABEL_H
#include <QLabel>
class QPixmap;
class QStringList;
class QFileDialog;
class QResizeEvent;
class ImageLabel : public QLabel
{
Q_OBJECT
public:
explicit ImageLabel(QWidget *parent = 0);
protected:
virtual int heightForWidth( int width ) const;
virtual QSize sizeHint() const;
QPixmap scaledPixmap() const;
void setPixmap ( const QPixmap & );
void resizeEvent(QResizeEvent *);
private:
QPixmap pix;
};
#endif // IMAGELABEL_H
choicelabel.h
#ifndef CHOICELABEL_H
#define CHOICELABEL_H
class QStringList;
class ChoiceLabel : public ImageLabel
{
Q_OBJECT
public:
ChoiceLabel();
private:
QStringList *imageFiles;
void mousePressEvent(QMouseEvent *);
void keyPressEvent(QKeyEvent *);
void focusInEvent(QFocusEvent *);
void focusOutEvent(QFocusEvent *);
};
#endif // CHOICELABEL_H
mainwindow.cpp
#include "mainwindow.h"
#include "imagelabel.h"
#include "choicelabel.h"
#include <QGridLayout>
#include <qDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
choiceLabelA = new ChoiceLabel; //the problem occurs here
resultLabel = new ImageLabel;
centralWidget = new QWidget(this);
this->setCentralWidget(centralWidget);
gridLayout = new QGridLayout(centralWidget);
gridLayout->addWidget(resultLabel);
}
EDIT:
imagelabel.cpp
#include "imagelabel.h"
#include <QDebug>
ImageLabel::ImageLabel(QWidget *parent) :
QLabel(parent)
{
setMinimumSize(250,250);
setAlignment(Qt::AlignCenter | Qt::AlignCenter);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
QPixmap initialPixmap(250, 250);
initialPixmap.fill(Qt::black);
setPixmap(initialPixmap);
}
void ImageLabel::setPixmap ( const QPixmap & p)
{
pix = p;
QLabel::setPixmap(scaledPixmap());
}
QPixmap ImageLabel::scaledPixmap() const
{
return pix.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
int ImageLabel::heightForWidth( int width ) const
{
return pix.isNull() ? this->height() : ((qreal)pix.height()*width)/pix.width();
}
QSize ImageLabel::sizeHint() const
{
int w = this->width();
return QSize( w, heightForWidth(w) );
}
void ImageLabel::resizeEvent(QResizeEvent *)
{
if(!pix.isNull())
QLabel::setPixmap(scaledPixmap());
}
choicelabel.cpp
#include "choicelabel.h"
#include <QStringList>
#include <QFileDialog>
#include <QFrame>
ChoiceLabel::ChoiceLabel():
imageFiles()
{
setFocusPolicy(Qt::StrongFocus);
}
void ChoiceLabel::mousePressEvent(QMouseEvent *)
{
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::ExistingFiles);
dialog.setNameFilter("Images (*.png *.jpg)");
dialog.setDirectory("C:/Users/FrankFritz/Desktop/qt/uglypictures");
if (dialog.exec()){
imageFiles = dialog.selectedFiles();
QPixmap pixmap = imageFiles->first();
setPixmap(pixmap);
}
}
void ChoiceLabel::keyPressEvent(QKeyEvent *ev)
{
static int index(0);
if (ev->key() == Qt::Key_Right){
index = (index + 1) % imageFiles->length();
setPixmap( QPixmap(imageFiles->at(index)) );
}
if (ev->key() == Qt::Key_Left){
if (index == 0){
index = imageFiles->length() - 1;
}
else{
index = (index - 1) % imageFiles->length();
}
setPixmap( QPixmap(imageFiles->at(index)) );
}
}
void ChoiceLabel::focusInEvent(QFocusEvent *)
{
setFrameStyle(QFrame::StyledPanel);
}
void ChoiceLabel::focusOutEvent(QFocusEvent *)
{
setFrameStyle(QFrame::NoFrame);
}
Most probably
ChoiceLabel::ChoiceLabel():
imageFiles()
{
setFocusPolicy(Qt::StrongFocus);
}
ChoiceLabel::ChoiceLabel(QWidget *parent): ImageLabel(parent)
{
setFocusPolicy(Qt::StrongFocus);
}
Forgot to call the base class' constructor. Also forgot to specify a parent QWidget * for ChoiceLabel in its own constructor.
See What are the rules for calling the superclass constructor? for reference.

Increasing cpu and ram usage while calling update for multiple QSGNodes

I create an application with Qt Scene Graph (Qt 5.6 on Ubuntu 16.04). It has about 12 instances of QSGNodes and calls update for them every 30ms.
I don't have any problem with updating one of them, but when i call update for all of them, cpu and ram usage began to increase. After some hours cpu usage will be near 100%. (under normal conditions cpu usage should be around 3-4).
Here is minimal version(Sorry for long code, It's simplest version that produces this bug):
main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "gui/diagramgraph.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QQuickView>
#include <QTimer>
#include "gui/diagramgraph.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qmlRegisterType<DiagramGraph>("DiagramGraph", 1, 0, "DiagramGraph");
QTimer *updateTimer = new QTimer(this);
for(int i = 1; i <= 12; i++){
QQuickView *view = new QQuickView();
view->setSource(QUrl("qrc:/ui/diagram.qml"));
view->setClearBeforeRendering(true);
QObject *object = view->rootObject();
DiagramGraph* graph = object->findChild<DiagramGraph *>("diagram");
QObject::connect(updateTimer, SIGNAL(timeout()), graph, SLOT(update()));
QWidget *container = QWidget::createWindowContainer(view, this);
ui->vetical->addWidget(container);
}
updateTimer->setTimerType(Qt::PreciseTimer);
updateTimer->start(30);
}
MainWindow::~MainWindow()
{
delete ui;
}
gui/diagramgraph.h
#ifndef DIAGRAMGRAPH_H
#define DIAGRAMGRAPH_H
#include <QQuickItem>
class DiagramGraph : public QQuickItem
{
Q_OBJECT
public:
DiagramGraph();
void init();
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
};
#endif // DIAGRAMGRAPH_H
gui/diagramgraph.cpp
#include "samples.h"
#include "diagramgraph.h"
class DiagramGraphNode : public QSGNode
{
public:
Samples * samples;
};
DiagramGraph::DiagramGraph()
{
setFlag(ItemHasContents, true);
}
QSGNode * DiagramGraph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
DiagramGraphNode *n= static_cast<DiagramGraphNode *>(oldNode);
QRectF rect = boundingRect();
if (rect.isEmpty()) {
delete n;
return 0;
}
if (!n) {
n = new DiagramGraphNode();
n->samples = new Samples();
n->appendChildNode(n->samples);
}
n->samples->updateGeometry();
return n;
}
void DiagramGraph::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry){
update();
QQuickItem::geometryChanged(newGeometry, oldGeometry);
}
gui/samples.h
#ifndef SAMPLES_H
#define SAMPLES_H
#include <QSGGeometryNode>
class Samples : public QSGGeometryNode
{
public:
Samples();
void updateGeometry();
private:
QSGGeometry _geometry;
};
#endif // SAMPLES_H
gui/samples.cpp
#include "samples.h"
#include <QtGui/QColor>
#include <QtQuick/QSGSimpleMaterial>
struct LineMaterial
{
QColor color;
};
class LineShader : public QSGSimpleMaterialShader<LineMaterial>
{
QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial)
public:
LineShader() {
setShaderSourceFile(QOpenGLShader::Vertex, ":/shaders/shaders/samples.vsh");
setShaderSourceFile(QOpenGLShader::Fragment, ":/shaders/shaders/samples.fsh");
}
QList<QByteArray> attributes() const { return QList<QByteArray>() << "y" << "t"; }
void updateState(const LineMaterial *m, const LineMaterial *) {
program()->setUniformValue(id_color, m->color);
}
void resolveUniforms() {
id_color = program()->uniformLocation("color");
}
private:
int id_color;
};
struct Vertex {
float y;
float t;
inline void set(float yy, float tt) { y = yy; t = tt; }
};
static const QSGGeometry::AttributeSet &attributes()
{
static QSGGeometry::Attribute attr[] = {
QSGGeometry::Attribute::create(0, 1, GL_FLOAT, true),
QSGGeometry::Attribute::create(1, 1, GL_FLOAT),
};
static QSGGeometry::AttributeSet set = { 2, 2 * sizeof(float), attr };
return set;
}
Samples::Samples()
: _geometry(attributes(), 0){
setGeometry(&_geometry);
_geometry.setLineWidth(3);
_geometry.setDrawingMode(GL_LINES);
QSGSimpleMaterial<LineMaterial> *m = LineShader::createMaterial();
m->state()->color = QColor("red");
m->setFlag(QSGMaterial::Blending);
setMaterial(m);
setFlag(OwnsMaterial);
}
void Samples::updateGeometry()
{
_geometry.allocate(20);
Vertex *v = (Vertex *) _geometry.vertexData();
for (uint i=0; i < 20; i++){
v[i].set(.5, i);
}
}
mainwindow.ui
just a QVBoxLayout
diagram.qml
import QtQuick 2.0
import QtQuick.Controls 1.4
import DiagramGraph 1.0
Item{
id: diagram_main
DiagramGraph{
id: diagram_graph
objectName: "diagram"
anchors.left: diagram_main.left
height: 100
}
}
shaders/samples.fsh
uniform lowp vec4 color;
uniform lowp float qt_Opacity;
void main(void)
{
gl_FragColor = color * qt_Opacity;
}
shaders/samples.vsh
attribute highp float y;
attribute highp float t;
uniform highp mat4 qt_Matrix;
void main(void)
{
gl_Position = qt_Matrix * vec4(t, y * 100.f, 0.f, 1.f);
}

Adding Text in GraphicsView in Qt

I am implementing a code to add different entities on a button click.I am getting a problem to add Text in graphics view. Following is the code snippet that I am implementing. What needs to be done?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPaintEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPainter>
#include "line.h"
#include "circle.h"
#include "ellipse.h"
#include "point.h"
#include "arc.h"
#include "text.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void wheelEvent(QWheelEvent* event);
private:
Ui::MainWindow *ui;
bool mFirstClick;
bool mPaintFlag;
int mStartX;
int mStartY;
int mEndX;
int mEndY;
QGraphicsScene *scene;
QPainter *painter;
point *item;
line *item1;
circle *item2;
ellipse *item3;
arc *item4;
private slots:
void drawPoint();
void drawLine();
void drawCircle();
void drawEllipse();
void drawArc();
void drawText();
void on_actionSave_triggered();
void on_actionOpen_triggered();
void on_actionQuit_2_triggered();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
#include<QFileDialog>
#include<QMessageBox>
#include<QTextEdit>
#include<QString>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("GD CAD"));
scene = new QGraphicsScene;
for(int x = 0; x <= ui->graphicsView->width(); x += 10){
scene->addLine(x,0,x,ui->graphicsView->height(),QPen(Qt::green));
}
for(int y = 0; y <= ui->graphicsView->height(); y += 10){
scene->addLine(0,y,ui->graphicsView->width(),y,QPen(Qt::green));
}
for(int x = 10; x <= ui->graphicsView->width(); x += 100){
scene->addLine(x,0,x,ui->graphicsView->height(),QPen(Qt::darkGreen));
}
for(int y = 10; y <= ui->graphicsView->height(); y += 100){
scene->addLine(0,y,ui->graphicsView->width(),y,QPen(Qt::darkGreen));
}
ui->graphicsView->setScene(scene);
connect(ui->pointButton, SIGNAL(clicked()), this, SLOT(drawPoint()));
connect(ui->lineButton, SIGNAL(clicked()), this, SLOT(drawLine()));
connect(ui->circleButton, SIGNAL(clicked()), this, SLOT(drawCircle()));
connect(ui->ellipseButton, SIGNAL(clicked()), this, SLOT(drawEllipse()));
connect(ui->arcButton, SIGNAL(clicked()),this, SLOT(drawArc()));
connect(ui->text,SIGNAL(clicked()),this,SLOT(drawText()));
connect(ui->actionPoints, SIGNAL(triggered()), this, SLOT(drawPoint()));
connect(ui->actionLine, SIGNAL(triggered()), this, SLOT(drawLine()));
connect(ui->actionCircle, SIGNAL(triggered()), this, SLOT(drawCircle()));
connect(ui->actionEllipse, SIGNAL(triggered()), this, SLOT(drawEllipse()));
}
void MainWindow::drawPoint(){
ui->graphicsView->setScene(scene);
item = new point;
scene->addItem(item);
qDebug() << "Point Created";
connect(item, SIGNAL(DrawFinished()), this, SLOT(drawPoint()));
}
void MainWindow::drawLine(){
ui->graphicsView->setScene(scene);
item1 = new line;
scene->addItem(item1);
qDebug() << "Line Created";
connect(item1, SIGNAL(DrawFinished()), this, SLOT(drawLine()));
}
void MainWindow::drawCircle(){
ui->graphicsView->setScene(scene);
item2 = new circle;
scene->addItem(item2);
qDebug() << "Circle Created";
connect(item2, SIGNAL(DrawFinished()), this, SLOT(drawCircle()));
}
void MainWindow::drawArc(){
ui->graphicsView->setScene(scene);
item4 = new arc;
scene->addItem(item4);
qDebug() << "Circle Created";
connect(item4, SIGNAL(DrawFinished()), this, SLOT(drawArc()));
}
void MainWindow::drawEllipse(){
ui->graphicsView->setScene(scene);
item3 = new ellipse;
scene->addItem(item3);
qDebug() << "Ellipse Created";
connect(item3, SIGNAL(DrawFinished()), this, SLOT(drawEllipse()));
}
void MainWindow::wheelEvent(QWheelEvent* event) {
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
// Scale the view / do the zoom
double scaleFactor = 1.15;
if(event->delta() > 0) {
// Zoom in
ui->graphicsView->scale(scaleFactor, scaleFactor);
} else {
// Zooming out
ui->graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
}
void MainWindow::on_actionOpen_triggered()
{
QString filename=QFileDialog::getOpenFileName(
this,
tr("Open File"),
QString(),
tr("file Name(*.dwg|*.DWG|*.dxf)")
);
if (!filename.isEmpty()) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this,
tr("Error"), tr("Could not open file"));
return;
}
}
}
void MainWindow::on_actionSave_triggered()
{
QString filename=QFileDialog::getSaveFileName(
this,
tr("Save File"),
QString(),
tr("file Name(*.txt)")
);
if(!filename.isEmpty()) {
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
return;
} else {
QTextStream stream(&file);
QTextEdit *textEdit;
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
}
void MainWindow::on_actionQuit_2_triggered(){
MainWindow *window;
window->close();
}
void MainWindow::drawText(){
ui->graphicsView->setScene(scene);
text *item5 = new text;
scene->addItem(item5);
qDebug() << "text created";
connect(item5, SIGNAL(DrawFinished()), this, SLOT(drawText()));
}
MainWindow::~MainWindow()
{
delete ui;
}
text.h
#ifndef TEXT_H
#define TEXT_H
#include <QGraphicsTextItem>
#include <QPen>
#include<QFocusEvent>
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsSceneMouseEvent>
#include<QGraphicsTextItem>
#include<QFont>
#include"mainwindow.h"
#include"ui_mainwindow.h"
class text:public QGraphicsTextItem
{
Q_OBJECT
public:
enum { Type = UserType + 3 };
enum Mode { InsertText };
void setFont(const QFont &font);
text(QGraphicsItem *parent = 0);
int type() const { return Type; }
public slots:
void setMode(Mode mode);
signals:
void lostFocus(text *item);
void selectedChange(QGraphicsItem *item);
void textInserted(QGraphicsTextItem *item);
void itemSelected(QGraphicsItem *item);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void focusOutEvent(QFocusEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
Mode myMode;
QFont myFont;};
#endif // TEXT_H
text.cpp
#include "text.h"
#include"mainwindow.h"
#include"ui_mainwindow.h"
text::text(QGraphicsItem *parent):QGraphicsTextItem(parent)
{
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
}
QVariant text::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
emit selectedChange(this);
return value;
}
void text::focusOutEvent(QFocusEvent *event)
{
setTextInteractionFlags(Qt::NoTextInteraction);
emit lostFocus(this);
QGraphicsTextItem::focusOutEvent(event);
}
void text::setMode(Mode mode)
{
myMode = mode;
}
void text::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (textInteractionFlags() == Qt::NoTextInteraction)
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(event);
}
void text::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
switch(myMode){
case InsertText:
text *textItem;
textItem = new text();
// textItem->setFont(myFont);
textItem->setPlainText("hello");
textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
textItem->setZValue(1000.0);
connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)),
this, SLOT(editorLostFocus(DiagramTextItem*)));
connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
this, SIGNAL(itemSelected(QGraphicsItem*)));
//addItem(textItem);
// textItem->setDefaultTextColor(myTextColor);
textItem->setPos(mouseEvent->scenePos());
emit textInserted(textItem);
//! [8] //! [9]
default:
;
}
// QGraphicsScene::mousePressEvent(mouseEvent);
}
Hm, if i am not mistaken, it does look like you are setting all kinds of properties of the text item, like Interaction-flags, z-value, color and so on -- everything but not the actual text. The text would be empty and therefore your QGraphicsTextItem will be invisible.
Use setPlainText(), setHtml() or setDocument() on your text item.
There are two places where text-items are created; one is in the mainwindow.cpp:
void MainWindow::drawText(){
ui->graphicsView->setScene(scene);
text *item5 = new text;
scene->addItem(item5);
qDebug() << "text created";
connect(item5, SIGNAL(DrawFinished()), this, SLOT(drawText()));
}
The text is created and added to the scene (with addItem()), but it does not have an actual content; set its content:
item5->setPlainText ("Mickey");
The second text-item is created from inside the text (which is a subclass of a QGraphicsTextItem) class itself:
void text::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
...
switch(myMode){
case InsertText:
text *textItem;
textItem = new text();
// textItem->setFont(myFont);
textItem->setPlainText("hello");
It is created correctly, and given a text, but not added to the scene. Add it to the scene, for instance by making it a child of the current text item:
textItem->setParentItem (this);