Use Scrollbar with QGridLayout - c++

Currently I have this code to add several QLineEdits to ui.widget but I also need a vertical scrollbar in case of too many elements -> limited space available:
QGridLayout *gridLayout = new QGridLayout(ui.widget);
int rowIndex = 0, colIndex = 0;
for(auto number : m_numbers)
{
QLineEdit *lineEdit = new QLineEdit();
gridLayout->addWidget(lineEdit, rowIndex, colIndex, Qt::AlignLeft);
if(colIndex == 7)
{
colIndex = 0;
++rowIndex;
}
else ++colIndex;
}
ui.widget->setLayout(gridLayout);
How can I make it scrollable?

Use QScrollBar : The QScrollBar widget provides a vertical or horizontal scroll bar.
define a fix size for your widget and if user create too much QLineEdit, add your customized QScrollBar to that widget.
QScrollBar * scroll = new QScrollBar(Qt::Vertical, ui->widget);
OR use QScrollArea like this image:
This is a sample project for your question on github download here.

Related

Issue change tab QTabWidget & QScrollArea Qt

I'm trying to create a QScrollArea in a QTabWidget.
Versions :
Qt 5.15.0
Qt creator 4.12.4
MSVC2019 64 bits
First of all, I've created the QTabWidget :
tabWidget = new QTabWidget(this);
tabWidget->setGeometry(10, 15, 1200, 665);
tabWidget->setStyleSheet("font-size : 15px");
tab1Content = new QWidget(tabWidget); tabWidget->addTab(tab1Content, "tab1");
tab2Content = new QWidget(tabWidget); tabWidget->addTab(tab2Content, "tab2");
tab3Content = new QWidget(tabWidget); tabWidget->addTab(tab3Content, "tab3");
tab4Content = new QWidget(tabWidget); tabWidget->addTab(tab4Content, "tab4");
I can add
tabWidget->setEnable(true);
And for all tabs, 0 <= i < tabWidget.count
tabWidget->setTabEnabled(i, true);
Click to change tab doesn't work : https://i.stack.imgur.com/8r1Jg.png
Strange thing : color looks like enabled but i can only change tabs with ← → and when i lost tabWidget focus by clicking on an other thing outside the tabWidget, i can't regain focus.
So i've created temporary button to change tabs and linked to tabWidget like that :
connect(changeTab, &QPushButton::clicked, [&]() {onChangeTab();});
void MainWindow::onChangeTab() {
tabWidget->setCurrentIndex(tabWidget->currentIndex() >= tabWidget->count() - 1 ? 0 : tabWidget->currentIndex() + 1);
}
It works well.
Thus, I've start to create the QScrollArea :
First, it doesn't work, so I've tried to found sth on internet :
QScrollArea not working as expected with QWidget and QVBoxLayout
My result : https://i.stack.imgur.com/jvVol.png
I cannot click on a single button and i can't scroll...
And if i try to force scroll like this, it doesn't scroll
scrollArea->scroll(0, 50);
Last thing, there isn't infinite loop or dead lock things because all things around this cursed tabWidget and scroll Area work perfectly.
I don't know why these objects "don't answer" if somedoby had this kind of experiment could you help me please ?
Thank you very much in advance.
try this code
#include "widget.h"
#include<QTabWidget>
#include<QLabel>
#include<QVBoxLayout>
#include<QScrollArea>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QTabWidget *tabWidget = new QTabWidget(this);
tabWidget->setGeometry(10, 15, 1200, 665);
tabWidget->setStyleSheet("font-size : 15px");
QWidget * tab1Content = new QWidget;
//preparing tab1content ( e.g.)
QVBoxLayout * verticalLayout = new QVBoxLayout;
// adding items to vertical layout
for(int i=0;i<100;i++)
verticalLayout->addWidget(new QLabel(QString::number(i)));
// set this vertical layout inside tab1content
tab1Content->setLayout(verticalLayout);
// create new scroll area ...
QScrollArea * scroll = new QScrollArea;
// ... and add tab1content in scroll area
scroll->setWidget(tab1Content);
// and finally add scroll area inside tabwidget
tabWidget->addTab(scroll,"tab1");
QWidget * tab2Content = new QWidget; tabWidget->addTab(tab2Content, "tab2");
QWidget * tab3Content = new QWidget; tabWidget->addTab(tab3Content, "tab3");
QWidget * tab4Content = new QWidget; tabWidget->addTab(tab4Content, "tab4");
}
Widget::~Widget()
{
}

