Changing QWidget with QGlWidget in Qt 4.8.0 - qt

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.

Related

How to show QWindow inside QMdiArea

I have a OpenGLWindow class that inherits QWindow and QOpenGLFunctions_3_3_Core, it's opening collada dae files (works fine in simple project).
Also i have a pdfViewer class that inherits from QWidgets.
I want to display this windows in MdiArea class:
void MainViewer::CreateSubWindow(QString &pathToFile)
{
if (pathToFile.endsWith(".pdf"))
{
PdfViewer *newViewer=new PdfViewer(&pathToFile);
m_LoadedFiles->insert(pathToFile,newViewer);//this qhash save inform of current opened docs, i need it
m_MainMdiArea->addSubWindow(static_cast<PdfViewer*>(m_LoadedFiles->value(pathToFile)))->show();
}
if (pathToFile.endsWith(".dae"))
{
DaeViewer *newViewer=new DaeViewer(pathToFile);
m_LoadedFiles->insert(pathToFile, newViewer);
m_MainMdiArea->addSubWindow(m_LoadedFiles->value(pathToFile))->show();
static_cast<DaeViewer*>(m_LoadedFiles->value(pathToFile))->OpenGLWindow::show();
newViewer->setAnimating(true);
}
mdiSubWindowsCount++;
}
Getting the same result:
I understood that show method of QWidget and QWindow is different.
I want to see my openGlWindow in myMdiArea but don't know how to call show method
Solution:
DaeViewer *newViewer=new DaeViewer(pathToFile);
m_MainMdiArea->addSubWindow(QWidget::createWindowContainer(newViewer))->show();

Correct way of promoting QTableWidget

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

How to handle QComboBox signals in inner classes

I am using Qt5 and I have created a class "outer" with an "inner" class. The "inner" class has two QComboBox "cb1" and "cb2" objects as private variables.
In the principle, the displayed text of the second QComboBox, "cb2", depends of the current text of the first QComboBox "cb1". In fact, it is easy to implement a connection between these two, using signals and slots by writing the appropriate slot.
The problem is that Qt does not support writing slots inside an inner class. That makes me confused.
How can I handle a connection between these two QComboBoxes in the "inner" class?
For some code,
class Outer : public QDialog
{
Q_OBJECT
// private variables;
class Inner : public QWidget
{
QComboBox *cb1, *cb2;
// Other variables;
public:
// Public methods
public slots:
void setIndex(int i);
};
// Other things;
};
Inner Implementation
Outer::Inner::Inner()
{
// Useless things;
connect(cb1, SIGNAL(currentIndexChanged(int)), this, SLOT(setIndex(int)));
}
Outer::Inner::setIndex(int i)
{
// Some stuff to retrieve the correct index in cb2;
}
In Qt 5, any method can be connected to a signal, whether marked as a slot or not, so what you are describing is a non problem.
You need to use the modern connect syntax, and it will work fine:
connect(cb1, &QComboBox::currentIndexChanged, this, &Outer::Inner::setIndex);
Of course, nothing else will work correctly: the qobject_cast mechanism won't work, metadata will be wrong, etc.
An inner class cannot be a QObject. I completely fail to see the point of it. Make it a local class in the .cpp file instead of an inner class.
From your code I don't get a reason why you need an inner class at all.
If you just want to avoid the possibility to use the Class somewhere else, I would recommend to put it in a anonymous namespace.
namespace {
class YourAnonymousClass{
...
}
}
class TheOtherClass {
...
}

Tabbed Dialog Box using Qt Designer

