Qt slot, no matching function for call - c++

I'm quite new to Qt. I wanted to create a simple application where there's triangle generated using OpenGL and three push buttons changing that triangle colour.
Here's my code:
In MainWindow.h I declare slots:
public slots:
void redButton(Widget w);
void greenButton(Widget w);
void blueButton(Widget w);
They change colour using function in Widget class:
void MainWindow::redButton(Widget w)
{
w.setColor(red);
}
In widget.h I have:
class Widget : public QGLWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
QSize minimumSizeHint() const;
QSize sizeHint() const;
enum color
{
red,
green,
blue
};
enum color c;
void setColor(enum color color1);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
};
And function setColor looks like this:
void Widget::setColor(enum color color1)
{
c = color1;
}
Unfortunately I get an error saying:
no matching function forr call to 'Widget::setColor(QPushButton*&)'
w.setColor(red);
//Same goes for blue and green
I don't know what I'm doing wrong.

Well, your function declaration
void Widget::setColor(enum color color1);
obviously doesn't match your calls for
void Widget::setColor(QPushButton*&);
Certainly none of those QPushButton instances, establishes a valid instance of enum color, thus you get those compiler errors.

Related

Is it possible torender Qt QWidgets and QML using custom graphics engine?

I have some project where I'm interested in using of QML ui.
But it is not enough for us to use standart Qt rendering sistem, I must try to repaint all ui elements every frame, not only in QCoreApplication::processEvents().
It's requered because it is some DirectX render in background of ui.
In this case I found the way to render widgets only using QWidget::render() function, but this method uses CPU instead of GPU, so it is too slow and is't correct at all.
So, what I have:
I have QApplication integrated into my application's loop.
Signals/Slots system works fine and process events is called right
way.
Own render system with DirectX11, that i use to render other
graphics.
I need redraw (update) qt (QML) ui every frame using
DirectX, or maybe angle, but every frame of render.
Already existing code example:
In this example reimplemented widget is app's main window and used like context of DirectX render.
header:
#ifndef _QTD3DCONTEXTWIDGET_
#define _QTD3DCONTEXTWIDGET_
#include <QtWidgets/QWidget>
#include <QtQuick/QQuickView>
#include <QtQuickWidgets/QQuickWidget>
#include <QtQml/qqml.h>
#include <QtWidgets/QPushButton>
#include <QtGui/QPaintEngine>
#include <QtGui/QPaintDevice>
class QtGfxPaintEngine : public QPaintEngine
{
public:
QtGfxPaintEngine(PaintEngineFeatures caps = PaintEngineFeatures());
virtual bool begin(QPaintDevice *pdev);
virtual bool end();
//virtual void drawEllipse(const QRectF &rect);
//virtual void drawEllipse(const QRect &rect);
virtual void drawImage(const QRectF &rectangle,
const QImage &image,
const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
virtual void drawPoints(const QPointF *points, int pointCount);
virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
virtual void drawRects(const QRectF *rects, int rectCount);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
virtual void drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p);
// default implementation used
//virtual void drawLines(const QLineF *lines, int lineCount); //not
//virtual void drawLines(const QLine *lines, int lineCount);
//virtual void drawPath(const QPainterPath &path);
//virtual void drawPoints(const QPoint *points, int pointCount);
//virtual void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
//virtual void drawRects(const QRect *rects, int rectCount);
virtual Type type() const;
virtual void updateState(const QPaintEngineState &newState);
private:
int getClosestPowOfTwo(QSize& size);
};
class QtD3DContextWidget : public QWidget
{
Q_OBJECT
public:
QtD3DContextWidget(QWidget* parent = nullptr);
virtual ~QtD3DContextWidget() = default;
virtual QPaintEngine* paintEngine() const;
virtual void paintEvent(QPaintEvent* event);
void mousePressEvent(QMouseEvent *event) override;
QQuickWidget* containerWidget;
QPushButton* widg;
QtGfxPaintEngine* mPaintEngine;
private:
};
#endif // !_QTD3DCONTEXTWIDGET_
cpp, without draw functions (they are implemented with DirectX and works fine):
QtD3DContextWidget::QtD3DContextWidget(QWidget* parent /*= nullptr*/)
: QWidget(parent, Qt::MSWindowsOwnDC)
{
mPaintEngine = new QtGfxPaintEngine(QPaintEngine::AllFeatures);
QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
setAttribute(Qt::WA_NativeWindow, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_UpdatesDisabled, true);
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_OpaquePaintEvent, true);
containerWidget = new QQuickWidget(this);
containerWidget->setAttribute(Qt::WA_TranslucentBackground, true);
containerWidget->setAttribute(Qt::WA_OpaquePaintEvent, true);
containerWidget->setAttribute(Qt::WA_NoSystemBackground, true);
containerWidget->setClearColor(Qt::transparent);
QString sourceUi = QCoreApplication::applicationDirPath() + "/qtui/test.qml";
containerWidget->setSource(QUrl::fromLocalFile(sourceUi));
containerWidget->move(0, 0);
resize(1280, 720);
widg = new QPushButton("test", this);
//widg->setBackgroundRole(QPalette::WindowText);
widg->resize(50, 50);
widg->move(600, 300);
widg->show();
show();
setVisible(true);
//wrapper->show();
}
QPaintEngine* QtD3DContextWidget::paintEngine() const
{
return mPaintEngine;
}
void QtD3DContextWidget::paintEvent(QPaintEvent* event)
{
}
QtGfxPaintEngine::QtGfxPaintEngine(PaintEngineFeatures caps /*= PaintEngineFeatures()*/)
: QPaintEngine(caps)
{}
QPaintEngine::Type QtGfxPaintEngine::type() const
{
return QPaintEngine::Direct3D;
}
void QtGfxPaintEngine::updateState(const QPaintEngineState &newState)
{}
and in render ui method:
QPainter painter(w);
painter.setBrushOrigin(w->containerWidget->pos());
w->containerWidget->render(&painter);// , w->widg->pos());// , w->widg->rect());// , QWidget::DrawChildren);
painter.end();
that's works fine but using CPU.
What i try it's to replace it with
w->repaint();
so entire widget is repainted, but not every frame, and in this case ui is "blinking" and widget try to repain it's background not as transparent, but with white color.
Or replace with
w->containerWidget->repaint();
and nothing is happends.
trying to call QApplication::process events just after w->repaint() don't make sence, as i can see.
and ofcourse i have comented setAttribute(Qt::WA_UpdatesDisabled, true); if i try to refresh widget in this manner.
PS: sorry for my english)))
If you want to render all Qt content through a central renderer then you might be better of implementing your own QPA (Qt Platform Abstraction) plugin, based on or derived from the normal Windows QPA plugin.
Then you can (a) handout your paint device implementation from there and not need any application side code and potentially use something like ANGLE to get the QtQuick scene graph rendered via Direct3D

