How to handle QComboBox signals in inner classes - qt

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 {
...
}

Related

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.

How to Clear all the Widgets in Parent Widgets?

I am using the constructor QWidget(QWidget *parent). This parent widget contains a lot of child widgets. I need to clear all the child widgets from the parent at runtime. How can I do this?
Previous answer is wrong!! You cannot use findChildren to delete a widget's children, because Qt4's findChildren recursively lists children. Therefore, you will delete children of children, which then may be deleted twice, potentially crashing your app.
More generally, in Qt, taking a list of QObject pointers and deleting them one by one is dangerous, as destroying an object may chain-destroy other objects, due to the parent ownership mechanism, or by connecting a destroyed() signal to a deleteLater() slot. Therefore, destroying the first objects in the list may invalidate the next ones.
You need to list children widgets either by:
Passing the Qt::FindDirectChildrenOnly flag to findChild if you are using Qt5 (which did not exist when the question was asked...)
Using QLayout functions for listing items,
Using QObject::children, and for each test if it is a widget using isWidgetType() or a cast
Using findChild() in a loop and delete the result until it returns a null pointer
To take care of the recursivity problem pointed out by #galinette you can just remove the widgets in a while loop
while ( QWidget* w = findChild<QWidget*>() )
delete w;
Summarizing and supplementing:
For Qt5 in one line:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
For Qt5 for a lot of children, using setUpdatesEnabled():
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
Note that this is not exception safe! While Qt does not at this time appear to throw exceptions here, the signal destroyed() could be connected to code that does throw, or an overridden Object::childEvent(QChildEvent*) could throw.
Better would be to use a helper class:
class UpdatesEnabledHelper
{
QWidget* m_parentWidget;
public:
UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); }
~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); }
};
...
UpdatesEnabledHelper helper(parentWidget);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
For Qt4:
QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
if (widget->parentWidget() == parentWidget)
delete widget;
Removing from the QLayout works in both Qt4 and Qt5:
QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
delete child;
QObjects (and therefore QWidgets) remove themselves (automagically) from their parent in their (QObject) destructor.
From Qt docs
The following code fragment shows a safe way to remove all items from a layout:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
You can use the following in your parent widget class:
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}

Is it possible to do a #define in Adobe Flex?

I'm looking for a way to do something similar to a c/c++ #define in adobe flex.
I'd like to have lots of different paths a project build can take depending on wither or not something was defined. Does such a thing exist in flex?
I know there is ways to set global variables but that wont really suit my purpose. being able to have structures with numerous #ifndefined and such is really what i'm in need of.
thanks!
Actually MXMLC (the compiler in the Flex SDK) does support some limited preprocessor features. You can use them to pass in constant values, or to simulate #ifdef / #ifndef type functionality.
Check out this documentation
Example 1:
This code only gets executed if the -define=CONFIG::debugging,true flag is passed to the compiler:
CONFIG::debugging {
// Execute debugging code here.
}
Example 2:
Change the color of the button depending on if you defined 'CONFIG::release' or 'CONFIG::debugging'
// compilers/MyButton.as
package {
import mx.controls.Button;
CONFIG::debugging
public class MyButton extends Button {
public function MyButton() {
super();
// Set the label text to blue.
setStyle("color", 0x0000FF);
}
}
CONFIG::release
public class MyButton extends Button {
public function MyButton() {
super();
// Set the label text to red.
setStyle("color", 0xFF0000);
}
}
}
Just to keep this info here, it is possible to use the C Pre-Processor (CPP) with AS3 if you want to. It provides more powerful features than the ones built into MXMLC, if you need them. Example:
http://osflash.org/flex2cpp

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