Call a method of a subclassing QWidget - c++

it should be really easy, but something just doesn't work and i can't find the problem.
I have two classes, like below:
1) individualtab
#ifndef INDIVIDUALTAB_H
#define INDIVIDUALTAB_H
#include <QMainWindow>
#include <QInputDialog>
#include <QTableWidget>
#include <QVBoxLayout>
#include <QLabel>
class IndividualTab : public QWidget
{
Q_OBJECT
public:
IndividualTab(QWidget *parent = 0);
QTableWidget *table;
QVBoxLayout *layout;
};
#endif // INDIVIDUALTAB_H
IndividualTab::IndividualTab(QWidget *parent) : QWidget()
{
table = new QTableWidget(0,4);
layout = new QVBoxLayout();
}
2) secondclass
#ifndef SECONDCLASS_H
#define SECONDCLASS_H
#include "individualtab.h"
class secondClass : public QMainWindow
{
Q_OBJECT
public:
explicit secondClass(QWidget *parent = 0);
Ui::secondClass *ui;
~secondClass();
QList<IndividualTab> *individualTabList;
};
#endif // SECONDCLASS_H
secondClass::secondClass(QWidget *parent) : QMainWindow(parent), ui(new Ui::secondClass)
{
ui->setupUi(this);
}
secondClass::~secondClass()
{
delete ui;
}
void secondClass::addNewItem()
{
//Getting parameters
QList<QString> parameters;
//creating QList
//Updating individualTab
for(int i = 0; i < ui->tabWidget->count(); i++)
{
if(parameters.at(0) == ui->tabWidget->tabText(i))
{
IndividualTab tab = individualTabList->at(i);
tab.addItem(parameters);
break;
}
}
}
When i compile i have this error:
In file included from ../secondclass.h:5:0,
from ../secondclass.cpp:1:
/usr/include/qt4/QtGui/qwidget.h: In copy constructor 'IndividualTab::IndividualTab(const IndividualTab&)':
/usr/include/qt4/QtGui/qwidget.h:806:5: error: 'QWidget::QWidget(const QWidget&)' is private
../individualtab.h:10:7: error: within this context
../secondclass.cpp: In member function 'void SecondClass::addNewItem()':
../secondclass.cpp:142:56: note: synthesized method 'IndividualTab::IndividualTab(const IndividualTab&)' first required here
I tought that the problem was in IndividualTab tab = individualTabList->at(i);
So i changed in
IndividualTab *tab = new IndividualTab();
tab = individualTabList->at(i);
but in this case, i had this error:
../secondclass.cpp: In member function 'void SecondClass::addNewItem()':
../secondclass.cpp:143:42: error: cannot convert 'const IndividualTab' to 'IndividualTab*' in assignment
../secondclass.cpp:144:17: error: request for member 'addItem' in 'tab', which is of non-class type 'IndividualTab*'
In file included from ../secondclass.h:5:0,
from ../secondclass.cpp:1:
/usr/include/qt4/QtGui/qwidget.h: In copy constructor 'IndividualTab::IndividualTab(const IndividualTab&)':
../individualtab.h:10:7: instantiated from 'void QList<T>::node_construct(QList<T>::Node*, const T&) [with T = IndividualTab]'
/usr/include/qt4/QtCore/qlist.h:512:13: instantiated from 'void QList<T>::append(const T&) [with T = IndividualTab]'
../Ripetizioni/secondclass.cpp:112:38: instantiated from here
/usr/include/qt4/QtGui/qwidget.h:806:5: error: 'QWidget::QWidget(const QWidget&)' is private
../individualtab.h:10:7: error: within this context
In file included from /usr/include/qt4/QtCore/qobject.h:50:0,
from /usr/include/qt4/QtGui/qwidget.h:46,
from /usr/include/qt4/QtGui/qmainwindow.h:45,
from /usr/include/qt4/QtGui/QMainWindow:1,
from ../secondclass.h:4,
from ../secondclass.cpp:1:
/usr/include/qt4/QtCore/qlist.h: In member function 'void QList<T>::node_construct(QList<T>::Node*, const T&) [with T = IndividualTab]':
/usr/include/qt4/QtCore/qlist.h:372:58: note: synthesized method 'IndividualTab::IndividualTab(const IndividualTab&)' first required here
thanks in advance!

