I'm trying to use QTimer, which inherits QObject, in my newly created class. However I try it I keep getting the error 'QObject' is an ambiguous base of 'Recorder' . I did try my best to avoid ambiguity in my simple program but still got stuck with it.
Here's the structure of my classes.
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
dialog.h: mainwindow UI
#ifndef DIALOG_H
#define DIALOG_H
#include "detector.h"
#include <QDialog>
#include <QtCore>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
Detector myDetector;
detector.h: detector window UI
#ifndef DETECTOR_H
#define DETECTOR_H
#include <QDialog>
#include <QtCore>
#include <QObject>
#include "actualrec.h"
namespace Ui {
class Detector;
}
class Detector : public QDialog
{
Q_OBJECT
public:
explicit Detector(QWidget *parent = 0);
~Detector();
void run();
private:
ActualRec theDetector;
Ui::Detector *ui;
actualrec.h: detector code
#ifndef ACTUALREC_H
#define ACTUALREC_H
#include <QtCore>
#include <QObject>
#include <QImage>
#include "recorder.h"
class ActualRec : public QThread
{
public:
ActualRec();
void run();
private:
Recorder theRecorder;
recorder.h: recorder code, where I want to use my QTimer
#ifndef RECORDER_H
#define RECORDER_H
#include <QtCore>
class Recorder : public QThread, public QObject
{
public:
Recorder();
void run();
private:
QTimer* theTimer;
recorder.cpp constructor has
*theTimer = new QTimer(this);
the output is following:
http://i.imgur.com/Awb6qhd.png
Any help would be much appreciated
You have several issues in your code:
1) Wrong usage of thread with Qt
class Recorder : public QThread, public QObject
a) It is enough to inherit QThread without explicitly inheriting QObject since QThread inherits QObject.
b) Even if you did this, historically, QObject ought to be the first base in the list in a general case.
c) However, you may wish to reconsider how to use your threads. This is one way, but necessarily the best.
2) Allocating an object for QTimer on the heap
Why are you allocating memory on the heap for a timer in the first place? It is OK to allocate it on the stack, especially since it is a member. That way, you would not need to deal with the this hassle either. The whole memory management becomes a lot simpler.
3) Not utilizing Q_NULLPTR
You ought to use it instead of 0 for the default values of the parents.
4) Including the whole QtCore module
#include <QtCore>
You should only include the parts that you eventually use. This is a brute-force way of including things.
Therefore, write something like this instead:
class Recorder : public QThread
{
public:
Recorder();
void run();
private:
QTimer theTimer;
Of course, if you use the threading mechanism the other way around in Qt, then it is perfectly fine to write this instead for the inheritance:
class Recorder : public QObject
but then your code would need some other change, so the code is broken as it is now, either way.
QThread already inherits QObject, and you can't inherit from two classes both inheriting QObject themselves.
You shall no inherit QObject twice. This is because signals and slots are mapped by integers and the ids can collide with each.
This also applies to any object that inherits from QObject.
class BadClass : public QTimer, public Dialog
{
};
Related
I want to separate my roles in a game to different .cpp and .h files,
but I have trouble calling the pointer in mainwindow from another class, which I added through scene->add() in mainwindow.cpp.
It shows "player" was not declared in this scope when I run.
I know this question seems pretty basic, but I've tried my best to fix it with no results.
The following are main methods I've tried:
add MainWindow:: before player, but it shows the similar error
that mainwindow is not declared in this scope.
revise player to this pointer, and it says that class Player has no such member.
revise player to pos() pointer, it says pos() is not
declared in this scope
set class Player as friend with main window, but nothing changes
Here is the code:
main window.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
scene(new QGraphicsScene(0,0,800,600)),
timer(new QTimer)
{
ui->setupUi(this);
ui->graphicsView->setScene(scene);
player = new QGraphicsPixmapItem(QPixmap(":/img/whitedog.png").scaled(150,150));
scene->addItem(player);
player->setPos(0, 0);
timer->start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
main window.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include <QKeyEvent>
#include "player.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
friend class Player;
~MainWindow();
private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QTimer *timer;
QGraphicsItem *player;
};
#endif // MAINWINDOW_H
player.cpp
#include "player.h"
Player::Player()
{
}
void Player::keyPressEvent(QKeyEvent *e)
{
switch(e->key()) {
case Qt::Key_Up:
player->setPos(player->x(), player->y()-10);
break;
}
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <QKeyEvent>
#include <QGraphicsScene>
#include <QMainWindow>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include "ui_mainwindow.h"
class Player
{
public:
Player();
void keyPressEvent(QKeyEvent *e);
};
#endif // PLAYER_H
You are getting confused between two different things.
You have a class Player, which I believe is the one that you want to declare in mainwindow.h but an object of class Player is not created anywhere( as far as what is shown above ).
The player currently declared in the mainwindow.h is of type QGraphicsItem and not of the Player class that you created, so you cannot expect your keyPressEvent to work on it.
You need to have a second look at your design, know the purpose of the Player class, it's responsibilities. Currently it is a simple class not inheriting from anything, did you want it to maybe inherit from QGraphicsItem.
In such a case, your class maybe could look something like this :
class Player : public QGraphicsItem
{
//Players's responsibilities.
}
And in your mainwindow.h, you can just use the instance of the Player instead of using a QGraphicsItem instance.
class MainWindow : public QMainWindow
{
...// other stuff
private:
Player *player;
}
Additional Pointers :
1 . I don't see a reason for the Player class to be a friend class in mainwindow.h, but then again it is your design.
2 . Prefer initializing the player object part in the member initialization list rather than doing it in the constructor.
First let me quickly introduce myself.
My name is Jonathan and I'm a video game technical artist and developer from Belgium.
I work mainly with C# or other script languages like Max Script, Python or Mel, and I begin to code in C++. I already did some little software in Visual Studio with WinForm and WPF.
StackOverflow was/and will be always an incredible resource for me.
I register because I moved further in my C++/Qt learning and I am now stuck with a Qt design and code problem.
I used the MVP pattern by the past for WinForm applications, and try to do the same with Qt. So I investigate and found the interface with Q_DECLARE_INTERFACE(MyInterfaceClass, "interfaceNameString") and QT_INTERFACES in the class that will implement the interface.
But I have a problem to connect the signal from the interface to a slot from and in my presenter.
error: no matching function for call to 'Presenter::connect(QObject*&, void (IView_Creator::)(), Presenter, void (Presenter::*)())'
QObject::connect(object,&IView_Creator::CreatorTest, this, &Presenter::Create);
error: no type named 'type' in 'struct std::enable_if'
The interface : (iview_creator.h)
#ifndef IVIEW_CREATOR_H
#define IVIEW_CREATOR_H
#include <QtPlugin>
class IView_Creator
{
public:
virtual ~IView_Creator(){}
virtual void WriteSomething() = 0;
signals:
virtual void CreatorTest() = 0;
};
Q_DECLARE_INTERFACE(IView_Creator, "interface")
#endif // IVIEW_CREATOR_H
The main class : (mainWindow.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "iview_creator.h"
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow ,public IView_Creator
{
Q_OBJECT
Q_INTERFACES(IView_Creator)
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
// IView_Creator interface
signals:
void CreatorTest();
};
#endif // MAINWINDOW_H
The presenter class : (presenter_creator.h)
#ifndef PRESENTER_H
#define PRESENTER_H
#include <QObject>
#include "mainwindow.h"
class Presenter : private QObject
{
Q_OBJECT
public:
Presenter(const MainWindow* mw);
private:
void Initialize(IView_Creator* mw);
private slots:
void Create();
};
#endif // PRESENTER_H
The implementation of the presenter :
#include "presenter_creator.h"
Presenter::Presenter(const MainWindow *mw)
{
IView_Creator *i = qobject_cast<IView_Creator*>(mw);
if(i != NULL)
Initialize(i);
}
void Presenter::Initialize(IView_Creator *mw)
{
auto object = dynamic_cast<QObject*>(mw);
Q_ASSERT(object);
QObject::connect(object, SIGNAL(CreatorTest()), this, SLOT(Create()));
//QObject::connect(object,QOverload<QObject*>::of(&IView_Creator::CreatorTest), this, &Presenter::Create);
QObject::connect(object,&IView_Creator::CreatorTest, this, &Presenter::Create);
mw->WriteSomething();
}
void Presenter::Create()
{
printf("Create");
}
The main class :
#include "mainwindow.h"
#include "presenter_creator.h"
#include <QApplication>
static Presenter* pt = NULL;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
MainWindow *mw = &w;
pt = new Presenter(mw);
w.show();
return a.exec();
}
The problem appear when I try to use the new synthax system of the connect function. I seems to work with the old SIGNAL SLOT string system.
I already try everything I found on the net but with no luck.
Maybe someone with more C++ and Qt knowledge could know how to solve this problem.
This can't work with the new signal-slot syntax since QObject doesn't inherit from IView_Creator.
The fundamental difference between the old and the new syntax is that with the old syntax QObject::connect checks at runtime whether the signal and the slot of the connection actually exist, while this check is performed at compile time with the new syntax.
However, after your cast of mw to QObject* the information that object actually also is an instance of IView_Creator is lost to the implementation of QObject::connect. All it knows is that &IView_Creator::CreatorTest needs an object of a subtype of IView_Creator and that not every QObject (that's all it knows about object) is also an IView_Creator, so it can't guarantee that this connection can always be created. Therefore it fails to compile.
Material class has a mainwindow with a menu bar. When i click one of the elements in the menu bar i want to open the Fiction Qdialog window.
material.h
#ifndef MATERIALS_H
#define MATERIALS_H
#include <QMainWindow>
#include "materialinner.h"
class FictionSection;
namespace Ui {
class Materials;
}
class Materials : public QMainWindow, public MaterialInner
{
Q_OBJECT
public:
explicit Materials(QWidget *parent = 0);
~Materials();
private:
Ui::Materials *ui;
FictionSection *fiction;
};
#endif // MATERIALS_H
materials.cpp
#include "materials.h"
#include "ui_materials.h"
#include "fictionsection.h"
#include <QDebug>
#include <QMessageBox>
Materials::Materials(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Materials)
{
ui->setupUi(this);
// connect(ui->ficti,SIGNAL(textChanged(const QString &)),this,SLOT(displaySearch()));
}
Materials::~Materials()
{
delete ui;
}
void Materials::on_actionFiction_section_triggered()
{
this->hide();
fiction = new FictionSection();
fiction->show();
}
fictionsection.h
#ifndef FICTIONSECTION_H
#define FICTIONSECTION_H
#include <QDialog>
#include "materials.h"
namespace Ui {
class FictionSection;
}
class FictionSection : public QDialog, public Materials
{
Q_OBJECT
public:
explicit FictionSection(QWidget *parent = 0);
~FictionSection();
private:
Ui::FictionSection *ui;
};
#endif // FICTIONSECTION_H
When i compile it gives an error which is
Request for member 'show' is ambiguous.
Please help me to solve this. Thank you in advance.
The problem is that your FictionSection class inherits from both QDialog and Materials, but your Materials class also inherits from QMainWindow. Both QMainWindow and QDialog have a virtual show() method (inherited from QWidget), which causes the ambiguity. In other words: do you intend to call QMainWindow::show's implementation or QDialog::show's implementation? No one knows.
To solve this, you should use inheritance properly. Inherit from either QMainWindow or QDialog, but not both.
You need to understand why it is that you're inheriting the way you are (which is wrong) and improve the logic of the relationship between your classes to avoid problems like this one.
Also, class names should be singular, so Materials should be Material. If it needs to handle multiple things, then it could be MaterialManager or something similar.
I want to create SerialPort class,
and it can receive msg automatic and then emit a signal.
but when I compile it show the error message:
error: 'QObject' is an ambiguous base of 'SerialPort'
QObject::connect(&uartObj, SIGNAL(readDone(QByteArray)), this, SLOT(hdlRxDone(QByteArray)));
have someone can help me to solve it ?
thanks.
#ifndef SERIALPORT_H
#define SERIALPORT_H
#include <QObject>
#include <QSerialPort>
#include <QThread>
class SerialPort : public QSerialPort, public QThread
{
Q_OBJECT
public:
explicit SerialPort(QObject *parent = 0);
~SerialPort();
void stop();
signals:
void readDone(QByteArray data);
public slots:
private:
void run();
};
#endif // SERIALPORT_H
Both QSerialPort and QThread derived from QObject, so in your code you have multiple inheritance from QObject, which is forbidden in Qt. You should derive only from QThread, but it is not very good way. The best way is to create simple Worker class derived from QObject, which HAS QSerialPort, and move this class to some thread with moveToThread().
You can find more information about correct usage here or in the documentation.
Full example about serial port in separate thread you can find here, it is in russian language, but you need only code which is not very complex.
I have a problem with accessing ui elements from another class(with instance). I have a second QMainWindow in my application, I can access in secondWindow.cxx class all ui elements but not in read.cxx class. My code looks like following. Where is my mistake? Thank you for your help.
-------------------------------secondWindow.h------------------------------------
#ifndef __secondWindow_h
#define __secondWindow_h
#include "ui_secondwindow.h"
class secondWindow : public QMainWindow
{
friend class read;
igstkStandardClassBasicTraitsMacro(secondWindow, QMainWindow);
Q_OBJECT
public:
igstkStateMachineMacro();
secondWindow();
virtual ~secondWindow();
void createSignalAndSlots();
public slots:
void secondWindowTest();
protected:
private:
Ui::secondMainWindow m_secondWindowUI;
};
#endif
-------------------------------secondWindow.cxx------------------------------------
#include "secondWindow.moc"
#include "secondWindow.h"
#include "read.h"
secondWindow::secondWindow() :m_StateMachine(this)
{
m_secondWindowUI.setupUi(this);
createSignalAndSlots();
}
void secondWindow::createSignalAndSlots()
{
connect(m_secondWindowUI.pushButton1, SIGNAL(clicked()),this, SLOT(secondWindowTest()));
connect(m_secondWindowUI.pushButton2, SIGNAL(clicked()), read::instance(), SLOT(readTest()));
}
void secondWindow::secondWindowTest()
{
m_secondWindowUI.pushButton1->setEnabled(true); //OK
}
secondWindow::~secondWindow(){}
---------------------------------read.h--------------------------------------
#pragma once
#include "secondWindow.h"
class read : public QObject
{
Q_OBJECT
public:
static read *instance();
read();
virtual ~read() {}
public slots:
void readTest();
protected:
secondWindow *m_readUI;
static read *m_read;
private:
};
---------------------------------read.cxx--------------------------------------
#include <read.moc>
#include "secondWindow.h"
#include "read.h"
read *read::m_read= NULL;
read::read()
{
m_readUI = dynamic_cast<secondWindow*>( QApplication::instance() );
}
read *read::instance()
{
if(m_read == NULL)
m_read = new read();
return m_read;
}
void read::readTest()
{
m_readUI->m_secondWindowUI.qlabelTest->setText("test"); //segmentation fault
}
You are casting a QApplication::instance(), which is a QApplication * deriving from QCoreApplication * deriving from QObject *. That won't work, it's not a secondWindow *, not even a QMainWindow *, not even a QWidget *.
Apart from that, your coding style is rather strange -- in Qt, it's customary to use CamelCase for classes, not thisStuff which usually applies to functions and methods. Including <read.moc> is just wrong. Why is read::m_read static? Finally, the coupling between the two window classes is set up in a strange way (accessing global stuff like QApplication just to get a reference to another window smells ugly code). A much better and more obvious approach is to either wrap all of your windows in a parent object or setting up the dependencies explicitly, perhaps like this:
MainWindow *mainWindow = new MainWindow();
SecondWindow *second = new SecondWindow(mainWindow);
UtilityWindow *utilityWin = new UtilityWindow(second);