December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

[Merged] Inheriting Ui::MainWindow to add QListWidgetItem to a give ListWidget

Page  
1

Ok this is a rather difficult problem i have run into. I am attempting to inherit the ui to a given class. From this class i have functions that add list items to a list located on the parent widget. I can achieve this with no problem. Once I implement however, it throws a segFault. any thoughts? here are some code snipets.

from my header

  1. class MedicationButtonEventHandler : QWidget , public  Ui::MainForm
  2. {
  3.     Q_OBJECT
  4. public:
  5.     virtual ~MedicationButtonEventHandler();
  6.     static MedicationButtonEventHandler* GetInstance();

etc…..

from my cpp

  1. QListWidgetItem* MedicationButtonEventHandler::Medication_Add_Clicked()
  2. {
  3.     Ui::MainForm *ui = new Ui::MainForm;
  4.     MedicationButtonEventHandler::listItem = new QListWidgetItem(QIcon(":/img/medications.png"),
  5.                                                     ui->txt_Medicaiton_MedicationName->text()+ " - "+
  6.                                                     ui->txt_Medication_Dosage->text()+
  7.                                                     ui->cmb_Medication_Dosage->currentText()+ " - " +
  8.                                                     ui->txt_Medication_Quantity->text()+
  9.                                                     ui->cmb_Medication_Quantity->currentText()+" - " +
  10.                                                     ui->cmb_Medication_Method->currentText()+ " - " +
  11.                                                     ui->txt_Medication_Frequency->text()+" - " +"Date Started: "+
  12.                                                     ui->txt_Medication_DateStarted->text()+ " Date Modified: " +
  13.                                                     ui->txt_Medication_DateModified->text()+ " Date Stopped: " +
  14.                                                     ui->txt_Medication_DateStopped->text()+ " - " +
  15.                                                     ui->txt_Medication_PrescribingDoctor->text()+ " - " +
  16.                                                     ui->txt_Medication_Pharmacy->text()+ " - " +
  17.                                                     ui->txt_Medication_PharmacyPhone->text()+ " - " +
  18.                                                     ui->txt_Medication_PrescriptionNumber->text()+ " - " +
  19.                                                     ui->cmb_Medication_MedicationType_2->currentText()
  20.                                                     ,ui->lst_Medication_List);
  21.  
  22.     listItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
  23.     listItem->setCheckState(Qt::Checked);;
  24.     ui->lst_Medication_List->insertItem(nextInstance,listItem);
  25.  
  26.     return listItem;
  27.  
  28.     delete listItem;
  29.  
  30.     delete ui;
  31.  
  32.     MedicationButtonEventHandler::nextInstance++;
  33.  
  34. }

when i call this function to test it it segfaults. I know it is recommended that i inherit ui privately, but i need to be able to actually change attributes of the ui. Thanks for any help.

edit: code highlighted / Denis Kormalev

28 replies

December 3, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1607 posts

Please use @ tags for code. I fixed it at this post, but please don’t forget them in future.

December 3, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1607 posts

About problem. Maybe there were some code eated by textile, but in this code you have return and some code after it (that obviously will be not executed).
Also as I understood MedicationButtonEventHandler::listItem is static member of class. Is it defined and initialized?

December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

Its actually a pointer to a QListWidgetItem at the class level

December 3, 2010

Volker Volker
Ant Farmer
5331 posts

The segfault is beacause you did not call

  1. setupUi(this);

Also, there are some more mistakes:

  • you do not have a constructor for your class. This is a must have one, and you mast call the base class constructor (QWidget in your case) with the parent. Otherwise you will not have the parent-child relationship and QObject does not delete your objects
  • you usually setup the UI in the constructor with that mentioned setupUi() method
  • in your case, every time you call MedicationButtonEventHandler::Medication_Add_Clicked() you construct an new ui. If you call it 10 times you end up with 10 ui instances.

December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

Right I realize the 10 ui instances part, as far as a constructor and such i do have one, i did not include my entire header file just where i was inheriting. I dont want it to be a child of anything, I want to be able to call this function on some click event, and add an item to an already existing widget from the actual UI designer. I guess im not fully understanding the need to call setupUI when im not trying to create a new one. I am relatively new to QT and as such i do not know all the ins and outs yet.

December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

I should probably mention that this is a singleton and my constructor is private

December 3, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1607 posts

As for me class design I see in your code is really strange. Are you sure you need such design? Or maybe you simply triyng to do something that can use more common design but don’t know how?
Try to describe more, maybe we can help you to use Qt more effectively.

December 3, 2010

Volker Volker
Ant Farmer
5331 posts

Wether the constructor is private does not matter. At the time your widget is constructed, it should be constructed correctly and complete.

As far as I understood:

  • This class is a widget (as it inherits from QWidget)
  • This is a singleton (which does not matter in our case)
  • You have kind of button and/or action that you click on and in a slot connected to the clicked() or triggered() signal you want to create a new list item that is added to your list view

If that is true:

  • call setupUi(this) in the constructor
  • no need to create an instance of the Ui class with new (line 3 in your cpp), as your Widget already inherits this class! Call the ui members without “ui->”
  • In your slot, create the list item and add it to the list view. If you setup the ui in the constructor and if you have called setupUi() you won’t get a segmentation fault.

December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

The QWidget was a mistake from something i had tried early on. Its not a widgetclass at all. I actually inherit QObject. As far as actually setting the ui the way you described, does not work either.As far as my design, i simply want to be able to handle function definitions outside of the main form to prevent it from being 8000 lines. So to do this i need to abstract out the Ui aspect of much of it( the things that need to be dynamically generated based on user input). So I simply want a function that, when called, will add a new listitem to an already existing listwidget ( located in ui_MainForm.h). The code works if moved into MainForm. I just cant seem to get the interface to work properly. I should be able to simply inherit from the Mainform( which will carry all of its child widgets with it) and make whatever changes i need to make as needed. At this point I am not even concerned with the slots and signals. I just wish to call a function located outside of Mainform that changes mainform itself( or its children). Does that better explain things?

December 3, 2010

Volker Volker
Ant Farmer
5331 posts

Sorry, I don’t understand what you’re trying to do. It sounds like you’re doing it over complicated. If your business logic has 8000 lines, it hat 8000 lines of code – regardles if it is in one file or split over 20.

Adding an item is in my opinion a function that belongs to the list widget class (reps. the form that does contain the list widget). You should add method (probably as a slot) that you call with the relevant data and let the method create the list view item. That also has the advantage that you can change your implementation afterwards without the need to change all your other code.

Regarding the UI (classes):
A UI class generated with uic from a .ui file only does make sense and is functionable when you marry it with a QWidget, that’s what setupUi() is for. If you don’t call that, your UI is useless.

I’d suggest you make yourself comfortable with the principles of the uic generated classes first. Use Chapter Using a Designer UI File in Your Application [doc.qt.nokia.com] of Qt Designer documentation as a starting point

And as an advice: Make it work correctly in the first place and do the optimizations afterwards. If you have a working application – made straight forward – it is often much easier to “beautify” it later.

December 3, 2010

webmaster.skelton webmaster.sk..
Lab Rat
65 posts

Thanks for the help, It just seems like QT makes it difficult for this sort of design. I know everything works as i originally had it that way to make sure it did. Ill figure out what i need eventually. Thanks

December 3, 2010

Tobias Hunger Tobias Hunger
Hobby Entomologist
3373 posts

I would recommend keeping the UI class small by using signals, slots and accessors. Add signals for all the ui actions that are of interest and connect them to other objects implementing the business logic. Those can in turn trigger slots in the UI to trigger the changes you want. That way the internals of the UI stay in one class and you will not need to fix up code all over the place when you decide to rework the UI.

December 3, 2010

Tobias Hunger Tobias Hunger
Hobby Entomologist
3373 posts

By the way: EventHandler has a well defined meaning in Qt. Are you using the term in a similar way? If not that might confuse Qt coders that will have to maintain the code later on:-)

