Correct way of promoting QTableWidget - qt

I need to have a custom qtablewidget for which I've promoted built in QTableWidget as follows :
Just created a class called Inventory, then inherited it from QTableWidget, added a qtablewidget into mainwindow from the qt designer and promoted it to Inventory class
//inventory.h
#ifndef INVENTORY_H
#define INVENTORY_H
#include <QTableWidget>
class Inventory : public QTableWidget
{
public:
Inventory(QTableWidget* parent = 0);
};
#endif // INVENTORY_H
//inventory.cpp
#include "inventory.h"
Inventory::Inventory(QTableWidget *parent)
: QTableWidget(parent)
{
setRowCount(3);
setColumnCount(3);
horizontalHeader()->setDefaultSectionSize(160);
verticalHeader()->setDefaultSectionSize(160);
}
but for some reason it just won't build correctly, throwing this instead:
error: invalid conversion from ‘QWidget*’ to ‘QTableWidget*’ [-fpermissive]
tableWidget = new Inventory(centralWidget);
^
in a ui_mainwindow.h file at the line
where tableWidget is declared as Inventory* tableWidget
what is wrong ??
How to fix this ?
p.s.
building with qt 5.7.1
and qtcreator 4.2.0

I think you are confused between your derived class which base is QTableWidget and the constructor for your derived Inventory class.
Obviously for Qt and Qt Editor to work, you need to define a
Inventory::Inventory(QWidget* parent = 0)
constructor, taking a QWidget as a parent widget. ( parent here in the sense of container widget, often a layout)
Your constructor is taking a QTableWidget* which seems very fishy to me, and your compiler is telling you that a QWdget* is not a to QTableWidget*, which makes sense.
Change the signature of the Inventory constructor should make the job

Related

How to receive event whenever a QWidget is added to QApplication's widget tree?

I want to inspect something application wide. Specifically I'd like to inspect every widget that is added to the application.
Similar thing can be done in JavaScript/HTML, where you can add DOM mutation listener which fires on DOM changes.
Can I listen on added widgets upon QApplication? Specifically, capture widgets added to QApplication object as children OR widgets added to any of the top level widgets or their children, subchildren, etc...
If not possible, what is best workaround available?
The most stable solution is likely to be to walk the object hierarchy every so often, starting with the QApplication as the root, and check each object with your predicate. This is going to be inefficient, which is why I asked for more information about what objects you actually want to query. On the other hand, for a test framework, you may not care so much about efficiency.
It might be possible to do something else, however. You can install event-filtering objects on any QObject, which define how they respond when they receive an event from Qt's event system. You could install an event filter on the root QApplication object (and recursively on any children created) that would check if the event is a QChildEvent and if added() returns true for it. If that's true, meaning a new child was added, you could then install this event filter onto that child as well. All other events would be passed on untouched. You can read more about installing event filters here. Essentially, a filter is a QObject subclass that defines the eventFilter() function, which returns true for events that should be filtered (stopped) and false otherwise. When this returns true, run your predicate on the newly-created object and install the same event filter on it.
One issue to be aware of with this is that the eventFilter() function only receives QObjects. You can learn if the object is a QWidget by calling isWidgetType(), but you don't know more than that. So as long as your predicate can make do with only methods and data defined for these general base classes, that should be OK.
As per #bnaecker's answer, here is some code:
AddChildEventFilter.h
#include <QObject>
class QEvent;
class AddChildEventFilter: public QObject {
Q_OBJECT
public:
AddChildEventFilter(QObject* parent=0);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
AddChildEventFilter.cpp
#include "AddChildEventFilter.h"
#include <QEvent>
#include <QDebug>
#include <QWidget>
#include <QChildEvent>
AddChildEventFilter::AddChildEventFilter(QObject* parent):QObject(parent) {}
bool AddChildEventFilter::eventFilter(QObject* obj, QEvent* event) {
if(QWidget* widget = dynamic_cast<QWidget*>(obj)) {
if(QChildEvent* chevent = dynamic_cast<QChildEvent*>(event)) {
if(chevent->added()) {
QObject* child = chevent->child();
qDebug()<<"Child added: "<<child->metaObject()->className()<<"to"<<widget->metaObject()->className();
child->installEventFilter(new AddChildEventFilter(child));
}
}
}
return false;
}
Usage:
#include "AddChildEventFilter.h"
#include <QWidget>
#include <QApplication>
void PrintAllEvents()
{
for(QWidget* widget: QApplication::allWidgets()) {
widget->installEventFilter(new AddChildEventFilter(widget));
}
}

Proper way to manually set the layout of a window in Qt

I need a QMainWindow layout to change depending on the number of cores.
Therefore I set it manually (not using the Design mode).
My question is:
After this layout was created, how can I refer to the widgets it contains?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//...
buildLayout();
//...
// Now I'd like to use something like this:
// ui->threadingTable->...
// However, it's not the member of ui
}
void MainWindow::buildLayout()
{
QWidget *window = new QWidget(this);
QTableView *threadingTable = new QTableView(window);
//...
QGridLayout *layout = new QGridLayout(window);
layout->addWidget(threadingTable, 0, 0);
//...
window->setLayout(layout);
this->setCentralWidget(window);
}
I can get the QLayoutItem out of this->centralWidget().
Or I can make all widgets in layout members of MainWindow class and access them directly.
However, I feel that neither of these is the right way.
Is there a way to pass the widgets to ui?
So that I could access them by calling
ui->threadingTable
Both options are fine. It is possible to get pointer to threadingTable from the main class member or directly from the objects hierarchy:
qDebug() << qobject_cast<QGridLayout *>(this->centralWidget()->layout())->itemAtPosition(0, 0)->widget();
qDebug() << this->centralWidget()->layout()->itemAt(0)->widget();
Of course, null verification may be required. You can also check this question QGridLayout: Getting the list of QWidget added.
The class Ui::MainWindow is automatically generated from the .ui xml form that can be generated in the Design mode: "Using a Designer UI File in Your Application"
Since the layout is constructed manually the .ui file and the ui instance is not needed at all. You can remove them from your project.
On the other hand, it is possible to use custom widgets even in the Design mode in .ui forms.
So, if you need some tricky object you can build the entire form in handy Design mode and then, for example, the standard QTableView may be promoted to your CustomTableView that is inherited from QTableView. That custom class may implement some special behavior.

