invalid static_cast from type 'QCell*' to type 'QWidget*' - qt

this error appears in line 4:
void QPiece::setPosition( QPoint value )
{
_position = value;
QWidget* parentWidget = static_cast<QWidget *>( _board->Cells[value.x() ][ value.y() ]);
if (parentWidget->layout()) {
parentWidget->layout()->addWidget( this ); }
else {
QHBoxLayout *layout = new QHBoxLayout( parentWidget );
layout->setMargin(0);
layout->addWidget(this);
parentWidget->setLayout(layout);
}
this->setParent( _board->Cells[ value.x() ][ value.y() ] );
}
Here is definition of function Cells():
class QBoard : public QWidget
{
Q_OBJECT
public:
QCell *Cells[8][8];
QBoard(QWidget *parent = 0);
void drawCells();
private:
void positionCells();
};
I think I do something wrong, but what? Thanks in advance.
Here is type of QCell, and i think QWidget is parent to QLabel
class QCell:public QLabel
{
Q_OBJECT
public:
QCell( QPoint position, QWidget *parent = 0 );
private:
QGame *_game;
QPoint _position;
protected:
void mousePressEvent( QMouseEvent *ev );
};

This should work without a cast at all, the conversion from derived to base is implicit.
A likely cause of this error would be that you only have a forward declaration of QCell visible in that compilation unit, which would trigger this error. You need to have the complete class declaration visible for the compiler to know whether that conversion is legal or not.
Example:
#include <QWidget>
class QCell;
int main(int argc, char **argv)
{
QCell *w = 0;
QWidget *q = static_cast<QWidget*>(w);
}
main.cpp: In function ‘int main(int, char**)’:
main.cpp:8:41: error: invalid static_cast from type ‘QCell*’ to type ‘QWidget*’

Related

How to install event filter on a custom Qt class?

I want to install an event filter on an object of a custom class in Qt. So I created a project such as QtGuiApplication1 on the Qt Designer and created a simple class as myClass as which has a widget and a QGraphicsView for drawing a colored rectangle.
in header file:
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
#include "myClass.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
private:
Ui::QtGuiApplication1Class ui;
bool eventFilter(QObject *obj, QEvent *ev);
myClass* myClass_;
};
in .cpp
#include "QtGuiApplication1.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
myClass_ = new myClass(this, QRect(100, 100, 200, 200));
myClass_->installEventFilter(this);
}
bool QtGuiApplication1::eventFilter(QObject * obj, QEvent * ev)
{
if (obj == myClass_)
{
bool hi = true;
}
return false;
}
and the myClass code is here:
header file of myClass:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QGraphicsView>
class myClass : public QObject
{
Q_OBJECT
public:
explicit myClass(QObject *parent = 0);
myClass();
myClass(QWidget* parent, QRect inRect);
private:
QWidget * widget;
QGraphicsView* qGraph_back;
QGraphicsScene* scene_back;
};
#endif /
cpp file of myClass:
#include "myClass.h"
myClass::myClass(QObject *parent) :
QObject(parent)
{
}
myClass::myClass()
{
}
myClass::myClass(QWidget* parent, QRect inRect)
{
widget = new QWidget(parent);
qGraph_back = new QGraphicsView(widget);
scene_back = new QGraphicsScene(qGraph_back);
widget->setGeometry(inRect);
scene_back->setSceneRect(0,0,inRect.width(),inRect.height());
qGraph_back->setBackgroundBrush(QColor(0, 0, 255, 80));
qGraph_back->setScene(scene_back);
qGraph_back->show();
}
I want to get all the events of myClass_ object such as mouse event, But I can't and the eventfilter doesn't work. how to install eventfilter on the object?
The event filter will work only for events in your MyClass instance, only. Not for its children.
So, events, such as a mouse click or move, in your qGraph_back will be not visible in your eventFilter method.
When you add a child in a widget, an QChildEvent event is raised. You can use it to install the event filter on all children (and grandchildren, etc.). But, you have to install the event filter on your MyClass before adding the children.
A quick example:
class Listener: public QObject
{
public:
Listener(): QObject()
{}
bool eventFilter(QObject* object, QEvent* event)
{
qDebug() << Q_FUNC_INFO << object << event;
if (event->type() == QEvent::ChildAdded)
{
QChildEvent* ev = dynamic_cast<QChildEvent*>(event);
ev->child()->installEventFilter(this);
}
return false;
}
};
class Widget: public QWidget
{
public:
Widget(QObject* parent) : QWidget()
{
installEventFilter(parent);
QGraphicsView* view = new QGraphicsView(this);
auto layout = new QHBoxLayout(this);
layout->addWidget(view);
layout->addWidget(new QLabel("Foobar"))
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Listener* listener = new Listener();
Widget* w = new Widget(listener);
w->show();
return app.exec();
}
As you can see, the events in the QLabel are now sent to the listener. But, you can't see the events from the view because they are caught by the viewport widget in the QGraphicsView...
You have to handle the case where the added child has a viewport (inherits from QAbstractItemView, etc.) and it becomes more complicated.
So, if you have to know when the user clicks on your view, it would be easier to use signals/slots and not an event filter.

How to make a QSlider change with double values

My problem is that I just can't seem to make my QSlider work with double values instead of integer, because I need to make it return double values to a QLineEdit and also set it's own value when I put some value in the edit.
When I was a Qt beginner I started with this tutorial. It is a little bit old (it refers to Qt4.1), but it was good enough to get me started!
I have put together a simple example application that can show you where to start... Maybe you can find it helpful!
#include <QApplication>
#include <QtGui>
#include <QVBoxLayout>
#include <QSlider>
#include <QLabel>
class DoubleSlider : public QSlider {
Q_OBJECT
public:
DoubleSlider(QWidget *parent = 0) : QSlider(parent) {
connect(this, SIGNAL(valueChanged(int)),
this, SLOT(notifyValueChanged(int)));
}
signals:
void doubleValueChanged(double value);
public slots:
void notifyValueChanged(int value) {
double doubleValue = value / 10.0;
emit doubleValueChanged(doubleValue);
}
};
class Test : public QWidget {
Q_OBJECT
public:
Test(QWidget *parent = 0) : QWidget(parent),
m_slider(new DoubleSlider()),
m_label(new QLabel())
{
m_slider->setOrientation(Qt::Horizontal);
m_slider->setRange(0, 100);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_slider);
layout->addWidget(m_label);
connect(m_slider, SIGNAL(doubleValueChanged(double)),
this, SLOT(updateLabelValue(double)));
updateLabelValue(m_slider->value());
}
public slots:
void updateLabelValue(double value) {
m_label->setText(QString::number(value, 'f', 2));
}
private:
QSlider *m_slider;
QLabel *m_label;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Test *wid = new Test();
wid->show();
return a.exec();
}
#include "main.moc"
You can simply divide slider value on some constant. For example:
const int dpi = 10; // Any constant 10^n
int slideVal = 57; // Integer value from slider
double realVal = double( slideVal / dpi ); // float value

