Qt two QList member variables causes crash - c++

so I'm not sure if this is a bug in Qt or if I just don't understand something, but i have this class:
class myClass : public QDialog, private Ui::myClass
{
Q_OBJECT
public:
explicit myClass(QWidget *parent = 0);
private:
QList<ushort> list1;
QList<ushort> list2;
}
I create this window by clicking on an action in another window:
void mainWindow::on_myClassAction_triggered()
{
myClass *mc = new mc(NULL);
mc->show();
}
So now things get weird. Even if i don't use list1 and list2 anywhere in myClass, the program will crash when i close or sometimes open myClass. If i comment out one, or both of them, it works. What is going on here??

I'm using Qt Creator. I just re-ran QMake and now it works. Definitely was some sort of bug within Qt/Qt Creator.

This is not a bug of any sort. It's a classic binary incompatibility problem: you've had some code that depended on the layout of some of your classes, but the outdated Makefiles did not capture that dependency. Thus when you changed the layout of the class, the dependent code didn't get recompiled. It would be way too expensive for qmake to rescan the entire project looking for such dependencies every time you build it. It's on you to re-run qmake when you change the code to introduce such binary incompatibilities.
For small projects, you may simply wish to always rebuild the code, forcing a qmake re-run.

Related

Qt QFileDialog::setDirectory funny behavior in Ubuntu 12.04

I have a class that inherits from QFileDialog. In the constructor, I call setDirectory and pass in the last directory visited (which the class keeps track of; see code below). On Windows, this works fine. And if I show the dialog multiple times, it is internally smart enough to resume at the last location (e.g. where the user saved a file before). This is the desired behavior.
On Ubuntu 12.04 (GCC 4.8 compiler), on the other hand, the system does not automatically resume where last left off if I call showFileDialog multiple times. So I tried adding the setDirectory call within that function as commented below, but that didn't change anything. Furthermore, if I take out setDirectory from the constructor so it is only called in showFileDialog, the file dialog opens to the folder from which the program was run. (i.e. setDirectory didn't work.) Subsequent calls to showFileDialog will open a file dialog starting in the directory requested.
So it seems like the call has a delayed effectiveness. Is this a Qt bug, or mine? Either way, how can I get the setDirectory call to be effective?
Example code:
QString FileDialog::defaultDir = QDir::homePath();
FileDialog::FileDialog(QWidget *parentWindow /*, ...*/)
: QFileDialog(parentWindow)
{
setDirectory(defaultDir);
//...
}
QString FileDialog::showFileDialog()
{
// Adding setDirectory(defaultDir) here doesn't help.
if(!exec())
{
return QString::null;
}
defaultDir = directory().path();
//...
}
It is not clear from the code above how you know that the path was changed. I'm not sure that directory() is responsible for that.
Consider using void QFileDialog::directoryEntered(const QString & directory) signal.
Workaround found:
I happen to set the dialog title (setWindowTitle()) every time I open a FileDialog. If I connect to the QFileDialog::windowTitleChanged signal and call setDirectory within the slot, it is effective.
This is an unintuitive workaround though, so I am open to better answers.

I would like to use the span slider from Qxt without having to install it. Is this possible?

I stumbled across a widget that provides you with a slider with two handles so you can select a range between an upper and lower limit.
I would like to use it without having to install all of Qxt though, since I am pretty sure this is the only thing that I need.
How can I deal with qxt_p() in order to use this widget as a standalone?
You need to add the following in the main class:
private:
QxtSpanSliderPrivate* d_ptr;
friend class QxtSpanSliderPrivate;
And in the following in the private class:
private:
QxtSpanSlider* q_ptr;
friend class QxtSpanSlider;
Also you should remove Qwt macros usage and replace qxt_d() and qxt_q() with direct access to q_ptr and d_ptr.
Each constructor of the main class should initialize both pointers:
QxtSpanSlider::QxtSpanSlider(Qt::Orientation orientation, QWidget* parent) :
QSlider(orientation, parent),
d_ptr(new QxtSpanSliderPrivate())
{
d_ptr->q_ptr = this;
//...
}
In case I forgot something, here is the gist. This code allowed me to successfully use QxtSpanSlider in Qt5.

Demo program error: '' was not declared in this scope