Change Widget Constructor in UI

I ran into a problem with Qt while promoting my QGLWidget for the GUI.
Since the constructor of my QGLWidget is
GLWidget::GLWidget( const QGLFormat& format, QWidget* parent )
: QGLWidget( format, parent ),
m_vertexBuffer( QGLBuffer::VertexBuffer ) {}
So the object should get instantiated like this
QGLFormat glFormat;
glFormat.setVersion( 3, 3 );
glFormat.setProfile( QGLFormat::CoreProfile );
glFormat.setSampleBuffers( true );
GLWidget w( glFormat, parent );
But the ui_mainwindow.h does this automatically with
widget = new GLWidget(centralWidget);
which can't be modified due to the fact that the ui_mainwindow.h is created new every time the UI is recompiled. So I will probably have to tell in my maindwindow.cpp that the GLWidget is to be instantiated different from the standard constructor, but with a QFormat. Any idea how this is done?
I believe this can not be achieved using the Qt Designer auto-generated code.
There are atleast two different kind of solutions for this:
Subclass QGLWidget to set the QGLFormat in its MyGLWidget(QWidget* parent = 0); constructor.
or
Create the widget manually (without Qt Designer).
I prefer the latter one because I like to be in control.

Subclassing QUiloader and reimplementing createWidget function of it

I needed to read widget classnames, names etc from gui loaded via QUiloader.
And I got answer here that I needed to subclass QUiloader and reimplement its method.
I have MainWindow, and via menu/toolbar I load the file, and show it. And when I load I want to know what elements are in that gui to work further with them.
The code I got from a user here:
class UiLoader : public QUiLoader
{
Q_OBJECT
public:
QStringList *wlist;
UiLoader(QObject *parent = 0) : QUiLoader(parent) {}
virtual QWidget* createWidget(const QString &className, QWidget *parent =0, const QString &name = QString())
{
QWidget* widget = QUiLoader::createWidget(className, parent, name);
//here do my stuff with className, parent, name
return widget;
}
};
I used Uiloader to load my file. And it is working.
My question now is how I intercept createWidget before returning widget, I want to get the list of widget and then return Widgets.
I do not know how what is the efficient way to create a list as simple as this one:
0=>TextBox, 1=>Button, ...
I really do not care about the structure I just need to know which one comes first and what it is.
Thanks.
I wouldn't reimplement class loader at all honestly.. May be only if you need to 'inject' something into existing code which use QUiLoader a lot.. but in general only thing you need:
pWidget = ...->createWidget(...);
QList<QWidget *> widgets = pWidget->findChildren<QWidget *>();
here you go, your widgets contains list of all form components..

Changing QWidget with QGlWidget in Qt 4.8.0

I am working on an application that currently uses QWidgets for rendering moving images, and I am trying to move from using QWidgets to QGlWidgets, but my application keeps crashing.
The only modifications I've done are:
from this:
class MyClass : public QWidget
{
MyClass(QWidget *parent):QWidget(parent)
{
...
}
}
to this:
class MyClass : public QGlWidget
{
MyClass(QWidget *parent):QGlWidget(QGLFormat(QGL::SampleBuffers),parent)
{
...
}
}
Do I have to modify my code more, if so what other modifications are needed?
I am currently using Visual studio 2010, and qt 4.8.0
MyClass(QWidget *parent):QGlWidget(QGLFormat(QGL::SampleBuffers),parent)
{
...
}
It looks like you're creating a temporary QGLFormat object, which is being passed by reference to QGLWidget, and when that temporary object goes out of scope, you'll have an invalid reference.
I would use a different form of the constructor.
I found what the problem was.
In my QWidget class I had a member object QPainter, that I would reuse in the paint event. I kept searching and found that this is a bad practice, so now I declared a QPainter object at the beginning of the paint event and my problem is solved.

Resources