December 3, 2010

Volker Volker
Ant Farmer
5331 posts

I’m sure it can be done the way you intend to do it. But sometimes one just screws up everything. I’ve been bitten often enough :-) I usually start from scratch then.

Regarding your problem:
Of course you can create a list widget item with new in a separate class and add it to the ui of another class. But that couples the two classes tightly, which is not what you want most times, since one class needs to know the internals of the other. Maybe you decide to drop QListWidget in favor of QListView and specially design item model. You would have to change all your code!

It’s usually better to send messages to the other class and ask it to do the desired task (using signals/slots in Qt). Since the actual implementation is not public in this case, you easily could do the refactoring I mentioned in the paragraph before.

Give it a try and you will get beautiful and easy to write and maintainable code :-)

December 4, 2010

erapid erapid
Lab Rat
14 posts

Pure answer is that U call methods on uninitialised pointers.

Any form you create, throwing the widgets in the designer – just a collection of widgets. Try to open ui file in a text editor ;) ( But better don’t save it in editor )

So, when UIC eats form file it produces a Collection class: set of pointers with two methods – setupUi( Parent* ) and retranslateUi. Parent is QWidget in common case.

setupUI is a key! It creates and inits real widgets and sets them Parent as parent.

No setupUi – no real objects and then U’ll get segfault in ui->txt_Medicaiton_MedicationName->text().

See qt documentation [doc.qt.nokia.com]

And Yes – UR code is strange

  1.     return listItem;
  2.  
  3.     delete listItem;
  4.  
  5.     delete ui;
  6.  
  7.     MedicationButtonEventHandler::nextInstance++;

Do U catch that last three rows never runs?

Page  
1

  ‹‹ Non-virtual destructor in QNetworkAccessManager      [solved]Xml Schema and QDom ››

You must log in to post a reply. Not a member yet? Register here!