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



  • 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

    @
    class MedicationButtonEventHandler : QWidget , public Ui::MainForm
    {
    Q_OBJECT
    public:
    virtual ~MedicationButtonEventHandler();
    static MedicationButtonEventHandler* GetInstance();

    @
    etc.....

    from my cpp
    @
    QListWidgetItem* MedicationButtonEventHandler::Medication_Add_Clicked()
    {
    Ui::MainForm *ui = new Ui::MainForm;
    MedicationButtonEventHandler::listItem = new QListWidgetItem(QIcon(":/img/medications.png"),
    ui->txt_Medicaiton_MedicationName->text()+ " - "+
    ui->txt_Medication_Dosage->text()+
    ui->cmb_Medication_Dosage->currentText()+ " - " +
    ui->txt_Medication_Quantity->text()+
    ui->cmb_Medication_Quantity->currentText()+" - " +
    ui->cmb_Medication_Method->currentText()+ " - " +
    ui->txt_Medication_Frequency->text()+" - " +"Date Started: "+
    ui->txt_Medication_DateStarted->text()+ " Date Modified: " +
    ui->txt_Medication_DateModified->text()+ " Date Stopped: " +
    ui->txt_Medication_DateStopped->text()+ " - " +
    ui->txt_Medication_PrescribingDoctor->text()+ " - " +
    ui->txt_Medication_Pharmacy->text()+ " - " +
    ui->txt_Medication_PharmacyPhone->text()+ " - " +
    ui->txt_Medication_PrescriptionNumber->text()+ " - " +
    ui->cmb_Medication_MedicationType_2->currentText()
    ,ui->lst_Medication_List);

    listItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
    listItem->setCheckState(Qt::Checked);;
    ui->lst_Medication_List->insertItem(nextInstance,listItem);
    
    return listItem;
    
    delete listItem;
    
    delete ui;
    
    MedicationButtonEventHandler::nextInstance++;
    

    }
    @

    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]



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



  • 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?



  • Its actually a pointer to a QListWidgetItem at the class level



  • The segfault is beacause you did not call

    @
    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.


  • 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.



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



  • 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.



  • 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.


  • 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?



  • 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 ":http://doc.qt.nokia.com/4.7/designer-using-a-ui-file.html 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.



  • 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


  • Moderators

    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.


  • Moderators

    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:-)



  • 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 :-)



  • 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":http://doc.qt.nokia.com/4.7/designer-using-a-ui-file.html

    And Yes - UR code is strange
    @
    return listItem;

    delete listItem;
    
    delete ui;
    
    MedicationButtonEventHandler::nextInstance++;
    

    @
    Do U catch that last three rows never runs?



  • Ok so I am back now. After changing a few things around this is what i have ended up with:

    @MedicationButtonHandler::MedicationButtonHandler(QWidget *parent) : QDialog(parent), ui(new Ui::EditMedicationForm) , mainUi(new Ui::MainForm)
    {

    ui->setupUi(this);
    

    }

    QListWidgetItem* MedicationButtonHandler::MedicationEdit_Add_Clicked()
    {

    MedicationButtonHandler::listItem = new QListWidgetItem(QIcon(":/img/medications.png"),
    
                                                    ui->txt_Medication_Name->text()+ " - "+
                                                    ui->txt_Medication_Dosage->text()+
                                                    ui->cmb_Medication_Dosage->currentText()+ " - " +
                                                    ui->txt_Medication_Quantity->text()+
                                                    ui->cmb_Medication_Quantity->currentText()+" - " +
                                                    ui->cmb_Medication_Administered->currentText()+ " - " +
                                                    ui->txt_Medication_Frequency->text()+" - " +
                                                    ui->txt_Medication_DateStarted->text()+ "-" +
                                                    ui->txt_Medication_DateModified->text()+ " _ " +
                                                    ui->txt_Medication_PrescribingDoctor->text()+ " - " +
                                                    ui->txt_Medication_Pharmacy->text()+ " - " +
                                                    ui-> txt_Medication_PharmacyPhone->text()+ " - " +
                                                    ui-> txt_Medication_PrescriptionNum->text()
                                                    ,mainUi->lst_Medication_List);
    
    
    listItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
    
    mainUi->lst_Medication_List->insertItem(nextInstance,listItem);
    
    
    
    //delete listItem;
    
    
    
    
    
    
    return listItem;
    

    }

    @

    This still renders a seg fault even when i setup the Ui for the class.

    @



  • ok so here is the rundown, i simply wish to add a listItem to an exisisting listwidget on the mainform. This item needs to be added from another form called edit. When I actually try to connect the slots with the button clicked signal, I get a segfault. I am assuming it is because i can not access the mainForm widgets but I am not sure why. Here is some code.

    Header:

    @class MedicationButtonHandler : public QDialog , private Ui::EditMedicationForm , private Ui::MainForm
    {

    Q_OBJECT
    

    public:
    virtual ~MedicationButtonHandler();
    static MedicationButtonHandler* GetInstance();

    QListWidgetItem* listItem;
    

    public slots:
    QListWidgetItem * MedicationEdit_Add_Clicked();

    void Medication_Delete_Clicked();
    

    // QString* MedicationNotesClicked();

    // void MedicationLearnMoreClicked();

    // QString* MedicationFilesClicked();

    // void MedicationDiscontinueClicked();

    private:
    MedicationButtonHandler(QWidget parent = 0);
    static MedicationButtonHandler
    p_MedicationButtonHandler;
    static int nextInstance;
    Ui::EditMedicationForm *ui;
    Ui::MainForm *mainUi;

    };@

    cpp:

    @MedicationButtonHandler::MedicationButtonHandler(QWidget *parent) : QDialog(parent), ui(new Ui::EditMedicationForm) , mainUi(new Ui::MainForm)
    {

    ui->setupUi(this);
    

    }

    QListWidgetItem* MedicationButtonHandler::MedicationEdit_Add_Clicked()
    {

    MedicationButtonHandler::listItem = new QListWidgetItem(QIcon(":/img/medications.png"),
    
                                                    ui->txt_Medication_Name->text()+ " - "+
                                                    ui->txt_Medication_Dosage->text()+
                                                    ui->cmb_Medication_Dosage->currentText()+ " - " +
                                                    ui->txt_Medication_Quantity->text()+
                                                    ui->cmb_Medication_Quantity->currentText()+" - " +
                                                    ui->cmb_Medication_Administered->currentText()+ " - " +
                                                    ui->txt_Medication_Frequency->text()+" - " +
                                                    ui->txt_Medication_DateStarted->text()+ "-" +
                                                    ui->txt_Medication_DateModified->text()+ " _ " +
                                                    ui->txt_Medication_PrescribingDoctor->text()+ " - " +
                                                    ui->txt_Medication_Pharmacy->text()+ " - " +
                                                    ui-> txt_Medication_PharmacyPhone->text()+ " - " +
                                                    ui-> txt_Medication_PrescriptionNum->text()
                                                    ,lst_Medication_List);
    
    
    listItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
    
    mainUi->lst_Medication_List->insertItem(nextInstance,listItem);
    
    
    
    
    
    
    
    
    
    
    return listItem;
    

    }

    @

    I am not sure as to why this is not working,



  • Well, first off, you should either inherit from your UI class, or include it as a pointer - not both.

    Your call to ui->setupUi() is going to crash, because you have never initialized those ui or mainUi pointers.



  • Remove the ui pointers and change the constructor to use
    @
    Ui::EditMedicationForm::setupUi(this);
    Ui::MainForm::setupUi(this);
    @

    or

    Remove the Ui::* inheritance and change the constructor to use
    @
    ui = new Ui::EditMedicationForm;
    ui->setupUi(this);
    mainUi = new Ui::MainForm;
    mainUi->setupUi(this);
    @



  • U didn't setup mainUi, so mainUi->lst_Medication_List is a pointer to nowhere

    I'm sure Qt doesn't like to receive
    @ new QListWidgetItem( const QIcon & icon, const QString & text, QListWidget * parent = 0, int type = Type )@ with broken parent



  • It is not intended that setupUi() of two different Ui classes are called with the main QWidget (this). At best the resulting Ui will look strange. I cannot see any use for this either.

    You should have two classes, with .h and .cpp, for either EditMedicationForm and for MainForm.

    Your call to mainUi->lst_Medication_List crashes, because you did not call setupUi on mainUi, so the members of mainUi are not yet created.



  • Ok i understand that, but i need to be able to access and modify widgets located in two different UIs, For example, i have a list widget in main form and EditMedicationForm is where the attributes are changed. So I click add new, a new form pops up, I enter the information into the field, and i click save, those attributes need to be added to the listWidget located on main form. now am i wrong or do i not need to have access to both UI's to do this( fyi, I have tried handleing this in the editMedicationForm.cpp as well, i continue to get a seg fault because it will not let me setup the UI as it inherits from a QDialog, not a QMainWindow. Is there a better way to access and modify widgets located in multiple forms? I simply want to add a listwidget item to mainform from data created in editmedicationform. Am i thinking about the incorrectly?



  • [quote author="webmaster.skelton" date="1291900962"]Ok i understand that, but i need to be able to access and modify widgets located in two different UIs, For example, i have a list widget in main form and EditMedicationForm is where the attributes are changed. So I click add new, a new form pops up, I enter the information into the field, and i click save, those attributes need to be added to the listWidget located on main form.[/quote]

    Make your ui/mainUi pointers public or declare the respective other class as friends. The members of the uic generated ui classes are public. So you can access them everywhere.

    [quote author="webmaster.skelton" date="1291900962"]now am i wrong or do i not need to have access to both UI's to do this( fyi, I have tried handleing this in the editMedicationForm.cpp as well, i continue to get a seg fault because it will not let me setup the UI as it inherits from a QDialog, not a QMainWindow. Is there a better way to access and modify widgets located in multiple forms? I simply want to add a listwidget item to mainform from data created in editmedicationform. Am i thinking about the incorrectly?[/quote]

    Be warned: it is common sense, that exposing implementation details to other classes (the ui elements add to that) is considered harmful. It is usually better that you have getters in your classes and forms (your QDialog based class to enter the data) to extract the data you need and provide them in an ui-independend form (Strings, numbers, maybe a small helper class/struct) and to provide a setter (slot) in the other class (MainForm) that does the task of adding the actual list item.

    Also, you can not have widgets located in multiple forms! A widget belongs to either exactly one form (as a child widget) or no form at all (that holds for top level widgets like windows, dialogs, etc.)

    Sorry, but I think you did not understand the whole concept about user interfaces, forms, widgets and that all. I strongly suggest you do some steps backwards and start with some tutorials and introductions to become comfortable with the basic design of Qt applications.

    As a rule of thumb: one ui-file (Designer created form) goes together with exactly one header file (.h) and exactly one C++ implementation file (.cpp) and results in exactly one new custom widget. You can use the widget in other source files by including the header file. Whatever you made public in the class definition is available there.



  • [quote author="Volker" date="1291902228"]As a rule of thumb: one ui-file (Designer created form) goes together with exactly one header file (.h) and exactly one C++ implementation file (.cpp) and results in exactly one new custom widget.[/quote]Agree. Only if you know exactly what you're doing you can somewhat deviate from this rule, however you should probably still step back and rethink your implementation.



  • ok thanks for the help.



  • Is the issue solved? Can I close the thread?



  • It should be merged with "this thread":http://developer.qt.nokia.com/forums/viewthread/2139/



  • Yea it can be closed.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.