QScrollArea within QDialog - c++

I have created a QDialog of size 720x480. I added 100 QLabels on it, and after that I created a QScrollArea, which has as widget the QDialog:
QDialog *window = new QDialog;
window->setWindowTitle("My Dialog");
window->setFixedSize(720, 480);
for(int i = 0; i < 100; ++i)
{
QLabel *label = new QLabel(window);
label->setText(QString::number(i));
label->move(10, i * 100);
}
QScrollArea area;
area.setWidget(window);
window->exec();
But the result is not that expected (like the vertical scrollbar to appear and to work properly ).

Your window has fixed height (to 480) and you place labels far beyond this size (last one will be placed at position 10, 9900).
You need to change your window's size.

Related

Why adjustSize doesn't resize MainWindow in Qt?

I have a simple application. In MainWindow's constructor I have:
_someWidget = new someWidgetClass(this);
_someWidget ->setFixedSize(700,700);
_someWidget ->move(50,50);
wid = new QWidget(this);
wid->move(800,800);
wid->setFixedSize(100,100);
centralWidget()->adjustSize();
adjustSize();
I would like to resize MainWindow like that, his right bottom corner should be the right bottom corner of the wid, so I would like to resize MainWindow to his contents. But adjustSize doesn't work.
I tried to add sizeHint() method in someWidgetClass and return his size, but this doesn't help too.
you should set one layout for centralWidget , For Example, I test it with QGridLayout. then add your widget in that layout :
auto _someWidget = new QWidget(this);
_someWidget->move(50, 50);
_someWidget->setFixedSize(700, 700);
centralWidget()->layout()->addWidget(_someWidget);
auto wid = new QWidget(this);
wid->move(800, 800);
wid->setFixedSize(100, 100);
centralWidget()->layout()->addWidget(wid);
centralWidget()->adjustSize();
adjustSize();
about adjustSize Function :
Adjusts the size of the widget to fit its contents. This function uses
sizeHint() if it is valid, i.e., the size hint's width and height are
>= 0. Otherwise, it sets the size to the children rectangle that covers all child widgets (the union of all child widget rectangles).
For windows, the screen size is also taken into account. If the
sizeHint() is less than (200, 100) and the size policy is expanding,
the window will be at least (200, 100). The maximum size of a window
is 2/3 of the screen's width and height.

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.

How to make Qt subwidget height equal?

I have some QDockWidgets (not floating, only closable) inside a single QWidget.
I have some widgets inside each QDockWidget - their heights should be equal.
These inner widgets can be hidden through the context menu.
My inner widgets should have equal height. I done it this way:
void MyDocksPanel::redistributeSpace()
{
QBoxLayout * lay = (QBoxLayout *)layout();
for (int i = 0; i < lay->count(); i++)
{
QWidget * dock = lay->itemAt(i)->widget();
if (dock == NULL)
continue;
int size = 0;
foreach(QWidget * subWidget, dock->findChildren<QWidget*>())
size += subWidget->isVisible() ? 1 : 0;
if (dock->isVisible() && (size == 0))
dock->hide();
lay->setStretch(i, size);
}
}
All works fine until I add some const elements to each QDockWidget: some horizontal scrollbars and some Labels... Now my inner widgets have different sizes. But it is necessary for me to set their heights strongly equal.
QLayout lays out widget sizes on one level of a widget's hierarchy. How can I make height-equal subwidgets?
3 subwidgets vs 2 subwidgets
My first strategy to set stretches 3 and 2:
But, when i have added scroll bars:
Heights of my 5 widgets are equals to 37,37,37,28,28 ... and thats the problem
You're on the right track with the stretch factors, but think in terms of pixel values rather than small proportions. Try setting the stretch factor of each dock widget to this:
dockWidgetStretch = numChildWidgets * childWidgetMinimumHeight + scrollBarHeight;
where childWidgetMinimumHeight and scrollBarHeight are both expressed in pixels, and are both constants.
EDIT: Here is a working example. You might have to experiment a bit to get it to work with your program, but this should be a good start.
header.h
#include <QtGui>
class WidgetWith3Children : public QWidget
{
public:
WidgetWith3Children()
{
QTextEdit *edit1 = new QTextEdit;
QTextEdit *edit2 = new QTextEdit;
QTextEdit *edit3 = new QTextEdit;
QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(edit1);
layout->addWidget(edit2);
layout->addWidget(edit3);
layout->addWidget(scrollBar);
setLayout(layout);
}
};
class WidgetWith2Children : public QWidget
{
public:
WidgetWith2Children()
{
QTextEdit *edit1 = new QTextEdit;
QTextEdit *edit2 = new QTextEdit;
QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(edit1);
layout->addWidget(edit2);
layout->addWidget(scrollBar);
setLayout(layout);
}
};
class OuterWidget : public QWidget
{
public:
OuterWidget()
{
QDockWidget *dockWidget1 = new QDockWidget;
QDockWidget *dockWidget2 = new QDockWidget;
dockWidget1->setWidget(new WidgetWith3Children);
dockWidget2->setWidget(new WidgetWith2Children);
QVBoxLayout *layout = new QVBoxLayout;
// 71 is the height of the minimum size hint for QTextEdit
// 30 is the height of a horizontal scrollbar (on my system)
layout->addWidget(dockWidget1, 71 * 3 + 30);
layout->addWidget(dockWidget2, 71 * 2 + 30);
layout->setMargin(0);
setLayout(layout);
}
};
main.cpp
#include <QtGui/QApplication>
#include "header.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
OuterWidget w;
w.show();
return a.exec();
}
Just to check I understand: you have a QDockWidget which contains multiple children, as well as a label and a horizontal scrollbar. The label and scrollbar should be of fixed height, and the remaining vertical space should be divided between the child widgets.
If that's correct, all you need to do is add a QVBoxLayout to each QDockWidget. Add your widgets as I've done below:
QDockWidget DockWidget;
QVBoxLayout Layout = new QVBoxLayout(DockWidget);
FixedHeightWidget.setFixedHeight(10)
Layout.addWidget(FixedHeightWidget, 0);
Layout.addWidget(FirstVariableHeightWidget, 1);
Layout.addWidget(SecondVariableHeightWidget, 1);
Layout.addWidget(ThirdVariableHeightWidget, 1);
If you were to hide any of the widgets you've added to the layout, the layout will handle resizing the remaining visible children.