How to replace the QListWidget's icons with a custom widget?

Currently I have a QListWidget with viewMode set to Icon.
Is there a way to use a custom widget or painting instead of icon?
mTestLV = new QListWidget;
mTestLV->setIconSize(QSize(128, 128));
mTestLV->setViewMode(QListView::ViewMode::IconMode);
auto icon = QIcon("../../Resources/PCPP.jpg");
for (size_t i = 0; i < 64; i++)
mTestLV->addItem(new QListWidgetItem(icon, "naaaame"));
You can use setItemWidget to display a widget in a QListWidgetItem. Just create a QListWidgetItem, add it to your QListWidget, then set your custom widget on the item:
QListWidgetItem *item = new QListWidgetItem();
CustomWidget *custom = new CustomWidget();
mTestLV->addItem(item);
mTestLV->setItemWidget(item, custom);

How can I adjust the window size of a QDialog to its content?

I have a dialog box with a QScrollArea to show an arbitrary amount of checkboxes. How can I make the dialog box adjust its width so that the QScrollArea does not have a horizontal scroll bar (if the content is not extremely wide).
std::vector<std::string> vec_strCheckboxLabel;
vec_strCheckboxLabel.push_back("Checkbox 1");
vec_strCheckboxLabel.push_back("Checkbox 2");
vec_strCheckboxLabel.push_back("Checkbox 3 is really long and causes a horizontal scroll bar to appear");
vec_strCheckboxLabel.push_back("Checkbox 4");
vec_strCheckboxLabel.push_back("Checkbox 5");
m_pWidget = new QDialog;
m_pWidget->setWindowTitle("My Dialog");
m_pWidget->setWindowModality(Qt::ApplicationModal);
m_pWidget->setMinimumWidth(400);
QVBoxLayout * pWidgetLayout = new QVBoxLayout(m_pWidget);
QLabel * pLabel = new QLabel("Hello");
pWidgetLayout->addWidget(pLabel);
QHBoxLayout * pTopButtonsLayout = new QHBoxLayout(m_pWidget);
pWidgetLayout->addLayout(pTopButtonsLayout);
QPushButton * pButton;
pButton = new QPushButton("Select all", m_pWidget);
connect(pButton, SIGNAL(clicked()), this, SLOT(slotSelectAll()));
pTopButtonsLayout->addWidget(pButton);
pButton = new QPushButton("Select none", m_pWidget);
connect(pButton, SIGNAL(clicked()), this, SLOT(slotSelectNone()));
pTopButtonsLayout->addWidget(pButton);
// the checkboxes in a scroll area
{
QFrame * pFrameCheckboxes = new QFrame(m_pWidget);
QVBoxLayout * pCheckboxesLayout = new QVBoxLayout(pFrameCheckboxes);
// this frame takes all available space in the QDialog
pFrameCheckboxes->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
for (unsigned int i = 0, iEnd = vec_strCheckboxLabel.size(); i != iEnd; ++i)
{
QCheckBox * poCheckBox = new QCheckBox(vec_strCheckboxLabel[i].c_str());
pCheckboxesLayout->addWidget(poCheckBox);
}
// put into scroll area
QScrollArea * pScrollAreaTheCheckboxes = new QScrollArea(m_pWidget);
pWidgetLayout->addWidget(pScrollAreaTheCheckboxes);
pScrollAreaTheCheckboxes->setWidget(pFrameCheckboxes);
}
The problem is the scroll area limits its size to take available space by default; it does not demand space from the layout. You have to explicitly tell it to change that behavior.
Check out QAbstractScrollArea::SizeAdjustPolicy. You are probably looking for AdjustToContentsOnFirstShow, like so:
pScrollAreaTheCheckboxes->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
Unfortunately, you cannot set different adjust policies for horizontal and vertical aspects, if this is what you are after. Judicious use of QSizePolicy and layout settings (e.g. setStretch()) can fix this.
Qt4
As a workaround for Qt4, check the viewport's sizeHint() and set the scroll area's minimum size to that.
pScrollAreaTheCheckboxes->setMinimumSize(pScrollAreaTheCheckboxes->viewport()->sizeHint());
Do this after you've initialized all of your checkboxes.

