Hand code GUI completely



  • Dear readers,

    is there any tutorial which will learn you how to complete design a GUI by hand?
    I dont want to use Qt Designer (personal choice) but do it completely my self. Downside is that I can not find any
    good tutorials which learns you how to do this.

    I hope someone can tell me how this works, on where I can find a good tutorial.



  • Almost all included in SDK tutorials didn't have ui(Designer) files.



  • The descriptions in "good books":http://developer.qt.nokia.com/books also show how to hancode the UI.



  • A good way to learn is to use Qt Designer, have the .ui file processed by uic to the ui_xxx.h file and look at the generated code.



  • [quote author="Volker" date="1327361774"]A good way to learn is to use Qt Designer, have the .ui file processed by uic to the ui_xxx.h file and look at the generated code.[/quote]

    I disagree here, but perhaps that's my personal view. Uic puts many things in, that are not really needed.

    From my POV, it's easier to use the tutorials or a book, as they describe how to do it and make small, minimal examples with only the really needed stuff.



  • Thank you for your answers guys, and Gerolf, that is one of the main reasons I want to learn to hand-code it. Only thing is that I am not english and (I think) not fully understand stuff completely.

    I have the book "C++ GUI Programming with Qt 4 (2nd Edition) - The official C++/Qt book" and yes, they explain you how to GUI code a little bit but not in depth.

    They explain a littlebit about QHBoxLayout, QVBoxLayout and that's pritty much it. They explain more about using QDesigner. Then they show you GridBoxLayout and various other things.

    Also, all examples they show are made with QDesigner, and look totally different then when I would write them my self hand-coded. This part confuses me a bit because it all looks so totally different with lots and lots of extra code which I dont need.

    The thing is, I would love to learn how to do this (picture sample):
    !http://img651.imageshack.us/img651/7886/13106021.jpg(sample picture)!

    But when I do something like (a dumb example):

    1. Create a container by using:
      QHBoxLayout = container.

    2. Add two QVBoxLayouts to the container by using:
      QVBoxLayout = leftSide, rightSide.

    First of all, the leftSide and rightSide box wont sit next to each other.
    Besides that, when I add widgets to them they all look 'hussled through each other' lol.
    They dont really align really nice (beautifull).

    Best regards



  • The layout system in Qt is a very very tricky issue!
    I have never used any designer to my codes :)
    What is very important:
    Put all of your widget from top to bottom, and lay these out from bottom to top!


  • Moderators

    What is wrong about using a designer here? A UI is a very visual thing and directly seeing what I am doing does help me a lot!



  • I would do (schematic):

    @
    QVBoxLayout
    QHBoxLayout
    QGroupBox (personal info)
    QGridLayout
    QLabel - QLineEdit
    QLabel - QLineEdit
    QLabel - QLineEdit
    QLabel - QLineEdit
    QVBoxlayout
    QLabel (a - amount)
    QSlider
    vertical spacer
    QLabel (b - amount)
    QSlider
    vertical spacer
    QLabel (c - amount)
    QSlider
    QGridLayout
    QLabel - QLabel - Spacer
    QLabel - QLabel - Spacer
    QLabel - QLabel - Spacer
    vertical spacer
    QHBoxLayout
    QPushButton
    horizontal spacer
    @



  • [quote author="Tobias Hunger" date="1327417984"]What is wrong about using a designer here? A UI is a very visual thing and directly seeing what I am doing does help me a lot![/quote]

    Yes and no :-)
    I also code all my UIs by hand. This gives me some more options, especially, if you want to use also custom widgets etc.


  • Moderators

    Gerolf: There are cases where hand-coding makes sense, I agree about that, but in general you are faster and get better results using the designer.

    This thread is about "how to complete design a GUI by hand". I do challenge that "personal choice" is a valid reason for any professional to hand-craft UIs.



  • Thanks for your answer guys, this wil surely help me out a lot.

    @Gerolf : I will give your suggestion a try to see what I can come up with. Only thing is that I cannot find out how to use spacers and groupboxes. Then again, maybe I am using them in the wrong way lol. I am fairly new to Qt so I am still in the learning process.

    I will play around with it a bit and reply here with what I came up with :)

    Thank you all very much so far guys <3



  • bq. Only thing is that I cannot find out how to use spacers and groupboxes.

    Spacers are added by going to the target layout and adding:

    @TargetLayoutName->addstretch()@

    Where you put it in relation to other widgets matters of course. As for the groupbox, I have not learned that yet.



  • [quote author="GroundZero" date="1327445280"]
    Thanks for your answer guys, this will surely help me out a lot.

    Gerolf : I will give your suggestion a try to see what I can come up with. Only thing is that I cannot find out how to use spacers and groupboxes. Then again, maybe I am using them in the wrong way. I am fairly new to Qt so I am still in the learning process.

    I will play around with it a bit and reply here with what I came up with :)
    [/quote]

    @
    layout->addItem(new QSpacer(...));
    QGroupBox* pGrp = new QGroupBox(this);
    QGridLayout* pGrpGrid = new QGridLayout(pGrp);

    QLabel* pName = new QLabel(pGrp);
    pGrpGrid->addWidget(0,0,pName);
    // ...
    

    @



  • [quote author="Tobias Hunger" date="1327420165"]Gerolf: There are cases where hand-coding makes sense, I agree about that, but in general you are faster and get better results using the designer.

    This thread is about "how to complete design a GUI by hand". I do challenge that "personal choice" is a valid reason for any professional to hand-craft UIs.[/quote]

    I would say, it's ok, if you know what you do (and as a professional, you should know :-) ).
    Why should using a UI tool be better? It might be easier for some things and for some it may not.

    In MFC, it was not possible to code UI's by hand, as you had no layouters, only coordinates, but with layout classes, it's fairly easy to code the UI by hand.



  • Looking at my forms, with tons of widgets, I would drive nuts if I had to hand code them all in C++ :)



  • As said, I am still learning Qt so please go easy on me as I might make dumb mistakes, so my apologies for that if I do so.

    I wrote this (start) code:
    @#include <QApplication>
    #include <QWidget>
    #include <QGroupBox>
    #include <QGridLayout>
    #include <QHBoxLayout>
    #include <QVBoxLayout>
    #include <QLabel>
    #include <QLineEdit>
    #include <QSlider>
    #include <QSpinBox>
    #include <QSpacerItem>
    #include <QPushButton>

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    // create a main widget
    QWidget *mainAppWindow = new QWidget;
    mainAppWindow->setWindowTitle("Custom made GUI - Test 0.1");
    mainAppWindow->setFixedSize(500, 600);
    
    // create the widgets
    QLabel *nameLabel = new QLabel;
    nameLabel->setText("name");
    
    QLineEdit *nameText = new QLineEdit;
    
    QSlider *aAmount = new QSlider;
    
    aAmount->setRange(0, 100);
    
    aAmount->setValue(25);
    
    QGroupBox *personalInfoBox = new QGroupBox;
    personalInfoBox->setTitle("Personal Info");
    
    // create the layout for the personalInfoBox
    QHBoxLayout *pibLayout = new QHBoxLayout;
    pibLayout->addWidget(nameLabel);
    pibLayout->addWidget(nameText);
    pibLayout->addWidget(surnameLabel);
    pibLayout->addWidget(surnameText);
    pibLayout->addWidget(ageLabel);
    pibLayout->addWidget(ageText);
    pibLayout->addWidget(genderLabel);
    pibLayout->addWidget(genderText);
    
    // create the topleft box and add the group to it
    QHBoxLayout *topLeftLayout = new QHBoxLayout;
    topLeftLayout->addLayout(personalInfoBox);
    
    // add the layout to the main window
    mainAppWindow->setLayout(pibLayout);
    
    // display the window
    mainAppWindow->show();
    
    return app.exec&#40;&#41;;
    

    }@

    It gives me the following error:
    no matching function for call to 'QHBoxLayout::addLayout(QGroupBox*&)'

    I tried looking into the documentation but I cant see what I did wrong. I tried declaring it in two ways:

    @QGroupBox *personalInfoBox = new QGroupBox;
    personalInfoBox->setTitle("Personal Info");@

    and

    @QGroupBox *personalInfoBox = new QGroupBox("Personal Info");@

    but both give me the same error. When I use:
    @QGroupBox *personalInfoBox = new QGroupBox(tr("Personal Info"));@
    it says that tr cannot be found, but for now dont mind the translate thingy ;)

    P.S. I shorten the code a bit otherwise the list would be long, but I did declerate all the QLabels and QSliders and other stuff in my code. I have shown you one of each to see how I declerate them, but I remove the others to keep this 'post' a bit smaller ;)



  • [quote author="Volker" date="1327494502"]Looking at my forms, with tons of widgets, I would drive nuts if I had to hand code them all in C++ :)[/quote]

    Spit it up to sub forms? :-)
    I know there are cases, where it really makes sense, but I try to avoid forms with hundreds of widgets.



  • [quote author="Gerolf" date="1327498560"]
    [quote author="Volker" date="1327494502"]Looking at my forms, with tons of widgets, I would drive nuts if I had to hand code them all in C++ :)[/quote]

    Spit it up to sub forms? :-)
    I know there are cases, where it really makes sense, but I try to avoid forms with hundreds of widgets.[/quote]

    True, but you can Copy & Paste a lot to though ;)
    And I also use the clicking on the numbers on the left side to "fold" code. This way my screen stays pritty clean, and when I need something I can just "unfold" it, edit it or look at it, and fold it back up lol :)

    Anyways, I posted my code and question on page 2 (top). I am doing something wrong with the Group option :(



  • Hi,

    I could boiler plate you, and give you a working version :-)
    But it would be complete.

    First your bugs:

    a group box is a widget --> addWidget not addlayout

    pibLayout is the layout of the group box, add it there, not on the main window

    Full source for the sollution, only read it if you don't want to learn by building it on your own :-)

    @
    #include <QApplication>
    #include <QWidget>
    #include <QGroupBox>
    #include <QGridLayout>
    #include <QHBoxLayout>
    #include <QVBoxLayout>
    #include <QLabel>
    #include <QLineEdit>
    #include <QSlider>
    #include <QSpinBox>
    #include <QSpacerItem>
    #include <QPushButton>

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    // create a main widget
    QWidget *mainAppWindow = new QWidget;
    mainAppWindow->setWindowTitle("Custom made GUI - Test 0.1");
    mainAppWindow->setFixedSize(500, 600);
    
    // main vertical layout
    QVBoxLayout* pMainLayout = new QVBoxLayout(mainAppWindow);
    mainAppWindow->setLayout(pMainLayout);
    
    // ------------------------------------------------------
    // first sub layouts
    QHBoxLayout* pTopHBox  = new QHBoxLayout;
    pMainLayout->addLayout(pTopHBox);
    
    QGridLayout* pLabelGrid  = new QGridLayout;
    pMainLayout->addLayout(pLabelGrid);
    
    pMainLayout->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
    
    QHBoxLayout* pBtnHBox  = new QHBoxLayout;
    pMainLayout->addLayout(pBtnHBox);
    
    // ------------------------------------------------------
    // create the group box
    QGroupBox *personalInfoBox = new QGroupBox(mainAppWindow);
    personalInfoBox->setTitle("Personal Info");
    
    QLabel *nameLabel = new QLabel(QObject::tr("name"), personalInfoBox);
    QLineEdit *nameText = new QLineEdit(personalInfoBox);
    QLabel *surnameLabel = new QLabel(QObject::tr("surname"), personalInfoBox);
    QLineEdit *surnameText = new QLineEdit(personalInfoBox);
    QLabel *ageLabel = new QLabel(QObject::tr("age"), personalInfoBox);
    QLineEdit *ageText = new QLineEdit(personalInfoBox);
    QLabel *genderLabel = new QLabel(QObject::tr("gender"), personalInfoBox);
    QLineEdit *genderText = new QLineEdit(personalInfoBox);
    
    // create the layout for the personalInfoBox
    QGridLayout *pibLayout = new QGridLayout;
    pibLayout->addWidget(nameLabel, 0, 0);
    pibLayout->addWidget(nameText, 0, 1);
    pibLayout->addWidget(surnameLabel, 1, 0);
    pibLayout->addWidget(surnameText, 1, 1);
    pibLayout->addWidget(ageLabel, 2, 0);
    pibLayout->addWidget(ageText, 2, 1);
    pibLayout->addWidget(genderLabel, 3, 0);
    pibLayout->addWidget(genderText, 3, 1);
    personalInfoBox->setLayout(pibLayout);
    pTopHBox->addWidget(personalInfoBox);
    
    // ------------------------------------------------------
    // create the slider area
    QVBoxLayout* pSlidersLayout = new QVBoxLayout;
    pTopHBox->addLayout(pSlidersLayout);
    QSlider *aAmount = new QSlider(Qt::Horizontal, mainAppWindow);
    aAmount->setRange(0, 100);
    aAmount->setValue(25);
    QSlider *bAmount = new QSlider(Qt::Horizontal, mainAppWindow);
    bAmount->setRange(0, 100);
    bAmount->setValue(25);
    QSlider *cAmount = new QSlider(Qt::Horizontal, mainAppWindow);
    cAmount->setRange(0, 100);
    cAmount->setValue(25);
    
    pSlidersLayout->addWidget(new QLabel(QObject::tr("a - amount"), mainAppWindow));
    pSlidersLayout->addWidget(aAmount);
    pSlidersLayout->addWidget(new QLabel(QObject::tr("b - amount"), mainAppWindow));
    pSlidersLayout->addWidget(bAmount);
    pSlidersLayout->addWidget(new QLabel(QObject::tr("c - amount"), mainAppWindow));
    pSlidersLayout->addWidget(cAmount);
    
    // ------------------------------------------------------
    // create the info area
    pLabelGrid->addWidget(new QLabel(QObject::tr("a - statistic display"), mainAppWindow), 0, 0);
    pLabelGrid->addWidget(new QLabel(QObject::tr("a - runtime statistic display"), mainAppWindow), 0, 1);
    pLabelGrid->addItem(new QSpacerItem(0,0, QSizePolicy::Expanding,QSizePolicy::Minimum), 0, 2);
    pLabelGrid->addWidget(new QLabel(QObject::tr("b - statistic display"), mainAppWindow), 1, 0);
    pLabelGrid->addWidget(new QLabel(QObject::tr("b - runtime statistic display"), mainAppWindow), 1, 1);
    pLabelGrid->addWidget(new QLabel(QObject::tr("c - statistic display"), mainAppWindow), 2, 0);
    pLabelGrid->addWidget(new QLabel(QObject::tr("c - runtime statistic display"), mainAppWindow), 2, 1);
    
    // ------------------------------------------------------
    // create the button area
    QPushButton* pBtn = new QPushButton(QObject::tr("Push me"), mainAppWindow);
    pBtnHBox->addWidget(pBtn);
    pBtnHBox->addItem(new QSpacerItem(0,0, QSizePolicy::Expanding,QSizePolicy::Minimum));
    
    // display the window
    mainAppWindow->show();
    
    return app.exec();
    

    }
    @



  • Gerolf, thank you very much. I will try to fix my code first before copy pasting yours lol, need to learn it anyways haha. Thank you so much once again ;)

    P.S. I see you do a LOT of stuff totally different i.e.
    @pLabelGrid->addWidget(new QLabel(QObject::tr("c - runtime statistic display"), mainAppWindow), 2, 1);@
    @pibLayout->addWidget(nameText, 0, 1);@

    you use tr (translate?) and a 2nd attribute. After that you give the QLabel object a 2nd and 3rd attribute (2 and 1).
    Never seen that / done that but... ill try to fix my code and try to find out what this all means :)

    Also in the 2nd example the INT for a row and so on, thats pritty cool! this will surely help me out a LOT!



  • [quote author="Gerolf" date="1327498560"]
    Spit it up to sub forms? :-)
    I know there are cases, where it really makes sense, but I try to avoid forms with hundreds of widgets.[/quote]

    It's already subforms :-)
    Collecting data isn't always doable with two line edits and a combo box ;-)



  • [quote author="GroundZero" date="1327501166"]P.S. I see you do a LOT of stuff totally different i.e.
    @pLabelGrid->addWidget(new QLabel(QObject::tr("c - runtime statistic display"), mainAppWindow), 2, 1);@
    @pibLayout->addWidget(nameText, 0, 1);@

    you use tr (translate?) and a 2nd attribute. After that you give the QLabel object a 2nd and 3rd attribute (2 and 1).
    Never seen that / done that but... ill try to fix my code and try to find out what this all means :)

    Also in the 2nd example the INT for a row and so on, thats pritty cool! this will surely help me out a LOT![/quote]

    All widgets have parameters in the constructor, one is the parent, which I ALWAYS set. It also works without, then the layout sets them.

    the integers in the addWidget is for the grid layout.



  • yeah awesome, I never knew this does help me out a lot :)
    trying to code it now my self, hope I can figure this stuff out lol pritty hard to understand all the boxes and stuff.

    Webdevelopment is so much easier lol lol :-)

    EDIT:
    Figured I would but... I made a much simpler layout. Problem is that it is displayed right under each other instead of next
    to each other. How can I fix this? my code:

    @int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    // -------------------------------------------------------
    // create the main widget
    QWidget *mainApplication = new QWidget;
    mainApplication->setWindowTitle("Hand coded GUI");
    mainApplication->setFixedSize(500, 600);
    
    // -------------------------------------------------------
    // main box
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainApplication->setLayout(mainLayout);
    
    // -------------------------------------------------------
    // sub boxes
    QHBoxLayout *pLeftSide = new QHBoxLayout;
    QVBoxLayout *pRightSide = new QVBoxLayout;
    
    mainLayout->addLayout(pLeftSide);
    mainLayout->addLayout(pRightSide);
    
    // -------------------------------------------------------
    // create the group box
    QGroupBox *userinfoGroupBox = new QGroupBox;
    userinfoGroupBox->setTitle("Personal Info");
    
    // -------------------------------------------------------
    // create the content of the group box
    QLabel *nameLabel = new QLabel(QObject::tr("name"));
    QLineEdit *nameEdit = new QLineEdit;
    QLabel *surnameLabel = new QLabel(QObject::tr("surname"));
    QLineEdit *surnameEdit = new QLineEdit;
    
    // -------------------------------------------------------
    // create the layout for the userinfoGroupBox
    QGridLayout *gridView = new QGridLayout;
    gridView->addWidget(nameLabel, 0, 0);
    gridView->addWidget(nameEdit, 0, 1);
    gridView->addWidget(surnameLabel, 1, 0);
    gridView->addWidget(surnameEdit, 1, 1);
    
    // -------------------------------------------------------
    // add the layout to the group box
    userinfoGroupBox->setLayout(gridView);
    
    // -------------------------------------------------------
    // add the groupbox to the leftside box
    pLeftSide->addWidget(userinfoGroupBox);
    
    // -------------------------------------------------------
    // create some sliders
    QLabel *aSliderLabel = new QLabel(QObject::tr("a value"));
    QSlider *aSlider = new QSlider(Qt::Horizontal);
    aSlider->setRange(0, 100);
    aSlider->setValue(88);
    QLabel *bSliderLabel = new QLabel(QObject::tr("b value"));
    QSlider *bSlider = new QSlider(Qt::Horizontal);
    bSlider->setRange(0, 300);
    bSlider->setValue(142);
    
    // -------------------------------------------------------
    // add the widgets to the right window
    pRightSide->addWidget(aSliderLabel);
    pRightSide->addWidget(aSlider);
    pRightSide->addWidget(bSliderLabel);
    pRightSide->addWidget(bSlider);
    
    // display the window
    mainApplication->show();
    
    return app.exec&#40;&#41;;
    

    }@

    So what I want is:

    1. mainLayout = my main wrapper / container / box, or what ever you want to call it.
    2. pLeftSide and pRightSide are two boxes which should be displayed NEXT to each other.
    3. pLeftSide should display stuff by pairs of two next to each other (this is working)
    4. pRightSize should display stuff under each other (this is working)

    Also, my sliders get stretched out... so they are extremely width :-(

    EDIT:
    I have another question if I may so...

    I was reading the book. I made a GUI by using Qt Designer. Works flawless BUT... the book tells me the following:
    bq. Now run qmake to create a .pro file and a makefile (qmake -project;qmake gotocell.pro). The qmake tool is smart enough to detect the user interface file gotocell-dialog.ui and to generate the appropriate makefule rules to invoke uic, Qt's user interface compiler.

    Now... I have no clue what they mean with qmake this and qmake that lol. I want to see the source, how the GUI I made was build up in plain C++ and not a (no offence) stupid XML file look a like markup lol.

    Could someone walk me through the process of turning this XML look-a-like thingy to a C++ type.



  • If you only use box layouts, you will never create grids :-)
    Try using QGridLayout, it helps much in the UI you have.

    Another thing, what I typically do is, put creation of sub parts in a method. E.g. create the group box in a method and return the group box pointer. Using this, you can test it independently and just use it later.

    Do you use QtCreator? Or all tools by hand?

    Regarding your last question:

    call qmake to create a qt project file (qmake -project) and then create a make file (qmake xxx.pro). When you now compile the makefile (nmake, make, mingw-make, what ever tool chain you use), you get a ui_xxx.h file (or is it xxx_ui.h?). This is the C++ code of the ui file.



  • bq. In MFC, it was not possible to code UI’s by hand, as you had no layouters, only coordinates, but with layout classes, it’s fairly easy to code the UI by hand.

    I am a pretty big stickler when it comes to making guis. I don't really like using forms either. I am an engineer by trade, so when I tried C++/CLI, .NET, and sometimes straight winapi it was extremely hard for me to code without relying on forms. Finally discovered qt and all my problems were solved :)



  • @ Gerolf;

    I use Qt Creator to do everything. I will change my code and use some GridLayouts and hopefully that will make things look better haha.

    I am a bit confused though, but I will give it another try and hopefully get it done right this time ;)

    Thanks for your answer guys!



  • It is a mystery to me why even experienced Qt coders prefer hand-coding UIs over using designer. Sure, there are situations where manual layouting is needed to achieve some special results, but those should be exceptions.

    It is a good approach to learn about layouting by looking at the code generated by designer. I suggest to use that insight to learn enough about designer to use it. Since layout initialization code is usually not executed repeatedly, hand-crafting layouts will not result is significant performance gains, and makes UIs much harder to maintain.



  • I agree: Designer-based UI's when possible, and hand-crafted when needed. However, I must say that at time, I also find that I fight with Designer more than I like.


Log in to reply
 

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