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.
Related
Given this example:
Suppose A and B are QWidgets
Is it possible to keep everything starting from B static when the QScrollArea widget is scrolled?
The QScrollArea occupies the entire GUI, B is inside it to let the vertical ScrollBar closer to the right border of the GUI, or it would look like this:
What I can do in this case?
It is possible. You have to make use of the scrollbar being a widget of its own.
Here is the method:
Change your window in Qt Designer to be: spacer, QScrollArea (that will contain widget A), spacer, widget B, spacer; everything is in a QGridLayout (or QHBoxLayout but please read until the end).It is because widget B is outside the scroll area that it will not move during scrolling.
In your widget constructor, after ui->setupUi(); reparent and move the vertical scrollbar of your QScrollArea with these lines of code:
scrollArea->verticalScrollBar()->setParent(w);
layout->addWidget(sa->verticalScrollBar()); //Adds the scrollbar to the right of the layout.
Note about the margins:Obviously, you can easily push the scrollbar to the very right of your window by setting the layout right margin to 0.
If you also want it to cover the entire height of your window, while keeping some space between the other widgets and the window's border, that is where a QHBoxLayout will not suffice and you need a QGridLayout instead, set its top and bottom margin to 0 and add spacers (fixed size) to obtain the same visual result.
The C++ code for such a window would be:
QWidget* widget = new QWidget();
QGridLayout* layout = new QGridLayout(widget);
layout->setSpacing(0);
layout->setContentsMargins(9, 0, 0, 0);
widget->setLayout(layout);
QScrollArea* scrollArea = new QScrollArea(widget);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
QWidget* widgetB = new QLabel("Widget B", widget);
//Creates the spacer that will "simulate" the top and bottom margins
QSpacerItem* topSpacer = new QSpacerItem(0, 9, QSizePolicy::Minimum, QSizePolicy::Fixed),
* bottomSpacer = new QSpacerItem(0, 9, QSizePolicy::Minimum, QSizePolicy::Fixed);
layout->addItem(topSpacer, 0, 0);
layout->addWidget(scrollArea, 1, 0);
layout->addItem(bottomSpacer, 2, 0);
layout->addWidget(widgetB, 1, 1);
//Moves the scrollbar outside the scroll area
scrollArea->verticalScrollBar()->setParent(widget);
layout->addWidget(scrollArea->verticalScrollBar(), 0, 2, 3, 1);
QLabel* innerLabel = new QLabel("Some big label to force the scrolling");
scrollArea->setWidget(innerLabel);
innerLabel->setMinimumHeight(500);
widget->show();
I'm getting closer to getting a QScrollArea working, but it's still shrinking my custom widgets as they are added. Everything is resizing fluidly, and if the scroll area is too small, then the scroll bar appears, so it clearly has some idea of a minimum size.
At start, with two custom widgets in the scroll area, you can see some shrinking:
Here's the same window below the critical point. The text is now completely gone, but it won't shrink the QLineEdit, so it finally adds a scrollbar. (the scroll area has a blue background, the content widget is the purple)
I started in Design, but everything below the scroll area's widget is in code, as I was having trouble getting the vertical layout to work right using design.
Here's the starting point:
There's a page in a StackWidget that has two elements in a vertical layout. The scroll area has a QWidget. The constructor for MainWindow defines a vertical layout, assigning it to the member scrollWidgetLayout, and giving that layout to the scroll area's widget:
scrollWidgetLayout = new QVBoxLayout(ui->scrollAreaWidgetContents);
ui->scrollAreaWidgetContents->setLayout(scrollWidgetLayout);
The app starts on the first page of the stack widget, the user logs in, and the app runs off to fetch records from the server. Each record is turned into a widget:
RecordFolderWidget::RecordFolderWidget(Record *r, QWidget *parent) : QWidget(parent)
{
record = r;
//setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
QGridLayout *layout = new QGridLayout();
pathLineEdit = new QLineEdit();
finderButton = new QPushButton("...");
QLabel *nameLabel = new QLabel(record->name);
layout->setSpacing(5);
layout->setMargin(3);
layout->addWidget(nameLabel, 0, 0, 0, 1, Qt::AlignCenter);
layout->addWidget(pathLineEdit, 1, 0);
layout->addWidget(finderButton, 1, 1);
setLayout(layout);
//setMinimumHeight(sizeHint().height());
}
Note that there are some lines commented out, these are things I have been playing with to try to get it to work. The sizeHint, btw, appears to be correct, and does not change.
Once that Widget is created, it gets added to the scroll area's widget:
RecordFolderWidget *rf = new RecordFolderWidget(record);
rf->setParent(ui->scrollAreaWidgetContents);
scrollWidgetLayout->addWidget(rf);
I tried here to also resize the scroll areas contents, with no luck:
ui->scrollAreaWidgetContents->resize(rfSize.width(), rfSize.height() * records.count());
where rfSize was pulled from the custom widget's sizeHint after it was created, and this line was called once after the loop to create/add all of the widgets.
Other than the setMinimumHeight and resize above, I've tried changing the SizePolicy for the scrollAreaWidgetContents from preferred to expanding to minimumexpanding and did not see any difference. I'm sure I've missed something trivial, but just can't find it.
The problem that I see in your code is when adding the QLabel you are setting the rowSpan to 0, I have changed it and I can observe it correctly. In the next part I show my test code and the result:
QVBoxLayout *scrollWidgetLayout = new QVBoxLayout(ui->scrollAreaWidgetContents);
for(int i=0; i<10; i++){
QWidget *widget = new QWidget;
QGridLayout *layout = new QGridLayout(widget);
QLineEdit *pathLineEdit = new QLineEdit;
QPushButton *finderButton = new QPushButton("...");
QLabel *nameLabel = new QLabel(QString("name %1").arg(i));
layout->setSpacing(5);
layout->setMargin(3);
layout->addWidget(nameLabel, 0, 0, 1, 1, Qt::AlignCenter);
layout->addWidget(pathLineEdit, 1, 0);
layout->addWidget(finderButton, 1, 1);
scrollWidgetLayout->addWidget(widget);
}
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.
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.
I have been messing with this problem for hours, and decided it's time to ask SO :)
I have a Qt program that rotates an image and then updates the size of the widget. Here is the code I'm using to do this currently.
void VideoSubWindow::showFrame(const QImage& frame)
{
QPixmap pixmap = QPixmap::fromImage(frame);
ui->videoFrameLabel->setPixmap(pixmap);
resizeWidgets(pixmap.size());
}
void VideoSubWindow::resizeWidgets(const QSize &size)
{
if(frameSize != size)
{
frameSize = size;
ui->videoFrameLabel->setFixedSize(size);
ui->scrollArea->setMinimumSize(size.width() + 2, size.height() + 2);
}
}
The widgets are structured as follows:
VideoSubWindow (QMainWindow)
-> centralWidget (QWidget) (Vertical layout is set on this)
-> scrollArea (QScrollArea)
-> videoFrameLabel (QLabel)
-> statusBar (QStatusBar)
-> menuBar (QMenuBar)
When the code above is executed, like rotating the image 90 degrees, the image will be rotated, but the window doesn't resize to fit the new pixmap size. I have tried to call adjustSize() and updateGeometry() on SubWindow and centralWidget, but those seem to have zero effect. But, if I manually resize the window with my mouse, the window snaps to the minimum size that was set for the scrollArea, so that seems to be taking effect.
Does anyone have experience with this? Thanks!
Try with the resize(...) function : Qt documentation
adjustSize() used sizeHint() function, so calling adjustSize() on SubWindow and centralWidget cannot have any effet