For example here is my code
QScopedPointer<QTimer> timer2(new QTimer);
But I want to define
QScopedPointer<QTimer> timer2;
in mainwindow.h and create an instance
timer2(new QTimer);
in the mainwindow.cpp
How?
Try the following:
// mainwindow.h
class MainWindow : public QMainWindow
{
private:
QScopedPointer<QTimer> timer2;
};
If you want to create the instance in the constructor, use the following:
// mainwindow.cpp
MainWindow::MainWindow()
:timer2(new QTimer)
{
}
Alternately, if you want to create the instance in some arbitrary member function of MainWindow, use this:
// mainwindow.cpp
void MainWindow::someFunction()
{
timer2.reset(new QTimer);
}
It's also worth reviewing initialization lists in C++ and the documentation for QScopedPointer.
Use method reset of QScopedPointer
timer2.reset(new QTimer());
What you're doing amounts to a premature pessimization. You're creating members of a MainWindow class separately and individually on the heap, when you should be simply putting them into the class as members:
// interface
#include <QMainWindow>
#include <QTimer>
class MainWindow : public QMainWindow {
Q_OBJECT
QTimer m_timer;
public:
MainWindow(QWidget * parent = 0, Qt::WindowFlags flags = 0);
};
// implementation
MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags flags) :
QMainWindow(parent, flags),
m_timer()
{
...
}
Of course, you would ordinarily not want to expose all the details of the MainWindow's implementation in the interface (header) file. Thus you would leverage the PIMPL idiom:
// interface
#include <QMainWindow>
class MainWindowPrivate;
class MainWindow : public QMainWindow {
Q_OBJECT
Q_DECLARE_PRIVATE(MainWindow)
QScopedPointer<MainWindowPrivate> const d_ptr;
public:
MainWindow(QWidget * parent = 0, Qt::WindowFlags flags = 0);
}
// implementation
#include "MainWindow.h"
#include <QTimer>
class MainWindowPrivate {
public:
QTimer timer;
}
MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags flags) :
QMainWindow(parent, flags),
d_ptr(new(MainWindowPrivate())
{
Q_D(MainWindow);
d->timer.start( ... );
...
}
Related
I'm trying to connect signals from a child window (QDialog named VolumePage) to its parent (QMainWindow named MockUI). I'm running into a:
invalid use of incomplete type 'class Ui::VolumePage'
error when I attempt to make the connection.
I'm trying to connect inside the MockUI.cpp when I make the volume page. (Happens on a button press)
void MockUI::on_pushButton_3_clicked()
{
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
I've made Ui::VolumePage *ui; public.
Here's the entire error:
error: invalid use of incomplete type 'class Ui::VolumePage'
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
Can anyone help me understand what the problem is, or another clean way to do what I'm trying to do?
Edit: (Additional Source)
VolumePage.h:
#ifndef VOLUMEPAGE_H
#define VOLUMEPAGE_H
#include <QDialog>
namespace Ui {
class VolumePage;
}
class VolumePage : public QDialog
{
Q_OBJECT
public:
explicit VolumePage(QWidget *parent = 0);
Ui::VolumePage *ui;
~VolumePage();
private slots:
void on_verticalSlider_valueChanged(int value);
private:
};
#endif // VOLUMEPAGE_H
mockUI.cpp:
#include "mockUI.h"
#include "ui_mock_ics.h"
#include <QLCDNumber>
#include "volumepage.h"
MockUI::MockUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MockUI)
{
ui->setupUi(this);
}
MockUI::~MockUI()
{
delete ui;
}
void MockUI::on_pushButton_3_clicked()
{
//Modal Approach
//VolumePage volPage;
//volPage.setModal(true);
//volPage.exec();
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage->ui->verticalSlider,SIGNAL(valueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
volumepage.cpp:
#include "volumepage.h"
#include "mockUI.h"
#include "ui_volumepage.h"
VolumePage::VolumePage(QWidget *parent) :
QDialog(parent),
ui(new Ui::VolumePage)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
//Mock_ICS* ics = (Mock_ICS*)parent;
//connect(ui->verticalSlider,SIGNAL(valueChanged(int)),ics->ui->progressBar,SLOT(setValue(int)));
//connect(ui->verticalSlider,SIGNAL(valueChanged(int)),this->parent()->progressBar,SLOT(setValue(int)));
}
VolumePage::~VolumePage()
{
delete ui;
}
Ui::VolumePage *ui should remain private. Instead create a signal on the volPage, something like verticalSliderValueChanged(int value). See below...
mockui.h
#ifndef MOCKUI_H
#define MOCKUI_H
#include <QMainWindow>
#include "volumepage.h"
namespace Ui {
class MockUI;
}
class MockUI : public QMainWindow
{
Q_OBJECT
public:
explicit MockUI(QWidget *parent = 0);
~MockUI();
VolumePage* volPage;
private slots:
void on_pushButton_3_clicked();
private:
Ui::MockUI *ui;
};
#endif // MOCKUI_H
mockui.cpp
#include "mockui.h"
#include "ui_mockui.h"
#include "volumepage.h"
MockUI::MockUI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MockUI)
{
ui->setupUi(this);
}
MockUI::~MockUI()
{
delete ui;
}
void MockUI::on_pushButton_3_clicked()
{
//Non-Modal Approach
volPage = new VolumePage(this);
volPage->show();
connect(volPage,SIGNAL(verticalSliderValueChanged(int)),ui->progressBar,SLOT(setValue(int)));
}
volumepage.h
#ifndef VOLUMEPAGE_H
#define VOLUMEPAGE_H
#include <QDialog>
namespace Ui {
class VolumePage;
}
class VolumePage : public QDialog
{
Q_OBJECT
public:
explicit VolumePage(QWidget *parent = 0);
~VolumePage();
signals:
void verticalSliderValueChanged(int value);
private slots:
void on_verticalSlider_valueChanged(int value);
private:
Ui::VolumePage *ui;
};
#endif // VOLUMEPAGE_H
volumepage.cpp
#include "volumepage.h"
#include "ui_volumepage.h"
VolumePage::VolumePage(QWidget *parent) :
QDialog(parent),
ui(new Ui::VolumePage)
{
ui->setupUi(this);
}
VolumePage::~VolumePage()
{
delete ui;
}
void VolumePage::on_verticalSlider_valueChanged(int value)
{
emit verticalSliderValueChanged(value);
}
This is an example of the pImpl idiom in C++. Class VolumePage is the one you should be using - this is the "public" interface of what Qt Creator has generated. Ui::VolumePage contains the complicated details you should not worry about.
So, in your code you should be using VolumePage, not Ui::VolumePage. You shouldn't have make Ui::VolumePage public.
I am having a problem compiling dialog.h, the compiler complains that QHostAddress::Any is not a type, and expected identifier before numeric constant. (both on the second to last line of dialog.h).
Can someone tell me why this won't compile? I'm instantiating the server object, and passing parameters that the server constructor expects...i thought...
dialog.h
#include <QWidget>
#include <QHostAddress>
#include "server.h"
class QLabel;
class QPushButton;
class Dialog : public QWidget
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
private:
QLabel *statusLabel;
QPushButton *quitButton;
Server server;
};
server.h:
class Server : public QTcpServer
{
Q_OBJECT
public:
Server(QHostAddress listenAddress, quint16 listenPort, QObject *parent = 0);
QHostAddress hostAddress;
quint16 hostPort;
protected:
void incomingConnection(qintptr socketDescriptor);
private:
};
dialog.cpp (partial)
Dialog::Dialog(QWidget *parent)
: QWidget(parent), server(QHostAddress::Any, 4000)
{
server.cpp (partial)
#include "server.h"
#include "clientthread.h"
#include <stdlib.h>
Server(QHostAddress listenAddress, quint16 listenPort, QObject *parent = 0)
: hostAddress(listenAddress), hostPort(listenPort), QTcpServer(parent)
{
}
Note code above updated. Now compiler complains:
Expected ')' before 'listenAddress' on the constructor definition of Server.
You need to declare the Server object as a Dialog class member variable and than define it in constructor. Here is how the Dialog class should look like:
dialog.h
#include <QWidget>
#include <QHostAddress>
#include "server.h"
class QLabel;
class QPushButton;
class Dialog : public QWidget
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
private:
QLabel *statusLabel;
QPushButton *quitButton;
Server server; // Declare server member variable.
};
dialog.cpp
Dialog::Dialog(QWidget *parent)
:
QWidget(parent),
server(QHostAddress::Any, 4000) // construct server
{
//...
}
I am implementing a card game. I want the window ui to be an object of class Rule, so that Rule can modify the GUI directly.
So Rule has an object Window * ui initialized in the constructor.
But during compilation, the compiler tells me that in rule.h, "Window has not been declared", "Window is not a type". I included <window.h>, everything has the same type, everything is initialized, so I run out of ideas of why it does not work.
EDIT: I edited the code following alexisdm's notes. In addition, in rule.h, I had to change the definition of ui from Window * ui to Ui::Window *ui, because in window.h, ui is defined as Ui::Window * ui, and this is the object I want Rule::rule to control.
But now, in rule.cpp, ui->do_stuff() does not compile, because Ui::Window does not have the do_stuff() function, but Window does...
Arg! What to do?!! ui->do_stuff() works fine in window.cpp. Inheritance problem?
window.cpp:
Window::Window(QWidget *parent) :
QDialog(parent),
ui(new Ui::Window)
{
ui->setupUi(this);
player = new Game_state(); /* Game state */
rule = new Rule(player, ui); /* Implement the action of cards*/
}
void Window::do_stuff(){
//Do stuff
}
window.h
#include <QDialog>
#include "game_state.h"
#include "rule.h"
class Rule;
namespace Ui {
class Window;
}
class Window : public QDialog
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
~Window();
Game_state * player;
Rule * rule;
void do_stuff();
private:
Ui::Window *ui;
};
rule.h
#ifndef RULE_H
#define RULE_H
#include "window.h"
#include <game_state.h>
class Window;
class Rule{
public:
Rule(Game_state *, Ui::Window *);
void action(Card *);
private:
Game_state * player;
Ui::Window * ui;
};
#endif // RULE_H
rule.cpp
#include <rule.h>
Rule::Rule(Game_state * game, Ui::Window * window){
player = game;
ui = window;
}
void Rule::stuff(){
ui->do_stuff();
}
There is a circular dependency in your headers: window.h and rule.h are referencing each other.
You should replace both #include by forward declarations to avoid it.
class Window; // instead of #include "window.h"
class Rule; // instead of #include "rule.h"
You'll still need to add #include "window.h" in rule.cpp, and #include "rule.h" in window.cpp.
My guess is the name of your class, Window, is too generic and #include <window.h> probably includes the system one instead of yours.
Try change the clase and header name to something more specific to your app like CardWindow, or use #include "window.h"
I have a class BatchItem that inherits QObject, plus several classes that inherit from BatchItem:
#ifndef BATCHITEM_H
#define BATCHITEM_H
#include <QObject>
class BatchItem : public QObject
{
Q_OBJECT
public:
virtual void start() = 0;
virtual void stop() = 0;
signals:
/* ... some signals ... */
};
#endif // BATCHITEM_H
Example of a class that inherits from BatchItem:
#ifndef VIDEOBATCHITEM_H
#define VIDEOBATCHITEM_H
#include "batchprocessing/batchitem.h"
#include <QtCore/QObject>
class VideoBatchItem : public BatchItem
{
Q_OBJECT
public:
explicit VideoBatchItem(/* ... */, QObject *parent = 0);
void start();
void stop();
private:
/* ... some private member variables ... */
};
#endif // VIDEOBATCHITEM_H
And this is the corresponding .cpp:
#include "videobatchitem.h"
VideoBatchItem::VideoBatchItem(/* ... */,
QObject *parent) :
/* ... */,
QObject(parent)
{
/* ... */
}
/* ... */
But when I try to compile, I get the following error:
error: type ‘QObject’ is not a direct base of ‘VideoBatchItem’
Of course I see that this is correct, as QObject is only an indirect base of VideoBatchItem. But why is that a problem?
Isn't that also the case for e.g. QAbstractScrollArea, which inherits from QFrame, which in turn inherits from QWidget? They all take a QWidget as their parent, although QAbstractScrollArea only indirectly inherits from QWidget.
Unfortunately I couldn't find an answer to that in neither the documentation nor the .cpp files of the named widget classes.
Since I cannot pass a QObject parent, is there still a way to use Qt's parent-child system for the destruction of my derived batch items?
You can't call QObject base constructor. It doesn't matter about type of parent parameter but call of QObject(QObject * parent). You should call in this case BatchItem() without parameter and call setParent(parent) in constructor body, or overload BatchItem(QObject *) constructor.
I'm trying to connect a signal from a QProcess inside my mainwindow() object to another QObject based class inside my mainwindow() object but I get this error:
QObject::connect: Cannot connect (null)::readyReadStandardOutput () to (null)::logReady()
Heres the code, its not complete by any means but I don't know why it doesn't work.
exeProcess.h
#ifndef EXEPROCESS_H
#define EXEPROCESS_H
#include <QObject>
class exeProcess : public QObject
{
Q_OBJECT
public:
explicit exeProcess(QObject *parent = 0);
signals:
void outLog(QString outLogVar); //will eventually connect to QTextEdit
public slots:
void logReady();
};
#endif // EXEPROCESS_H
exeProcess.cpp
#include "exeprocess.h"
exeProcess::exeProcess(QObject *parent) :
QObject(parent)
{
}
void exeProcess::logReady(){
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QProcess>
#include "exeprocess.h"
/*main window ---------------------------------------*/
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QProcess *proc;
exeProcess *procLog;
public slots:
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(proc, SIGNAL(readyReadStandardOutput ()), procLog, SLOT(logReady()));
}
MainWindow::~MainWindow()
{
delete ui;
}
Thanks!.
You need to create the proc and procLog objects.
You've only got pointers as class members, so you'll have to initialize those (with new). connect only works on live objects.
proc is a pointer, but it does not point to anything. You have to instantiate a qprocess before you connect it!
proc = new QProcess();
connect(proc, SIGNAL(readyReadStandardOutput ()), procLog, SLOT(logReady()));