QWidgets aren't meant to be copied. Your individualTabList should be a container of pointers-to-IndividualTab. And there's no good reason for that member itself to be a pointer. Change the declaration to:
QList<IndividualTab*> individualTabList;
Then you can:
IndividualTab *tab = individualTabList.at(i);

Related

Qt connect between two classes not working

I have two classes: HoodPlanner and DrawRoad. Both classes inherit from QWidget and the the UI so I can access all UI elements in both classes.
Here's a snipped of both classes:
HoodPlanner:
#ifndef HOODPLANNER_H
#define HOODPLANNER_H
#include <ui_hoodplanner.h>
#include "drawroad.h"
#include <QtWidgets>
class HoodPlanner : public QWidget, private Ui::HoodPlanner
{
Q_OBJECT
private:
// (...)
public:
explicit HoodPlanner(QWidget * = 0);
// (...)
private slots:
// (...)
};
#endif // HOODPLANNER_H
DrawRoad:
#ifndef DRAWROAD_H
#define DRAWROAD_H
#include <ui_hoodplanner.h>
#include <QtWidgets>
class DrawRoad : public QWidget, private Ui::HoodPlanner
{
Q_OBJECT
private:
// (...)
public:
explicit DrawRoad(QWidget *parent = 0);
public slots:
void drawSC4Street();
};
#endif // DRAWROAD_H
In HoodPlanner I have a connect that will be emitted whenever the itemSelection changes in table_ts2. I have the slot stored in DrawRoad, but inserting a reference to the DrawRoad object in third position brings up errors.
HoodPlanner::HoodPlanner(QWidget *parent) : QWidget(parent)
{
setupUi(this);
// (...)
DrawRoad *drawRoad = new DrawRoad;
connect(table_ts2, SIGNAL(itemSelectionChanged()), &drawRoad, SLOT(drawSC4Street()));
}
Snipped from DrawRoad.cpp:
#include "drawroad.h"
DrawRoad::DrawRoad(QWidget *parent) : QWidget(parent)
{
}
void DrawRoad::drawSC4Street()
{
if(!table_ts2->selectionModel()->hasSelection()) return;
// (...)
}
And the following errors occur whenever I run the app:
hoodplanner.cpp:12: Fehler: no matching function for call to 'HoodPlanner::connect(QTableWidget*&, const char [24], DrawRoad**, const char [17])'
mingw492_32\include\QtCore\qobject.h:213: Fehler: no type named 'Object' in 'struct QtPrivate::FunctionPointer<const char*>'
(and lots of notes)
The errors don't help me at all and I've searched in several topics for a solution, but none of them had my problem.
Have you tried
HoodPlanner::HoodPlanner(QWidget *parent) : QWidget(parent)
{
setupUi(this);
// (...)
DrawRoad *drawRoad = new DrawRoad;
connect(table_ts2, SIGNAL(itemSelectionChanged()), drawRoad, SLOT(drawSC4Street()));
}
You declrared drawRoad as a pointer:
DrawRoad *drawRoad = new DrawRoad;
And then you pass its address to connect() with &drawRoad.
In this case you are passing a pointer to a pointer address. Try without the &

Qt: Cannot queue arguments of type MyClass