QGraphicsView issue

I dont understand what`s going on: when i create QGraphicsView object directly and adding scene with a pixmap, all is ok, pixmap appears on the screen:
scene.addPixmap(pix);
QGraphicsView graphicsView;
graphicsView.setScene(&scene);
But when i try to inherit QGraphicsView class with purpose of reimplementing events, nothing happend and i got white screen without pixmap, but events like changing cursor is working:
scene.addPixmap(pix);
DrawArea graphicsView;
graphicsView.setScene(&scene);
.h file:
class DrawArea : public QGraphicsView
{
Q_OBJECT
public:
DrawArea(QWidget *parent = 0);
~DrawArea();
signals:
public slots:
void mousePressEvent(QMouseEvent * e);
void paintEvent(QPaintEvent *);
void enterEvent(QEvent *e);
private:
QPoint coord;
};
.cpp file:
DrawArea::DrawArea(QWidget *parent)
: QGraphicsView(parent){
}
DrawArea::~DrawArea(){
}
void DrawArea::mousePressEvent(QMouseEvent * event){
}
void DrawArea::paintEvent(QPaintEvent *event){
}
void DrawArea::enterEvent(QEvent *event){
viewport()->setCursor(Qt::CrossCursor);
}
Tell me if something missed, Thanks in advance.
You should process your events. Try this:
void DrawArea::mousePressEvent(QMouseEvent * event)
{
//some actions
QGraphicsView::mousePressEvent(event);
}
void DrawArea::paintEvent(QPaintEvent *event)
{
//some actions
QGraphicsView::paintEvent(event);
}
Also I think that you don't need paintEvent at all, do all needed things in the scene.

Qt, using OpenGL, QGLWidget is private

I'm quite new to Qt. I wanted to create a simple application where there's triangle generated using OpenGL and three push buttons changing that triangle colour. Unfortunately I get an error:
E:\Programy\Qt\5.3\mingw482_32\include\QtOpenGL\qgl.h:457: error: 'QGLWidget::QGLWidget(const QGLWidget&)' is private
Q_DISABLE_COPY(QGLWidget)
I don't know what to do. Here's my code:
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
QVBoxLayout *layout;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QPushButton *redButton;
QPushButton *greenButton;
QPushButton *blueButton;
public slots:
void redSlot(Widget w);
void greenSlot(Widget w);
void blueSlot(Widget w);
};
Slots in MainWindow.cpp look like this:
void MainWindow::redSlot(Widget w)
{
w.setColor(red);
}
Widget.h
class Widget : public QGLWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
QSize minimumSizeHint() const;
QSize sizeHint() const;
enum color c;
void setColor(enum color color1);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
};
enum color is just an enum declared ina another header file
enum color
{
red,
green,
blue
};
Your Slots
void redSlot(Widget w);
void greenSlot(Widget w);
void blueSlot(Widget w);
all take a Parameter of Type Widget. This tries to create a copy of the object when called. Your Widget is a subclass of QGLWidget which has a private copy constructor and therefore can't be called from a subclassed object.
As you want to change the color of an existing object and not a copy of it you should change the functions to take a pointer of that object:
void redSlot(Widget*);
void greenSlot(Widget*);
void blueSlot(Widget*);
void MainWindow::redSlot(Widget* w)
{
w->setColor(red);
}

Qt connect itemDoubleClicked to self-defined slot

I have the following class that extends QListWidget, but I can't seem to connect the doubleClicked signal to the slot I desire. Here's the code implemented - in VS2012. The idea is to be able to double click a item and edit it. I connect the signal to the slot in the constructor, but the slot is never called when I run it through the debugger.
# .h file
class DisplayFeed :
public QListWidget
{
Q_OBJECT
public:
DisplayFeed(QWidget *parent, Logic *logic, int xpos, int ypos, int width, int height, std::string color);
~DisplayFeed(void);
void setColor(std::string color);
void refresh(std::vector<Event*> *thingsToInclude);
private:
Logic* logic;
private slots:
void editItem(QEventStore *item);
};
Below is the .cpp file. QEventStore extends QListWidgetItem. I placed the MessageBox to test the system as well, in case it was my other code that didn't work.
# .cpp file, only relevant methods included
DisplayFeed::DisplayFeed(QWidget *parent, Logic *logic, int xpos, int ypos, int width, int height, std::string color)
: QListWidget(parent)
{
this->logic = logic;
setGeometry(xpos, ypos, width, height);
setColor(color);
QObject::connect(this, SIGNAL(itemClicked(QEventStore*)), this, SLOT(editItem(QEventStore*)));
show();
}
void DisplayFeed::editItem(QEventStore *item){
QMessageBox::information(this,"Hello!","You clicked \""+item->text()+"\"");
QEventEditor *editor = new QEventEditor(item->getEvent());
}
You forgot the Q_OBJECT macro in your DisplayFeed class. It should be like :
# .h file
class DisplayFeed :
public QListWidget
{
Q_OBJECT
public:
DisplayFeed(QWidget *parent, Logic *logic, int xpos, int ypos, int width, int height, std::string color);
~DisplayFeed(void);
void setColor(std::string color);
void refresh(std::vector<Event*> *thingsToInclude);
private:
Logic* logic;
private slots:
void editItem(QEventStore *item);
};
That's the first thing I noticed and may solve your problem. If not I'll look deeper.
EDIT: Read the first answer here
There are several changes to do:
Add Q_OBJECT in the .h of displayFeed class
class DisplayFeed : public QListWidget
{
Q_OBJECT
...
};
Change your slot with a public slot and a QListWidgetItem* parameter
public slots:
void editItem(QListWidgetItem *item);
Connect with the good SIGNAL which have the same parameter that your SLOT
connect(this,SIGNAL(itemDoubleClicked(QListWidgetItem*)), this,SLOT(editItem(QListWidgetItem*)));
This works fine for me, hope it helps you.
I have found the answer. The problem is that the default signal for itemDoubleClicked emits the QListWidgetItem* and emitting a subclass of that doesn't work. So what I had to do was to go to editItem and get it to dynamic_cast the QListWidgetItem* to a QEventStore*

Adding a child widget to another widget in Qt

Although there are similar questions to mine posted on stackoverflow, none of their solutions actually respond to my problem. I have 2 independent widgets that I would like to combine (insert one widget into the other as a child): one is a UI created only with Qt Creator (drag-and-drop), and the other one an animation done in Qt with OpenGL. I am trying to add the animation in the UI and here is the code:
glwidget.h (animation):
class GLWidget : public QGLWidget
{
public:
GLWidget(QWidget *parent);
~GLWidget();
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void drawCube(int i, GLfloat z, GLfloat ri, GLfloat jmp, GLfloat amp);
QGLFramebufferObject *fbo;
};
and glwidget.cpp:
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
makeCurrent();
fbo = new QGLFramebufferObject(512, 512);
timerId = startTimer(20);
}
GLWidget::~GLWidget()
{
glDeleteLists(pbufferList, 1);
delete fbo;
}
void GLWidget::initializeGL()
{....
As for the UI, I have the header file:
class ClaraTeCourseSimulator : public QMainWindow
{
Q_OBJECT
public:
explicit ClaraTeCourseSimulator(QWidget *parent = 0);
~ClaraTeCourseSimulator();
private:
Ui::ClaraTeCourseSimulator *ui;
GLWidget *defaultAnim;
protected:
void setupActions();
protected slots:
void addAnimWidget();
};
and the .cpp file:
ClaraTeCourseSimulator::ClaraTeCourseSimulator(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ClaraTeCourseSimulator)
{
ui->setupUi(this);
defaultAnim = new GLWidget(ui->centralWidget);
}
void ClaraTeCourseSimulator::setupActions()
{
connect(ui->actionCar_Modelling, SIGNAL(triggered(bool)), ui->centralWidget,
SLOT(addAnimWidget()));
}
void ClaraTeCourseSimulator::addAnimWidget()
{
ui->centralWidget->layout()->addWidget(defaultAnim);
}
ClaraTeCourseSimulator::~ClaraTeCourseSimulator()
{
delete ui;
}
But when I try to run it I get about 24 of these errors: undefined reference to `imp_ZN9QGLFormatD1Ev all pointing to the constructor and destructor in glwidget.cpp.
What am I doing wrong? How can I fix this problem?
Are you trying to change the central widget to the GL one? Because specifying the parent for the GL widget does not change them. If you'd like to change a widget to another (using the Designer), I recommend the "promote to" feature, with which you can change a widget's actual class in the designer. So add a QWidget on the UI, and than promote it to your class (GLWidget).
It seems like the problem is with the GLFormat constructor call in the GLWidget constructor.