Writing to a QListWidget from OpenCV window

I am writing an application for manually selecting regions of interest from an image. Two windows will appear:
An OpenCV window, where the user should select a ROI with the mouse.
A QT window, where the selected ROI's coordinates will appear (in a QListWidget)
My problem is how to write onto the QListWidget of the QT window from the OpenCV mouse listener. I guess I have to write a function inside my QT class that returns a pointer to the QListWidget, but I havent managed to do it.
Can someone please point me in the right direction?
Here is my main:
#include "myclass.h"
#include <QApplication>
#include </PathToOPENCV/opencv/cv.h>
#include </PathToOPENCV/opencv/highgui.h>
#include <QtDebug>
#include <QListWidget>
using namespace cv;
// Pointer to list widget? Should I use it as a global variable to recieve the pointer of the QListWidget?
QListWidget * ptrToList;
void mouseEvent(int evt, int x, int y, int flags, void* param){
if( evt == CV_EVENT_LBUTTONUP){
// WRITE HERE ONTO QListWidget!
// Something like:
ptrToList->addItem("blah");
}
}
int main(int argc, char *argv[])
{
/*----- OPENCV STUFF ----*/
String windowName = "selectionWindow";
namedWindow( windowName , CV_WINDOW_NORMAL);
Mat theImage = imread("/PATHTOIMAGE/1.jpg");
imshow( windowName,theImage );
/* ---- Mouse Listener setup ----- */
setMouseCallback( windowName, mouseEvent , 0 );
/* ---- QT Stuff ---- */
QApplication a(argc, argv);
myClass w;
w.show();
// Should I do something like this?
ptrToList = w->getListPtr("listWidget");
return a.exec();
}
Here is myclass.h
namespace Ui {
class myClass;
}
class myClass : public QMainWindow
{
Q_OBJECT
public:
explicit myClass(QWidget *parent = 0);
~myClass();
private:
Ui::myClass *ui;
QListWidget * getListPtr(QString listName){
QListWidget * theList;
// None of these work...
//theList = this->parent()->getChild( listName );
//theList = this->getChild( listName );
return(theList);
}
};
EDIT:
#Roku,
I tried your suggestion, but I think I did it wrong. I added a function in myclass for setting up the mouse callback, so myclass.h is like this:
#include <functions.cpp>
using namespace cv;
namespace Ui {
class myClass; /* error: forward declaration of 'struct Ui::myClass' */
}
class myClass : public QMainWindow
{
Q_OBJECT
public:
explicit myClass(QWidget *parent = 0);
~myClass();
void setInnerMouseCallback(String windowName){
setMouseCallback( windowName, mouseEvent , ui->listWidget ); /* error: invalid use of incomplete type 'struct Ui::myClass'*/
}
private:
Ui::myClass *ui;
}
Then, I added a functions.cpp file with the following code:
void mouseEvent(int evt, int x, int y, int flags, void* param){
QListWidget * theList = (QListWidget*) param;
if( evt == CV_EVENT_LBUTTONUP){
theList->addItem("blah");
}
}
Is this correct? I get a couple of errors where pointed. Thank you for your help.
The third parameter of the setMouseCallback() is called as "user data" and its type is void*. It is designed to be used for just this kind of information. You could to move the setMouseCallback() function call to your main window. And then you could use the function like this:
setMouseCallback(windowName, mouseEvent, ui->listWidget);
In the mouse event callback function you would have a pointer to the list widget:
void mouseEvent(int evt, int x, int y, int flags, void* param)
{
if( evt == CV_EVENT_LBUTTONUP)
{
QListWidget* listWidget = (QListWidget*)param;
listWidget->addItem("blah");
}
}