I'm trying to pass my Class trough a signal with this:
connect(this, SIGNAL(SIG_connectSerial(SerialSetting::Settings)), serial, SLOT(openConnection(SerialSetting::Settings)),Qt::QueuedConnection);
The class I want to pass is that class:
#ifndef SERIALSETTING_H
#define SERIALSETTING_H
#include <QWidget>
#include <QtSerialPort/QSerialPort>
namespace Ui {
class SerialSetting;
}
class QIntValidator;
class SerialSetting : public QWidget
{
Q_OBJECT
public:
struct Settings {
QString portName;
qint32 baudRate;
};
Settings settings();
public:
explicit SerialSetting(QWidget *parent = 0);
~SerialSetting();
private slots:
void apply();
void on_btnApply_clicked();
private:
void fillPortsParameters();
void fillPortsInfo();
void updateSettings();
private:
Ui::SerialSetting *ui;
Settings currentSettings;
QIntValidator *intValidator;
};
#endif // SERIALSETTING_H
#include "serialsetting.h"
#include "ui_serialsetting.h"
#include <QtSerialPort/QSerialPortInfo>
#include <QIntValidator>
#include <QLineEdit>
QT_USE_NAMESPACE
static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A");
SerialSetting::SerialSetting(QWidget *parent) :
QWidget(parent),
ui(new Ui::SerialSetting)
{
ui->setupUi(this);
intValidator = new QIntValidator(0, 4000000, this);
//ui->cboBaudRate->setInsertPolicy(QComboBox::NoInsert);
fillPortsParameters(); //call function to fill comboboxes
connect(ui->btnApply, SIGNAL(clicked()),this, SLOT(apply()));
}
SerialSetting::~SerialSetting()
{
delete ui;
}
void SerialSetting::fillPortsParameters()
{
//fill cboComport with all available comports
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->cboComport->addItem(info.portName());
}
}
void SerialSetting::apply()
{
SerialSetting::currentSettings.portName = ui->cboComport->currentText();
hide();
}
SerialSetting::Settings SerialSetting::settings()
{
return SerialSetting::currentSettings;
}
void SerialSetting::on_btnApply_clicked()
{
}
The compiler throws this exception:
QObject::connect: Cannot queue arguments of type 'SerialSetting::Settings'
(Make sure 'SerialSetting::Settings' is registered using qRegisterMetaType().)
I tried qRegisterMetaType<SerialSetting>(); but this ended in the following error:
static assertion failed: Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system
#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
Adding the Makro Q_DECLARE_METATYPE(Ui::SerialSetting) at the end of the class-header throws another error:
invalid application of 'sizeof' to incomplete type 'Ui::SerialSetting'
isLarge = (sizeof(T)>sizeof(void*)),
You can't call Q_DECLARE_METATYPE on a forward-declared class (Ui::SerialSetting). Also, you need to declare the type that the signal uses as a parameter, in this case, SerialSetting::Settings.
Replace
Q_DECLARE_METATYPE(Ui::SerialSetting)
with
Q_DECLARE_METATYPE(SerialSetting::Settings)
and you should be fine.

Why does my attempt at connecting a pushbutton to a lambda fail?

I have some issues while trying to use lambda expression to make connections between a pushbutton and a function I want to call when I click the button.
I am using Qt 5.6, with the compiler MinGW 4.9.2 (the default one). My code is the following :
In mainwindow.cpp :
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initBuildings();
initPage();
for (int i(0); i<buildings.size(); ++i) {
connect(static_cast<QAbstractButton*>(widgetlist.at(i).at(2)), &QAbstractButton::clicked, [this, i]() {
buildings.at(i).buy(amountMultiplier);});
}
}
void MainWindow::initBuildings()
{
Building b1 = Building("Building 1",100,1,200);
Building b2 = Building("Building 2",1000,10,2000);
buildings.append(b1);
buildings.append(b2);
}
void MainWindow::initPage()
{
for (int i(0); i<buildings.size(); i++) {
QList<QWidget *> buttons;
QLabel *namelabel = new QLabel(buildings.at(i).getName());
QLabel *amountlabel = new QLabel;
QPushButton *buybutton = new QPushButton(this);
QPushButton *upgradebutton = new QPushButton(this);
amountlabel->setFixedSize(50,40);
buybutton->setFixedSize(100,40);
upgradebutton->setFixedSize(100,40);
buttons.append(namelabel);
buttons.append(amountlabel);
buttons.append(buybutton);
buttons.append(upgradebutton);
widgetlist.append(buttons);
}
}
In mainwindow.h :
#include <QMainWindow>
#include <QScrollArea>
#include <QList>
#include <building.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void initBuildings();
void initPage();
Ui::MainWindow *ui;
int amountMultiplier;
QList<Building> buildings;
QList<QList<QWidget*>> widgetlist;
};
And "Building" is a class I have created which does not inherit from another class. The function I want to use is a public funtion of this class:
void buy(int amount) const;
It doesn't compile and I get several errors :
no matching function for call to 'MainWindow::connect(QAbstractButton*, void (QAbstractButton::*)(bool), MainWindow::MainWindow(QWidget*)::<lambda()>)
invalid use of incomplete type 'struct QtPrivate::QEnableIf< false, QMetaObject::Connection>
cannot convert '<lambda closure object>MainWindow::MainWindow(QWidget*)::< lambda()>{((MainWindow*)this), i}' (type 'MainWindow::MainWindow(QWidget*)::< lambda()>') to type 'const QObject*
I tried to change the lambda capture list, or to change the way I get the value in the lists but it doesn't change anything and I don't figure what is the problem. Maybe I am wrong in the use of the lambda ?
Two problems:
buildings.at() returns a const Building &, and the buy method is not const. You must index the buildings using [] instead.
The type returned from widgetlist.at(i).at(2) is definitely not QPushButton* - if it was, the code would compile. Even the error message indicates what the issue is:
no matching function for call to 'MainWindow::connect(QWidget* const&, void (QAbstractButton::*)(bool), [...])
This compiles:
// https://github.com/KubaO/stackoverflown/tree/master/questions/lambda-list-37615204
#include <QtWidgets>
struct Building {
void buy() {}
};
class Class : public QObject {
QList<Building> m_buildings;
QList<QList<QWidget*>> m_widgets;
public:
Class() {
for (int i = 0; i<m_buildings.size(); ++i)
connect(static_cast<QAbstractButton*>(m_widgets.at(i).at(2)), &QAbstractButton::clicked, [=] {
m_buildings[i].buy();
});
}
};
int main() {}
If you wish an extra measure of safety in face of programming errors on your part, replace the static_cast with a qobject_cast, it'll then abort if you cast a non-button instead of doing something possibly misleading.
According to the documentation, your lambda should accept a bool argument.

