Automatically resizing a window based on its contents - qt

I have a QDialog subclass that contains a spacer as its only immediate child; all of the window’s UI elements are contained in the spacer. The user cannot change the window size directly, but UI elements will be shown or hidden as the user interacts with the window. I’d like the dialog to resize each time this happens so that the spacer (and the dialog itself) always takes up the minimum possible amount of space. How can I configure my dialog and my spacer to get the desired behavior?
(This question dealt with something similar, although in that case the user was able to resize the window. It was also not clear to me what the OP actually ended up doing in that case.)

You can resize the window to minimumSizeHint() after the number of widgets is changed :
resize(minimumSizeHint());
This will shrink the window to minimum size. But you should consider that the minimum size is not computed until some events are processed in the event loop. So after some widgets are hidden and some other are shown, just process the event loop for some iterations and then resize to minimum.
It's like :
for(int i=0;i<10;i++)
qApp->processEvents();
resize(minimumSizeHint());
A better solution is to single shot a QTimer which calls a slot in which you resize the window to minimum. This way when you resize the window, the minimum size hint is computed correctly.

void QWidget::adjustSize()
Adjusts the size of the widget to fit its contents.

Related

Resize QDialog at a runtime

I have a QDialog subclass containing some options of my application. Some of the options are core, the other are advanced, so I decided to put them into separeted checkable QGroupBox.
I want my dialog to shrink verticaly when the user checked off advanced options box, but I can't find the way to do it properly - the dialog size stays exactle the same
I set dialog's size policy to Expanding, tried to call adjustSize() and tried to call resize() method - nothing helps. I can't resize programmaticaly dialog to be smaller then it's current size (it only can become larger). At the same time, it is possible to resize it manualy.
Can anybody help me?
If you don't need manual resize, you can add
layout()->setSizeConstraint(QLayout::SetFixedSize);
to the dialog constructor, then the layout takes over the responsibility to automatically resize when widgets are shown or hidden.

How to set the desired size of a QMainWindow with QScrollArea?

I am working on a project where I have to display a pretty large (vertically) main Widget.
In the initial Version of my GUI it was just added as the central Widget of a QMainWindow, which caused the Problem that on small screen resolutions the controls on the Bottom of the Widget are unreachable.
To solve this i wrapped a QScrollArea around the main Widget, but now the main window is always relatively small even if it doesn't have to.
What do i need to change so the Main Windows (vertical) size is large enough to show all the contents unless it would be too large for the screen resolution? Also I don't want it to be stretched, so simply always using the whole vertical screen resolution is not an option. Ideally the size should be fixed to the size needed by the contents (w/o the scroll area) and only smaller where needed.
Overriding the sizeHint method did only resulted in a small enlargement of the Window and setting the minimal height brings me back to the beginning where some of the controls are not assessable on small resolutions.
Since i am new to QT I am actually out of ideas how to google the solution because most Solutions I can find are about sizing components inside a Window and not the Window itself.
By default a QScrollArea will not attempt to expand to fit its contents. In order to do this you will need to re-implement QScrollArea's sizeHint() to return the size of QScrollArea's child widgets.
In your question it sounds like you were trying to re-implement MainWindow's sizeHint? re-implementing sizeHint on the top-level window will have no effect as sizeHint designed for use with widgets inside layouts.

Size and position of child windows in QMdiArea