QGraphicsPixmapItem, alternative methods of connecting to slots

I'm aware I need to derive from QObject in order to connect to a slot if I am using QGraphicsPixmapItem, but I am struggling to do this. I have tried alternative ways to achieve what I want, I have tried onMousePress and isSelectable i.e.
run->setFlag(QGraphicsPixmapItem::ItemIsSelectable);
if (run->isSelected())
{
qDebug() << "selected";
}
else if (!run->isSelected())
{
qDebug() << "not selected";
}
although run is selectable, the first argument is never true, it is always "not selected"
This is my code, I am working on the slot method;
mainwindow.cpp
int MainWindow::sim()
{
...
QGraphicsPixmapItem* run = new QGraphicsPixmapItem(QPixmap::fromImage(image6));
run->scale(0.3,0.3);
run->setPos(-200,-200);
run->setFlag(QGraphicsPixmapItem::ItemIsSelectable);
run->setCursor(Qt::PointingHandCursor);
connect(run, SIGNAL(selectionChanged()), this, SLOT(runClicked()));
scene->addItem(run);
//pause
QGraphicsPixmapItem* pause = new QGraphicsPixmapItem(QPixmap::fromImage(image7));
pause->scale(0.3,0.3);
pause->setPos(-160,-197);
pause->setFlag(QGraphicsPixmapItem::ItemIsSelectable);
pause->setCursor(Qt::PointingHandCursor);
connect(pause, SIGNAL(selectionChanged()), this, SLOT(pauseClicked()));
scene->addItem(pause);
...
}
void MainWindow::runClicked()
{
qDebug() << "run Clicked";
}
void MainWindow::pauseClicked()
{
qDebug() << "pause Clicked";
}
mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
int sim();
...
public slots:
void runClicked();
void pauseClicked();
...
So obviously I get the error when connecting to the slots. Could anyone help please? Thank you.
To find out if your item is selected, do this:
QVariant MyItem::itemChange( GraphicsItemChange change, const QVariant& value )
{
if ( change == QGraphicsItem::ItemSelectedHasChanged ) {
qDebug() << ( isSelected() ? "selected" : "not selected" );
}
return QGraphicsItem::itemChange( change, value );
}
If you want to use signals and slots, you need to subclass both QObject and QGraphicsPixmapItem.
Because QObject doesn't contain clicked() signal, you need to implement that, too, by re-implementing
void mousePressEvent ( QGraphicsSceneMouseEvent *e ) and void mouseReleaseEvent ( QGraphicsSceneMouseEvent *e ).
MyItem:
#pragma once
#include <QGraphicsPixmapItem>
#include <qobject.h>
#include <QMouseEvent>
#include <QGraphicsSceneMouseEvent>
class MyItem: public QObject, public QGraphicsPixmapItem
/* moc.exe requires to derive from QObject first! */
{
Q_OBJECT
public:
MyItem(QGraphicsItem *parent = 0): QObject(), QGraphicsPixmapItem(parent)
{
}
MyItem(const QPixmap & pixmap, QGraphicsItem * parent = 0 ): QObject(),
QGraphicsPixmapItem(pixmap, parent)
{
}
signals:
void clicked();
protected:
// re-implement processing of mouse events
void mouseReleaseEvent ( QGraphicsSceneMouseEvent *e )
{
// check if cursor not moved since click beginning
if ((m_mouseClick) && (e->pos() == m_lastPoint))
{
// do something: for example emit Click signal
emit clicked();
}
}
void mousePressEvent ( QGraphicsSceneMouseEvent *e )
{
// store click position
m_lastPoint = e->pos();
// set the flag meaning "click begin"
m_mouseClick = true;
}
private:
bool m_mouseClick;
QPointF m_lastPoint;
};
And simple example of usage:
#include <qgraphicsview.h>
#include <qgraphicsscene.h>
#include "reader.h"
#include <qdebug.h>
class MainAppClass: public QObject
{
Q_OBJECT
public:
MainAppClass()
{
QGraphicsScene *scene = new QGraphicsScene();;
scene->setSceneRect( -100.0, -100.0, 200.0, 200.0 );
MyItem *item = new MyItem(QPixmap("about.png"));
connect(item, SIGNAL(clicked()), this, SLOT(pixmapClicked()));
scene->addItem(item);
QGraphicsView * view = new QGraphicsView( scene );
view->setRenderHints( QPainter::Antialiasing );
view->show();
}
public slots:
void pixmapClicked()
{
qDebug() << "item clicked!" ;
}
};