How to subclass in Qt?

I'd like to subclass QListWidgetItem, but I don't get what I'm doing wrong.
I subclassed QListWidget without any trouble using the same principles.
This is my header file :
#ifndef LSPROLISTITEM_H
#define LSPROLISTITEM_H
#include <QObject>
#include <QListWidgetItem>
class LsproListItem : public QListWidgetItem
{
Q_OBJECT
public:
explicit LsproListItem(QString &text, QObject *parent = 0);
signals:
public slots:
};
#endif // LSPROLISTITEM_H
and this is my cpp file :
#include "lsprolistitem.h"
#include <QListWidgetItem>
LsproListItem::LsproListItem(QString & text, QObject *parent) :
QListWidgetItem(text, parent)
{
}
I don't get the argument from my custom constructor, to create an object based on QListWidgetItem..
I try to create is this way :
LsproListItem *simpleText = new LsproListItem("Lorem ipsum");
But this fails with :
appcms.cpp: error : no matching constructor for initialization of 'LsproListItem'
LsproListItem *simpleText = new LsproListItem("Lorem ipsum");
^ ~~~~~~~~~~~~~
lsprolistitem.h:7: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [12]' to 'const LsproListItem' for 1st argument
class LsproListItem : public QListWidgetItem
^
lsprolistitem.h:: candidate constructor not viable: no known conversion from 'const char [12]' to 'QString &' for 1st argument
explicit LsproListItem(QString &text, QObject *parent = 0);
^
Quick solution(not the best): don't use reference:
public:
explicit LsproListItem(QString text, QObject *parent = 0);
//...
LsproListItem::LsproListItem(QString text, QObject *parent) :
Or
public:
explicit LsproListItem( const QString &text, QObject *parent = 0);
//...
LsproListItem::LsproListItem( const QString &text, QObject *parent) :
But there is another mistake. Remove Q_OBJECT macro because QListWidgetItem is not a QObject subclass and you can't use here signal and slots.
To prove: http://qt-project.org/doc/qt-5/qlistwidgetitem.html

invalid use of incomplete type/ foward declaration of