QScrollArea issue with vertical scroll

I have read few pages about QScrollArea, and I couldn't solve my issue. I have the next code:
QDialog *window = new QDialog;
window->resize(300, 300);
for(int i = 0; i < 50; ++i)
{
QLabel *label = new QLabel(window);
label->move(10, i * 15);
label->setText("Text");
}
QScrollArea *area = new QScrollArea;
area->setWidget(window);
area->show();
It seems that the vertical scroll from QScrollArea doesn't appear. I can't use QVBoxLayout because on my QDialog I don't have only QLabels aligned vertically ( this is just a simplified version of my QDialog ).
The QScrollArea won't get scrollbars unless the QWidget inside grows. Just moving some QLabels out of bounds doesn't make the parent QWidget grow, especially without a QLayout.
But if you manually resize them so that the QWidget is bigger than the QScrollAreay, you'll get scroll bars as expected :
QDialog *window = new QDialog;
window->resize(300, 600); //< 600px high widget
for(int i = 0; i < 50; ++i)
{
QLabel *label = new QLabel(window);
label->move(10, i * 15);
label->setText("Text");
}
QScrollArea *area = new QScrollArea;
area->setWidget(window);
area->resize(300,300); //< Inside a 300px high scrollarea, expect scrollbars!
area->show();
Note that now you will have both scroll bars, because the vertical scroll bar means there isn't enough room for our 300px width anymore. You can forcefully hide the horizontal scroll bar with area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
You could also always force a vertical scroll bar to appear with area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);, but this by itself wouldn't solve your problem. You'd still have a 300px widget inside a 300px area, and the scrollbar wouldn't have any space to move.
Making sure the QWidget is big enough for everything it contains is what you'll want to do, the QScrollArea will adapt. Usually we use layouts for that, but you can make it work by hand as well.

Error in Qt: QMainWindowLayout::addItem: Please use the public QMainWindow API instead

for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
QLineEdit *newEdit = new QLineEdit(" ");
newEdit->setGeometry(y * 50, x * 25, 50, 25);
newEdit->setText("0");
layout()->addWidget(newEdit);
objMatrix[y + x * size] = newEdit;
}
}
I am using that code to add widgets dynamicly. Then i get this error:
QMainWindowLayout::addItem: Please use the public QMainWindow API instead
As many times, as code layout()->addWidget(newEdit); has worked.
What should i do to prevent it?
Sorry for my english.
You should work with layouts in another way because in your code widget has not aby layout, so your pointer to layout is bad, so you programm crashes. Try In constructor for example:
        
QWidget *centralWidget = new QWidget(this);   
QGridLayout *layout = new QGridLayout();
centralWidget->setLayout(layout);
        
layout->addWidget(new QPushButton("Button  1"),0,0);
layout->addWidget(new QPushButton("Button  2"),0,1);    
layout->addWidget(new QPushButton("Button  3"),0,2);    
 
setCentralWidget(centralWidget);
If you want set position of widgets yourself then you don't need layout at all. Just set centralWidget as parent to all your another widgets and call setGeometry without any issue. Note that in this case top left corner of centralWidget will have 0;0 coordinates for child widgets.
You must first add central widget in window. And insert widgets in him.