I'm new to Qt and having a problem with the TabbedDialog box designed using the Qt Designer.
I have a Dialog dlg on which i have placed a tabWidget MyTabWidget containing two tabs Tab1 and Tab2. I want to make separate cpp files for each tab and define the functions in their respective files. the problem i'm having is how to access the UI widgets of the dialog dlg in these respective files.
There are a few steps to be taken here which is well-explained in the following documentation.
1) Include #include "ui_foo.h"
This is necessary to access the UI elements in your code. This is the file that is available through the QtDesigner and ui compiler, aka. uic process.
2) Either inherit Ui::Foo or have an object with composition with it within your class. It would be something like:
class Foo : public QWidget
{
Q_OBJECT
public:
Foo(QWidget *parent = 0);
private:
Ui::Foo ui;
};
or
class Foo : public QWidget, private Ui::Foo
{
Q_OBJECT
public:
Foo(QWidget *parent = 0);
};
3) Then you can use this instance to access the widgets (something like ui->foo) created by the QtDesigner application.
bool Foo::doStuff()
{
ui->foo()->doStuff();
}
You probably do not wish to have two separate source files and classes as you wrote, but if you wish, the above steps could be applied for both.
That being said, I think it is better if you go through the aforementioned documentation because it is lot more detailed about the several approaches, and how to access the UI components in your source code generated by QtDesigner.
You can pass a tab pointer to your function you want to use. Something like:
void Class1::yourFunction1(QWidget *tab1);
void Class2::yourFunction2(QWidget *tab2);
You can access these widget tabs like:
ui->tab
if it was created in QtDesigner.

calling Qt's QGraphicsView::setViewport with a custom QGLWidget

I've derived from QGLWidget before, like so:
class MyGLWidget : public QGLWidget
{
public:
// stuff...
virtual void initializeGL() { /* my custom OpenGL initialization routine */ }
// more stuff...
};
However, I find that if I try to initialize a QGraphicsView with my custom QGLWidget as the viewport, initializeGL doesn't get called (setting a breakpoint within the Qt library, neither does QGLWidget::initializeGL() when created plain).
// initializeGL, resizeGL, paintGL not called
ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));
// initializeGL, resizeGL, paintGL *still* not called
ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer)));
Where is the correct location to place the code that currently resides in MyGLWidget::initializeGL()?
The setupViewport slot of a custom QGraphicsView could be used to call updateGL() on the QGLWidget, which will cause initializeGL() to be called.
class MyGraphicsView : public QGraphicsView
{
//... The usual stuff
protected slots:
virtual void setupViewport(QWidget *viewport)
{
QGLWidget *glWidget = qobject_cast<QGLWidget*>(viewport);
if (glWidget)
glWidget->updateGL();
}
};
So what I've found is QGraphicsView installs a custom eventFilter on your QGLWidget viewport so it never sees the initialize/resize/repaint events. This probably was done to make it work properly with drawBackground() etc.
My current best resolution is to catch the desired event either in QGraphicsView::resizeEvent()/etc, or install a custom eventFilter on your QGLWidget derived class to catch the resize/paint/etc events before QGraphicsView's custom eventFilter swallows them.
The pain, the pain, ... integrating widgets derived from QGlWidgets into QGraphicsView is no fun, of the parts of Qt that I know this is definitely one of the messier areas. I ended up using a part of kgllib (out of kde) called widgetproxy that is a very decent wrapper around a QGlWidget. I modified it to fit my needs but works reasonably well for most general cases where you want to use an exisiting class derived from QGlWidget inside a QGraphicsView and draw other things on top of it.
initializeGL() won't get called until the first call to either paintGL() or resizeGL() and not when the widget is constructed. This may happen as late as when the widget is first made visible.
I'm going to go ahead and answer my own question. This isn't optimal, but this is how I've gotten around the problem.
Instead of
ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));
I've got this instead:
ui.graphicsView->setViewport(new QGLWidget(new CustomContext(QGLFormat(QGL::SampleBuffers))));
CustomContext is a class that derives from QGLContext. I've overridden the create member, like so:
virtual bool create(const QGLContext *shareContext = 0)
{
if(QGLContext::create(shareContext))
{
makeCurrent();
/* do my initialization here */
doneCurrent();
return true;
}
return false;
}
I don't think this is the optimal way to do this, but it's better than the alternative of not having a specific initialization step at all. I'd still be happy to have someone leave a better answer!

Resources