I've been looking for info about this problem .. but none of the solutions I've found have helped me, I really hope that you can helpme
maintabholder.h:
#ifndef MAINTABHOLDER_H
#define MAINTABHOLDER_H
#include <QMainWindow>
namespace Ui {
class MainTabHolder;
}
class MainTabHolder : public QMainWindow
{
Q_OBJECT
public:
explicit MainTabHolder(QWidget *parent = 0);
~MainTabHolder();
private:
Ui::MainTabHolder *ui;
};
#endif // MAINTABHOLDER_H
maintabholder.cpp:
#include "maintabholder.h"
#include "ui_maintabholder.h"
MainTabHolder::MainTabHolder(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainTabHolder)
{
ui->setupUi(this);
}
MainTabHolder::~MainTabHolder()
{
delete ui;
}
main.cpp:
#include "maintabholder.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainTabHolder w;
w.show();
return a.exec();
}
ui_maintabholder.h
#ifndef UI_MAINTABHOLDER_H
#define UI_MAINTABHOLDER_H
#include <QtCore/QVariant>
#include <QtWebKitWidgets/QWebView>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QHBoxLayout *horizontalLayout;
QTabWidget *tabWidget;
QWidget *comicViewer;
QWidget *comicSearcher;
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout_2;
QPushButton *pushButton;
QSpacerItem *horizontalSpacer;
QPushButton *pushButton_2;
QWebView *webView;
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
Form->setObjectName(QStringLiteral("Form"));
Form->resize(531, 308);
horizontalLayout = new QHBoxLayout(Form);
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
tabWidget = new QTabWidget(Form);
tabWidget->setObjectName(QStringLiteral("tabWidget"));
comicViewer = new QWidget();
comicViewer->setObjectName(QStringLiteral("comicViewer"));
comicViewer->setCursor(QCursor(Qt::ArrowCursor));
tabWidget->addTab(comicViewer, QString());
comicSearcher = new QWidget();
comicSearcher->setObjectName(QStringLiteral("comicSearcher"));
verticalLayout = new QVBoxLayout(comicSearcher);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
pushButton = new QPushButton(comicSearcher);
pushButton->setObjectName(QStringLiteral("pushButton"));
horizontalLayout_2->addWidget(pushButton);
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer);
pushButton_2 = new QPushButton(comicSearcher);
pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
pushButton_2->setEnabled(false);
horizontalLayout_2->addWidget(pushButton_2);
verticalLayout->addLayout(horizontalLayout_2);
webView = new QWebView(comicSearcher);
webView->setObjectName(QStringLiteral("webView"));
webView->setUrl(QUrl(QStringLiteral("about:blank")));
verticalLayout->addWidget(webView);
tabWidget->addTab(comicSearcher, QString());
horizontalLayout->addWidget(tabWidget);
retranslateUi(Form);
tabWidget->setCurrentIndex(1);
QMetaObject::connectSlotsByName(Form);
} // setupUi
void retranslateUi(QWidget *Form)
{
Form->setWindowTitle(QApplication::translate("Form", "Form", 0));
tabWidget->setTabText(tabWidget->indexOf(comicViewer), QApplication::translate("Form", "Comic Viewer", 0));
pushButton->setText(QApplication::translate("Form", "Go to SubManga", 0));
pushButton_2->setText(QApplication::translate("Form", "Download Comic", 0));
tabWidget->setTabText(tabWidget->indexOf(comicSearcher), QApplication::translate("Form", "Search For Comics", 0));
} // retranslateUi
};
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINTABHOLDER_H
the compiler errors are:
[...]\maintabholder.cpp: In constructor 'MainTabHolder::MainTabHolder(QWidget*)':
[...]\maintabholder.cpp:6:16: error: invalid use of incomplete type 'class Ui::MainTabHolder'
In file included from [...]\maintabholder.cpp:1:0:
[...]\maintabholder.h:7:7: error: forward declaration of 'class Ui::MainTabHolder'
[...]\maintabholder.cpp:8:7: error: invalid use of incomplete type 'class Ui::MainTabHolder'
In file included from [...]\maintabholder.cpp:1:0:
[...]\maintabholder.h:7:7: error: forward declaration of 'class Ui::MainTabHolder'
[...]\maintabholder.cpp: In destructor 'virtual MainTabHolder::~MainTabHolder()':
[...]\maintabholder.cpp:13:12: warning: possible problem detected in invocation of delete operator: [enabled by default]
[...]\maintabholder.cpp:13:12: warning: invalid use of incomplete type 'class Ui::MainTabHolder' [enabled by default]
In file included from [...]\maintabholder.cpp:1:0:
[...]\maintabholder.h:7:7: warning: forward declaration of 'class Ui::MainTabHolder' [enabled by default]
[...]\maintabholder.cpp:13:12: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
Can you give a help with this? I would appreciate it...
You are using a file generated by uic from Qt; you should verify that this tool successfully generate the file, by for example checking the build output and the file itself. Also, check that it is in the *.pro file (ie, that maintabholder.h is marked to be processed by uic).
I personnally advise to use the multiple inheritance method for ui :
// in maintabholder.h
// ...
#include "ui_maintabholder.h"
class MainTabHolder : public QMainWindow, public Ui::MainTabHolder
{
// ...
};
Simpler to use, and if you have a problem with the ui_*.h file the error is more explicit.
You should post ui_maintabholder.h.
You included the ui define head in your .cpp file, and defined a private member "Ui::MainTabHolder *ui;" in your .h file, so you need to add a forward declaration in your .h file(maintabholder.h:) before your class defination:
class Ui_MainTabHolder;
here Ui_MainTabHolder is your Ui class name, check your own project for correct one.