Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QScrollArea and Splitter



  • HI,

    I'm running into an issue integrating widgets, QSrollArea, and QSplitter in the main window. Using QTCreator I added a whole bunch of widgets. The widgets are placed as a grid. In other words I used the grid icon to automatically place the widgets in a nice orderly fashion. So far so good.

    As part of that I decided to add a QScrollArea in the main window along with the other widgets. Also placed in the grid. In the QScrollArea I added a whole number of QCombo-boxes. The combo-boxes are placed in a grid in the scroll area. There are 10 rows of combo-boxes and each row contains 7 combo-boxes.

    I also added a two buttons which hides and shows each row of combo-boxes to give the illusion that new rows are added or removed in the scroll area. As the user clicks the add or remove button, I simply set the visible flag to true or false for the combo-boxes for the row in question. That works fine. If I leave it as is when I run the application the first row of combo-boxes are displayed with no issue in the scroll area as I expected. As I click on the button to add a row (just makes the combo-boxes visible), eventually the scrollarea displays the vertical scroll so the user can navigate up and down the rows. The opposite is true when I remove rows. Also that is working as expected.

    The problem is when I place a vertical splitter between the scroll area frame and a frame of widgets just beneath the scroll area frame. I want to do this so I can resize the scroll area in case users don't want to use the vertical scroll associated in the scroll area. As it turns out Qt allocates the full size of the scroll area as if all the combo-boxes are all showing instead of just providing enough space to show just one row of combo-boxes like it did before adding the splitter. So naturally there is no scroll since the scroll area is maximized. Also I can't resize using the splitter although the splitter icon is displayed. Just doesn't do anything.

    Any idea how I can have the same behavior in the scroll area with the splitter the way it works without it?


  • Lifetime Qt Champion

    Hi,

    Can you provide a sample project that shows what you get ?

    It's rather hard to find what is going on based solely on the description.



  • If I post the mainwindow.ui would that work?



  • Also I tried doing this but I don't see a splitter at all.

    The widgets are in advanceFilterGridLayout and basicFilterLayout where advanceFilterGridLayout contains the ScrollArea and widgets within the scroll area.

    QSplitter *splitter = new QSplitter(Qt::Vertical);
    ui->advanceFilterGridLayout->addWidget(splitter);
    ui->basicFilterLayout->addWidget(splitter);


  • Lifetime Qt Champion

    It would be a first step.

    You can't put a widget in two different layouts.

    You should put each half of your GUI in the QSplitter.



  • OK, I stream down the application to show my issue. As you mentioned, I managed to get the splitter but it doesn't move.

    Click on the "Enabled Advance Filtering" button.

    Now you will see a large scroll area. This should be much smaller.

    Click on the "Add Row" button.

    New rows are added to the scroll area but there is no scroll bar. If you go to the splitter right underneath the scroll area it does not move in any direction. I'd like the scroll area to have enough room for may be two rows and as I add rows, the scroll bar appears. The splitter should allow me to expand the scroll area to any size I need to display more or less rows. If I expand far enough the scroll bars should disappear. Standard for GUI apps.

    If you remove the splitter, you will see that the scroll area works properly as I add rows but now no splitter to resize the scroll.

    Thanks for your help.

    mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QSplitter>
    #include <QComboBox>
    

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = NULL);
    ~MainWindow();

    private:
    void setupPanelToLookPretty();

    private slots:

    void on_enableAdvanceFilteringPushButton_clicked();
    
    void on_advanceFilterClearPushButton_clicked();
    
    void on_advanceFilterAddRowPushButton_clicked();
    
    void on_advanceFilterRemoveRowPushButton_clicked();
    

    private:
    Ui::MainWindow *ui;

    //advance filter inputs
    QList<QComboBox *> advanceFilteringComboboxObjectTypeList;
    QList<QComboBox *> advanceFilteringComboboxAttributeList;
    QList<QComboBox *> advanceFilteringComboboxMathList;
    QList<QComboBox *> advanceFilteringComboboxMinValueList;
    QList<QComboBox *> advanceFilteringComboboxMaxValueList;
    QList<QComboBox *> advanceFilteringComboboxBooleanList;
    
    QList<QLineEdit *> advanceFilteringObjectTypeLineEditList;
    QList<QLineEdit *> advanceFilteringAttributeLineEditList;
    QList<QLineEdit *> advanceFilteringMathLineEditList;
    QList<QLineEdit *> advanceFilteringMinValueLineEditList;
    QList<QLineEdit *> advanceFilteringMaxValueLineEditList;
    QList<QLineEdit *> advanceFilteringBooleanLineEditList;
    
    QList<QLineEdit *> advanceFilteringObjectTypeCompleterList;
    QList<QCompleter *> advanceFilteringAttributeCompleterList;
    QList<QCompleter *> advanceFilteringMathCompleterList;
    QList<QCompleter *> advanceFilteringMinValueCompleterList;
    QList<QCompleter *> advanceFilteringMaxValueCompleterList;
    QList<QCompleter *> advanceFilteringBooleanCompleterList;
    int advanceFilterCurrentRowNumber;
    bool advanceFilteringEnabled;
    

    };

    #endif // MAINWINDOW_H



  • mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #define ADVANCE_FILTER_ROW_NUMBER 10

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    advanceFilterCurrentRowNumber(0),
    advanceFilteringEnabled(false)
    {
    ui->setupUi(this);

    MainWindow::setupPanelToLookPretty();
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    //setupPanelToLookPretty is run only once when DataView comes up. It is NOT run when a new database is loaded.
    void MainWindow::setupPanelToLookPretty()
    {

    //Advance Filtering
    //Assign all the combo-boxes to QList so easy to handle in the future
    advanceFilteringComboboxObjectTypeList << ui->advanceFilterObjectTypeComboBox0 << ui->advanceFilterObjectTypeComboBox1 << ui->advanceFilterObjectTypeComboBox2 <<
                                 ui->advanceFilterObjectTypeComboBox3 << ui->advanceFilterObjectTypeComboBox4 << ui->advanceFilterObjectTypeComboBox5 <<
                                 ui->advanceFilterObjectTypeComboBox6 << ui->advanceFilterObjectTypeComboBox7 << ui->advanceFilterObjectTypeComboBox8 <<
                                 ui->advanceFilterObjectTypeComboBox9;
    
    advanceFilteringComboboxAttributeList << ui->advanceFilterAttributeComboBox0 << ui->advanceFilterAttributeComboBox1 << ui->advanceFilterAttributeComboBox2 <<
                                    ui->advanceFilterAttributeComboBox3 << ui->advanceFilterAttributeComboBox4 << ui->advanceFilterAttributeComboBox5 <<
                                    ui->advanceFilterAttributeComboBox6 << ui->advanceFilterAttributeComboBox7 << ui->advanceFilterAttributeComboBox8 <<
                                    ui->advanceFilterAttributeComboBox9;
    
    
    advanceFilteringComboboxMathList << ui->advanceFilterMathComboBox0 << ui->advanceFilterMathComboBox1 << ui->advanceFilterMathComboBox2 <<
                               ui->advanceFilterMathComboBox3 << ui->advanceFilterMathComboBox4 << ui->advanceFilterMathComboBox5 <<
                               ui->advanceFilterMathComboBox6 << ui->advanceFilterMathComboBox7 << ui->advanceFilterMathComboBox8 <<
                               ui->advanceFilterMathComboBox9;
    
    
    advanceFilteringComboboxMinValueList << ui->advanceFilterMinAtributeValueComboBox0 << ui->advanceFilterMinAtributeValueComboBox1 << ui->advanceFilterMinAtributeValueComboBox2 <<
                                   ui->advanceFilterMinAtributeValueComboBox3 << ui->advanceFilterMinAtributeValueComboBox4 << ui->advanceFilterMinAtributeValueComboBox5 <<
                                   ui->advanceFilterMinAtributeValueComboBox6 << ui->advanceFilterMinAtributeValueComboBox7 << ui->advanceFilterMinAtributeValueComboBox8 <<
                                   ui->advanceFilterMinAtributeValueComboBox9;
    
    
    
    advanceFilteringComboboxMaxValueList << ui->advanceFilterMaxAtributeValueComboBox0 << ui->advanceFilterMaxAtributeValueComboBox1 << ui->advanceFilterMaxAtributeValueComboBox2 <<
                                   ui->advanceFilterMaxAtributeValueComboBox3 << ui->advanceFilterMaxAtributeValueComboBox4 << ui->advanceFilterMaxAtributeValueComboBox5 <<
                                   ui->advanceFilterMaxAtributeValueComboBox6 << ui->advanceFilterMaxAtributeValueComboBox7 << ui->advanceFilterMaxAtributeValueComboBox8 <<
                                   ui->advanceFilterMaxAtributeValueComboBox9;
    
    
    //boolean has one less entry since the last query does not carry over to another query
    advanceFilteringComboboxBooleanList << ui->advanceFilterBooleanComboBox0 << ui->advanceFilterBooleanComboBox1 << ui->advanceFilterBooleanComboBox2 <<
                                  ui->advanceFilterBooleanComboBox3 << ui->advanceFilterBooleanComboBox4 << ui->advanceFilterBooleanComboBox5 <<
                                  ui->advanceFilterBooleanComboBox6 << ui->advanceFilterBooleanComboBox7 << ui->advanceFilterBooleanComboBox8;
    
    //Place tool tips and default lineEdit text but first create lineEdits for each of the combo boxes
    for(int i = 0; i < ADVANCE_FILTER_ROW_NUMBER; i++)
    {
        QLineEdit *tempLineEdit1 = new QLineEdit;
        advanceFilteringObjectTypeLineEditList << tempLineEdit1;
    
        //later  on we have assign the combo-boxes to a completer but since we dont have the actual list we do a temporary assignemnt to place text
        //object types
        advanceFilteringComboboxObjectTypeList[i]->setEditable(false);
        advanceFilteringComboboxObjectTypeList[i]->setLineEdit(advanceFilteringObjectTypeLineEditList[i]);
        advanceFilteringObjectTypeLineEditList[i]->setPlaceholderText("Select an Object Type");
        advanceFilteringComboboxObjectTypeList[i]->setToolTip("Shows all possible object types.  Users can can query on one more object types in the same query");
        advanceFilteringComboboxObjectTypeList[i]->setInsertPolicy(QComboBox::NoInsert);
        advanceFilteringComboboxObjectTypeList[i]->setCurrentIndex(-1);
        advanceFilteringComboboxObjectTypeList[i]->setVisible(false); //hide the combo-boxes as an initial condition
    
        //Attributes
        QLineEdit *tempLineEdit2 = new QLineEdit;
        advanceFilteringAttributeLineEditList << tempLineEdit2;
    
        advanceFilteringComboboxAttributeList[i]->setEditable(false);
        advanceFilteringComboboxAttributeList[i]->setLineEdit(advanceFilteringAttributeLineEditList[i]);
        advanceFilteringAttributeLineEditList[i]->setPlaceholderText("Select an Attribute (after selecting an Object Type");
        advanceFilteringComboboxAttributeList[i]->setToolTip("Shows all the attributes associated with a selected object type.");
        advanceFilteringComboboxAttributeList[i]->setInsertPolicy(QComboBox::NoInsert);
        advanceFilteringComboboxAttributeList[i]->setCurrentIndex(-1);
        advanceFilteringComboboxAttributeList[i]->setVisible(false); //hide the combo-boxes as an initial condition
    
        //Math input
        QLineEdit *tempLineEdit3 = new QLineEdit;
        advanceFilteringMathLineEditList << tempLineEdit3;
    
        advanceFilteringComboboxMathList[i]->setEditable(false);
        advanceFilteringComboboxMathList[i]->setLineEdit(advanceFilteringMathLineEditList[i]);
        advanceFilteringMathLineEditList[i]->setPlaceholderText("Comparison Selection");
        advanceFilteringComboboxMathList[i]->setInsertPolicy(QComboBox::NoInsert);
        advanceFilteringComboboxMathList[i]->addItem("=");
        advanceFilteringComboboxMathList[i]->addItem(">=");
        advanceFilteringComboboxMathList[i]->addItem("<");
        advanceFilteringComboboxMathList[i]->addItem("<=");
        advanceFilteringComboboxMathList[i]->addItem("!=");
        advanceFilteringComboboxMathList[i]->addItem("IN BETWEEN");
        advanceFilteringComboboxMathList[i]->addItem("CONTAINS");
        advanceFilteringComboboxMathList[i]->setToolTip("Select a comparison value. 'IN BETWEEN' requires a minimum and maximum entry.");
        advanceFilteringComboboxMathList[i]->setCurrentIndex(-1);  //must be at the end since we added
        advanceFilteringComboboxMathList[i]->setVisible(false); //hide the combo-boxes as an initial condition
    
        //min attribute values
        QLineEdit *tempLineEdit4 = new QLineEdit;
        advanceFilteringMinValueLineEditList << tempLineEdit4;
    
        advanceFilteringComboboxMinValueList[i]->setEditable(true);  //needs to be editable
        advanceFilteringComboboxMinValueList[i]->setLineEdit(advanceFilteringMinValueLineEditList[i]);
        advanceFilteringMinValueLineEditList[i]->setPlaceholderText("Select Minimum value");
        advanceFilteringComboboxMinValueList[i]->setToolTip("Select a value for the selected attribute.");
        advanceFilteringComboboxMinValueList[i]->setCurrentIndex(-1);
        advanceFilteringComboboxMinValueList[i]->setVisible(false); //hide the combo-boxes as an initial condition
    
        //max attribute values
        QLineEdit *tempLineEdit5 = new QLineEdit;
        advanceFilteringMaxValueLineEditList << tempLineEdit5;
    
        advanceFilteringComboboxMaxValueList[i]->setEditable(true); //needs to be editable
        advanceFilteringComboboxMaxValueList[i]->setLineEdit(advanceFilteringMaxValueLineEditList[i]);
        advanceFilteringMaxValueLineEditList[i]->setPlaceholderText("Select Maximum value");
        advanceFilteringComboboxMaxValueList[i]->setToolTip("Select a maximum value (Only valid when using the 'IN BETWEEN' selection under the comparison selections.");
        advanceFilteringComboboxMaxValueList[i]->setCurrentIndex(-1);
        advanceFilteringComboboxMaxValueList[i]->setVisible(false); //hide the combo-boxes as an initial condition
    
        //boolean selections (one less since last row has no boolean slection
        if(i < ADVANCE_FILTER_ROW_NUMBER - 1)
        {
            QLineEdit *tempLineEdit6 = new QLineEdit;
            advanceFilteringBooleanLineEditList << tempLineEdit6;
    
            advanceFilteringComboboxBooleanList[i]->setEditable(false);
            advanceFilteringComboboxBooleanList[i]->setLineEdit(advanceFilteringBooleanLineEditList[i]);
            advanceFilteringBooleanLineEditList[i]->setPlaceholderText("Select a boolean value");
            advanceFilteringBooleanLineEditList[i]->setToolTip("Select a boolean value (used for compound queries (AND/OR).  If not selected not a compund query.");
            advanceFilteringComboboxBooleanList[i]->addItem("");  //When there is no compund query
            advanceFilteringComboboxBooleanList[i]->addItem("AND");
            advanceFilteringComboboxBooleanList[i]->addItem("OR");
            advanceFilteringComboboxBooleanList[i]->setInsertPolicy(QComboBox::NoInsert);
            advanceFilteringComboboxBooleanList[i]->setCurrentIndex(-1);
            advanceFilteringComboboxBooleanList[i]->setVisible(false); //hide the combo-boxes as an initial condition
        }
    }
    
    //advance filter scroll area is removed from the display as an initial condition
    ui->advanceFilterScrollArea->setVisible(false);
    ui->advanceFilterClearPushButton->setVisible(false);
    ui->advanceFilterAddRowPushButton->setVisible(false);
    ui->advanceFilterRemoveRowPushButton->setVisible(false);
    

    // QSplitter *splitter = new QSplitter(Qt::Vertical);
    // ui->advanceFilterGridLayout->addWidget(splitter);
    // ui->basicFilterLayout->addWidget(splitter); //remove splitter from include if not using

    }

    //turn on/off the advance filtering/basic filtering dialogue boxes
    void MainWindow::on_enableAdvanceFilteringPushButton_clicked()
    {
    if(advanceFilteringEnabled == false)
    {
    advanceFilteringEnabled = true;
    ui->advanceFilterScrollArea->setVisible(true); //advance filtering scroll area
    ui->enableAdvanceFilteringPushButton->setText("Enable Basic Filtering");
    ui->advanceFilterClearPushButton->setVisible(true);
    ui->advanceFilterAddRowPushButton->setVisible(true);
    ui->advanceFilterRemoveRowPushButton->setVisible(true);

        //basic filetring selections turned on
        ui->clearFilterpushButton->setVisible(false);
        ui->objectTypeComboBox->setVisible(false);
        ui->eventTypeComboBox->setVisible(false);
        ui->ipStringValueComboBox->setVisible(false);
        ui->minTimeOfReceiptComboBox->setVisible(false);
        ui->maxTimeOfReceiptComboBox->setVisible(false);
    
        //show the last set of advance filter selection boxes
        if(advanceFilterCurrentRowNumber == ADVANCE_FILTER_ROW_NUMBER)  //since we start with zero we want to make sure we don't over allocate
            advanceFilterCurrentRowNumber--;
    
        for(int i = 0; i <= advanceFilterCurrentRowNumber; i++)
        {
           advanceFilteringComboboxObjectTypeList[i]->setVisible(true);
           advanceFilteringComboboxAttributeList[i]->setVisible(true);
           advanceFilteringComboboxMathList[i]->setVisible(true);
           advanceFilteringComboboxMinValueList[i]->setVisible(true);
           advanceFilteringComboboxMaxValueList[i]->setVisible(true);
           if(i < ADVANCE_FILTER_ROW_NUMBER - 1)
                advanceFilteringComboboxBooleanList[i]->setVisible(true);
        }
    }
    else  //advance filetring turned off so using basic filtering is enabled
    {
        advanceFilteringEnabled = false;
        ui->advanceFilterScrollArea->setVisible(false);
        ui->advanceFilterClearPushButton->setVisible(false);
        ui->advanceFilterAddRowPushButton->setVisible(false);
        ui->advanceFilterRemoveRowPushButton->setVisible(false);
        ui->enableAdvanceFilteringPushButton->setText("Enable Advance Filtering");
        //basic filetring selecections turned on
        ui->clearFilterpushButton->setVisible(true);
        ui->objectTypeComboBox->setVisible(true);
        ui->eventTypeComboBox->setVisible(true);
        ui->ipStringValueComboBox->setVisible(true);
        ui->minTimeOfReceiptComboBox->setVisible(true);
        ui->maxTimeOfReceiptComboBox->setVisible(true);
    }
    

    }

    //clear the advance filtering dialogue boxes
    void MainWindow::on_advanceFilterClearPushButton_clicked()
    {
    for(int i = 0; i < ADVANCE_FILTER_ROW_NUMBER; i++)
    {
    advanceFilteringComboboxObjectTypeList[i]->setCurrentIndex(-1);
    advanceFilteringComboboxAttributeList[i]->setCurrentIndex(-1);
    advanceFilteringComboboxMathList[i]->setCurrentIndex(-1);
    advanceFilteringComboboxMinValueList[i]->setCurrentIndex(-1);
    advanceFilteringComboboxMaxValueList[i]->setCurrentIndex(-1);
    if(i < ADVANCE_FILTER_ROW_NUMBER - 1)
    advanceFilteringComboboxBooleanList[i]->setCurrentIndex(-1);
    }

    }

    //Add an advance filter row
    void MainWindow::on_advanceFilterAddRowPushButton_clicked()
    {
    advanceFilterCurrentRowNumber++; //advance the master row number

    if(advanceFilterCurrentRowNumber >= ADVANCE_FILTER_ROW_NUMBER)
    {
        advanceFilterCurrentRowNumber--;  // go back to original value since button is clicked more times than required
        return;
    }
    advanceFilteringComboboxObjectTypeList[advanceFilterCurrentRowNumber]->setVisible(true);
    advanceFilteringComboboxAttributeList[advanceFilterCurrentRowNumber]->setVisible(true);
    advanceFilteringComboboxMathList[advanceFilterCurrentRowNumber]->setVisible(true);
    advanceFilteringComboboxMinValueList[advanceFilterCurrentRowNumber]->setVisible(true);
    advanceFilteringComboboxMaxValueList[advanceFilterCurrentRowNumber]->setVisible(true);
    if(advanceFilterCurrentRowNumber < ADVANCE_FILTER_ROW_NUMBER - 1)
         advanceFilteringComboboxBooleanList[advanceFilterCurrentRowNumber]->setVisible(true);
    

    }

    //Remove an advance filter row
    void MainWindow::on_advanceFilterRemoveRowPushButton_clicked()
    {
    if(advanceFilterCurrentRowNumber == 0)
    return;

    advanceFilteringComboboxObjectTypeList[advanceFilterCurrentRowNumber]->setVisible(false);
    advanceFilteringComboboxAttributeList[advanceFilterCurrentRowNumber]->setVisible(false);
    advanceFilteringComboboxMathList[advanceFilterCurrentRowNumber]->setVisible(false);
    advanceFilteringComboboxMinValueList[advanceFilterCurrentRowNumber]->setVisible(false);
    advanceFilteringComboboxMaxValueList[advanceFilterCurrentRowNumber]->setVisible(false);
    if(advanceFilterCurrentRowNumber < ADVANCE_FILTER_ROW_NUMBER - 1)
        advanceFilteringComboboxBooleanList[advanceFilterCurrentRowNumber]->setVisible(false);
    
    advanceFilterCurrentRowNumber--;  //decrement the master row number
    

    }



  • I can't load the mainwindow.ui. Says too many characters. Is there a way I can upload the project as a whole?


  • Lifetime Qt Champion

    @leinad Upload your project to some file sharing service and post the link here



  • Here is a link to a small project. Thanks for your help!

    https://rapidshare.nu/Tb2ds8iboe/test_zip


  • Lifetime Qt Champion

    Your file is not available anymore.





  • It's been a while. Can someone take a look at this and provide some assistance?

    Thanks.



  • Old link expired so here is a new link to the project. Please help!

    https://filebin.net/iuymg1uuawa9dw9y


  • Lifetime Qt Champion

    Why did you add that scroll area alone in its own QSplitter ?



  • I'm trying to adjust the scrollarea size, this way users can show all or partial number of combo-boxes. If they expand to full size the scrollbar in the scroll area will disappear and they can see all the comboxes.


  • Lifetime Qt Champion

    You should rather add it to your already existing splitter. You don't have the effect you want because you put a single widget in a single splitter.


Log in to reply