I am new to Qt and have started with the demo program found here. I have renamed the class AddressBook to Dialog. It compiles and executes just fine. I want to add my own code to the example, so I add a new label as a private member of the class:
private:
QCheckBox *native;
QLabel *integerLabel;
QLabel *doubleLabel;
QLabel *itemLabel;
...
QLabel *questionLabel;
QLabel *warningLabel;
QLabel *errorLabel;
QLabel *newLabel; // <== This is new
QErrorMessage *errorMessageDialog;
In the constructor Dialog::Dialog I (try to) allocate memory to the variables:
warningLabel = new QLabel;
warningLabel->setFrameStyle(frameStyle);
QPushButton *warningButton = new QPushButton(tr("QMessageBox::&warning()"));
errorLabel = new QLabel;
errorLabel->setFrameStyle(frameStyle);
QPushButton *errorButton =
new QPushButton(tr("QErrorMessage::showM&essage()"));
newLabel = new QLabel; // <== Error
newLabel->setFrameStyle(frameStyle);
As far as I can tell, I have created and allocated the variable correctly in this class, by copy and pasting *errorLabel and changing its name. Yet the compiler issues the error:
error: 'newLabel' was not declared in this scope
When I click the error, it takes me to the "new" line in the constructor. If I remark out the two lines in the constructor referring to newLabel, the program compiles. It IS in this scope in my mind. What mistake am I making here? How do we prevent these type issues in the future? (I have searched tens of similar posts and was able to identify the OP's mistake in 30s or less, but I cannot find my own, nor can I find a post where variables are declared in the class, but not found in the constructor.)
Thanks in advance,
Kyle
I have solved the problem. Even though it is not the answer I expected, I post this answer just in case it is helpful to the rest of the community.
I created a new project and copied the cpp/h files from the non-working project into the new project. The new project compiles. With the new project I can now add other private variables to the class and access them in the constructor (as well as the IDE). All parameters I have easy access to show the projects to be identical, yet one compiles and the other does not. I can only conclude the project itself somehow became corrupted (which does not inspire confidence).
While I am relieved it was not a stupid programmatic mistake on my part, I am disappointed in not being able to find and fix whatever was wrong with the project files. Thanks to all those who offered suggestions.

Qt Designer undefined symbol with Custom Widget plugin

I am using Qt 4.7.2 under Fedora 14.
I have a working library of custom widgets which I am trying to integrate into Qt Designer.
There is a simple widget base class, then some more complex widgets inheriting from it.
The simple widget integrates fine, but I have a problem with the more complex ones.
The problem comes from the fact that that the more complex ones require a special structure to be passed to them on creation. So my code for creating a complex widget in the plugin is:
QWidget *myPlugin::createWidget(QWidget *parent)
{
my_struct *xyz = new my_struct;
return new myWidget("MyWidget",xyz, parent);
}
my_struct is just a simple C style struct with ints, doubles and arrays.
Then when I start Qt Designer with this plugin I get:
/usr/lib64/qt4/bin/designer: symbol lookup error: /usr/lib64/qt4/plugins/designer/libMyPlugin.so: undefined symbol: _ZN8MyWidgetC1E7QStringP17my_structP7QWidget
I am building a release version of the plugin, not a debug version.
I also tried defining xyz as a static class variable in the plugin and just passing its address to the constructor, but I still get the same error.
I also tried adding xyx as an unused static class variable to my simple widget and that does not give the error, so the error seems to be coming from the call to the myWidget constuctor.
Can anyone help me resolve this?
Thanks Arne,
You were right.
I added my library explicitly to the plugin's .pro file and then it worked.
What puzzles me is how could I build the plugin with no errors without the library?
And why did my simple widget work without the library?
The error message looks as if the linker did not find a definition for the constructor myWidget(QString, my_struct*, QWidget*). Have you added the relevant source file to your release build? Do you actually have a definition for this constructor? It is also possible that you have to exchange the object file linking order. I have seen this with larger projects in the past, so I wouldn't be too surprised. The object file containing the definition needs to be stated before the one using the definition.

Showing two windows in Qt4

My friend and I have each created parts of a GUI using Qt 4. They both work independently and I am trying to integrate his form with the my main window. As of now this is the code I am using to try and load his form:
//connect buttons and such
connect(exitbtn, SIGNAL(triggered()),this,SLOT(terminated()));
connect(add, SIGNAL(triggered()),this,SLOT(add_rec()));
void MainWindowImpl::add_rec()
{
//form quits as soon as it loads...?
DialogImpl dia;//name of his form
dia.show();
}
I have included his header file. The program compiles but when I hit the trigger his form loads up for maybe half a second and then closes. Does anyone know what I am doing wrong?
You have almost get it right. This is because the RAII of C++. If you allocate the Dialog on stack, it would be destructed as soon as the function return.
Assuming MainWindowImpl inherits publically from QWidget, you're looking for this:
void MainWindowImpl::add_rec()
{
// passing "this" to the constructor makes sure dialog will be cleaned up.
// Note that DialogImpl will need a constructor that takes a
// QObject* parent parameter.
DialogImpl* dialog = new DialogImpl(this);
dialog->show();
}
Look at the Qt documentation for examples of how the constructors should look.
Apparently QT4 only allows one instance of an object at a time, however pointers are another matter. Change both the main.cpp and what ever your main window to look something like this:
DialogImpl *dia=new DialogImpl;
dia->show();