Qt creating children threads using QFuture error

I am trying to make a Collaborative Editor(I have to use Linux networking libraries for all the networking stuff), I have the main widget(custom made class that inherits QWidget) with all the components. In the constructor I create all the Widgets on this main Widget and at the end I try to create a new thread using QFuture(I use QFuture instead of QThread cause it allows me easily to call functions with any type of parameters, like QTextEdit, QTextCursor...) but it gives me this error at compilation:
"QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x1b064b0), parent's thread is QThread(0x1985750), current thread is QThread(0x1ae7610)".
How to solve the error?
Here is my code:
mainwindow.h:
...//includes
using namespace QtConcurrent;
...
namespace Ui {
class Widget;
class TextEdit;
}
class TextEdit;
class Widget;
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
...
QFuture<void> thread;
}
class TextEdit : public QTextEdit {
Q_OBJECT
...
}
static void receiveKeyPress(TextEdit *textedit, QTextCursor *secondUserCursor) {
unsigned long long int Number = NULL;
QMessageBox::information(textedit->parentWidget(), "UI Component", "This makes the thread to throw the error");
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL)
if( Number == Qt::Key_Home )
secondUserCursor->movePosition(QTextCursor::StartOfLine);
...
else {
QTextCharFormat backgroundFormat = textedit->textCursor().charFormat();
backgroundFormat.setBackground(QColor("lightGreen"));
//If I don't use QMessageBox up there, it breaks here on the next command
secondUserCursor->setCharFormat(backgroundFormat);
secondUserCursor->setPosition(textedit->textCursor().position());
secondUserCursor->insertText(QString::number(Number));
} //else
}//while
}//the function
And mainwindow.cpp:
#include "mainwindow.h"
Widget::Widget(QWidget *parent) {
...
thread = run(receiveKeyPress, this->edit1, this->edit1->secondUserCursor); //run is from QtConcurrent namespace
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
...
window.show();
return a.exec();
}
I've read here on stackoverflow how others use QObject(which I never used and I don't get the idea of it) and QThread(the only combination) but I already tried to use QThread and I wasn't able to pass QTextEdit and QTextCursor to it.
Thanks in advance
Edit:
mainwindow.h
class TextEdit : public QTextEdit {
Q_OBJECT
...
public slots:
void receiveKeyPress(qulonglong);
...
};
mainwindow.cpp
void TextEdit::receiveKeyPress(qulonglong Number) {
if( Number == Qt::Key_Home )
...
}
recv-thread.h - created based on this link http://developer.qt.nokia.com/doc/qt-4.8/thread-basics.html#example-3-clock
#include <QThread>
#include "mainwindow.h" //To get TextEdit in here
class RecvThread : public QThread {
Q_OBJECT
signals:
void transferDataToSlot(qulonglong Data);
protected:
void run();
};
recv-thread.cpp
#include "recv-thread.h"
void RecvThread::run() {
unsigned long long int Number = NULL;
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL) {
emit transferDataToSlot(Number);
}
}
}
main.cpp
...
#include "recv-thread.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
RecvThread recvThread;
...
QObject::connect(&recvThread, SIGNAL(transferDataToSlot(qulonglong)), window.edit1, SLOT(receiveKeyPress(qulonglong)), Qt::QueuedConnection); //line 38
recvThread.start();
//Displaying the window
window.show();
a.exec();
recvThread.quit();
recvThread.wait();
return 0;
}
Am I doing it right?

Resources