I have QMdiArea object in QMainWindow which I did not have set with setCentralWidget() but as mentioned below.
MainWindow::createMdiArea() {
QMdiArea mdiArea = new QMdiArea(this)
mdiArea.setGeometry(0,0,1024,600);
mdiArea.show();
}
I don't want to set this QMdiArea as the center widget. Now I am creating some child windows inside this QMdiArea, as following
MainWindow::createChildWindow()
{
HelpWindow child1 = new HelpWindow(). // HelpWindow is a very simple class derived from QWidget and containing one QLineEdit.
mdiArea.addSubWindow(&child1);
// Set the geometry of Child widget.
child1.parentWidget()->setGeometry(0,0,400,100); // Setting geometry which I have saved.
child1.show();
}
So far so good. But the problem is in the child window resize / close events I need to save the size of the HelpWindow and I am doing following to save the size of the child window in its resize / close events.
saveHelpWindowSize(size());
saveHelpWindowPos(pos());
Ok. Here comes the problem. The size I have got from the size() function inside the child window is different from the one which I have used in setGeometry() function, even I see it in some method other than resize event (i.e Close event).
So, Suppose first time the child window was created with the size (using setGeometry) 400, 200, when I go to close this window the size I will get from HelpWindow::size() might be say (385, 190) which I will save, and next time setGeometry() will get this size from settings, and at this time on close event I will get more smaller size, and eventually my child window will have size (0, 0).
1: Any thoughts on how to sync both these sizes (i.e., the size if the child widget being set by setGeometry() function and the size of the widget I am getting from size() function of the widget)
2: Another question, I am receiving resizeEvent / closeEvent events etc in the child widget (HelpWindow) class, but I am not getting moveEvent when I move the child window inside QMdiArea, the only time I receive this event is when I maximize the child window inside QMdiArea (which I won't be doing). So I need to save the position of my child window when its position is changed. How can I do it?

I want qt window to resize proportional

Just as the title said, when I resize the window, if I make it widen , I want the window's height resize proportional to make the window has the same ratio.
I just do the logic in paintEvent, but it doesn't work fine, can some guys have any solution?
I don't think do resizing in resizeEvent is a great way, the best result is that window flickering, but I want the fluent way
Don't do it in paintEvent but instead void QWidget::resizeEvent ( QResizeEvent * event ). Then you can compare event->size() and event->oldsize() to see which dimension got changed, then resize to match the other dimension to the changed one.
EDIT: Note that when you resize the window inside the resizeEvent function, you will create another resize event. So make sure you only resize if there's been a change that brought the window to a wrong aspect ratio, otherwise you will create infinite recursion to the function and a stack overflow.

Resizing QT's QTextEdit to Match Text Height: maximumViewportSize()

I am trying to use a QTextEdit widget inside of a form containing several QT widgets. The form itself sits inside a QScrollArea that is the central widget for a window. My intent is that any necessary scrolling will take place in the main QScrollArea (rather than inside any widgets), and any widgets inside will automatically resize their height to hold their contents.
I have tried to implement the automatic resizing of height with a QTextEdit, but have run into an odd issue. I created a sub-class of QTextEdit and reimplemented sizeHint() like this:
QSize OperationEditor::sizeHint() const {
QSize sizehint = QTextBrowser::sizeHint();
sizehint.setHeight(this->fitted_height);
return sizehint;
}
this->fitted_height is kept up-to-date via this slot that is wired to the QTextEdit's "contentsChanged()" signal:
void OperationEditor::fitHeightToDocument() {
this->document()->setTextWidth(this->viewport()->width());
QSize document_size(this->document()->size().toSize());
this->fitted_height = document_size.height();
this->updateGeometry();
}
The size policy of the QTextEdit sub-class is:
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
I took this approach after reading this post.
Here is my problem:
As the QTextEdit gradually resizes to fill the window, it stops getting larger and starts scrolling within the QTextEdit, no matter what height is returned from sizeHint(). If I initially have sizeHint() return some large constant number, then the QTextEdit is very big and is contained nicely within the outer QScrollArea, as one would expect. However, if sizeHint gradually adjusts the size of the QTextEdit rather than just making it really big to start, then it tops out when it fills the current window and starts scrolling instead of growing.
I have traced this problem to be that, no matter what my sizeHint() returns, it will never resize the QTextEdit larger than the value returned from maximumViewportSize(), which is inherited from QAbstractScrollArea. Note that this is not the same number as viewport()->maximumSize(). I am unable to figure out how to set that value.
Looking at QT's source code, maximumViewportSize() is returning "the size of the viewport as if the scroll bars had no valid scrolling range." This value is basically computed as the current size of the widget minus (2 * frameWidth + margins) plus any scrollbar widths/heights. This does not make a lot of sense to me, and it's not clear to me why that number would be used anywhere in a way that supercede's the sub-class's sizeHint() implementation. Also, it does seem odd that the single "frameWidth" integer is used in computing both the width and the height.
Can anyone please shed some light on this? I suspect that my poor understanding of QT's layout engine is to blame here.
Edit: after initially posting this, I had the idea to reimplement maximumViewportSize() to return the same thing as sizeHint(). Unfortunately, this did not work as I still have the same problem.
I have solved this issue. There were 2 things that I had to do to get it to work:
Walk up the widget hierarchy and make sure all the size policies made sense to ensure that if any child widget wanted to be big/small, then the parent widget would want to be the same thing.
This is the main source of the fix. It turns out that since the QTextEdit is inside a QFrame that is the main widget in a QScrollArea, the QScrollArea has a constraint that it will not resize the internal widget unless the "widgetResizable" property is true. The documentation for that is here: http://doc.qt.io/qt-4.8/qscrollarea.html#widgetResizable-prop. The documentation was not clear to me until I played around with this setting and got it to work. From the docs, it seems that this property only deals with times where the main scroll area wants to resize a widget (i.e. from parent to child). It actually means that if the main widget in the scroll area wants to ever resize (i.e. child to parent), then this setting has to be set to true.
So, the moral of the story is that the QTextEdit code was correct in overriding sizeHint, but the QScrollArea was ignoring the value returned from the main frame's sizeHint.
Yay! It Works!
You may try setting minimumSize property of the QTextEdit to see if that force the layout to grow.
I don't understand most of Qt's layout scheme but setting minimum and maximum size pretty much does what I want it to do. Well, most of the time anyways.

Resources