QMainWindow::showMaximized() Doesn't Update Size - qt

I'm trying to create a QMainWindow to encapsulate a QGraphicsView that I'm putting in it. I want it to start out maximized, so I do this:
QMainWindow *mainWindow = new QMainWindow();
mainWindow->setWindowState(Qt::WindowMaximized);
mainWindow->show();
qDebug() << mainWindow->size();
Which says my maximized window is 200x100, which is obviously incorrect.
Am I missing some sort of update function? I don't get why it wouldn't update the size. I've also tried using showMaximized() with the same result.
EDIT
My end-goal is to use the QMainWindow as a container for a QGraphicsView containing a QGraphicsScene. On top of all this, I want to have a QWebView at 50% width and 100% height, centered over everything.
So, I need the width and height in order to get all the coordinates and sizes correct.

Well, the effect of setWindowState() is not immediate, it gets executed asynchronously. When the window state changes, the widget receives a changeEvent(), so you should reimplement this or resizeEvent() to get the width() and height() after the maximization takes place.

Related

how to specify the height of scrollbar in QTreeView

just like the title described, when i redraw the scrollbar in QTreeView which has a header(QHeaderView), but the scrollbar's height is the entire height of QTreeView, and i want to let the scrollbar's height equals the QTreeView's height minus the header's height.just like the pic below:
A solution for your problem might be setting the location of the vertical scrollbar to a constant_offset value acquired from the QHeaderView (on the y axis).
This could be done by subclassing the QTreeView like so:
class MyTreeView : public QTreeView
{
public:
MyTreeView(QWidget* parent = nullptr): QTreeView(parent){}
void updateVertScrollBar()
{
auto* ptr = verticalScrollBar();
QRect rect = ptr->geometry();
rect.setTop(header()->height());
ptr->setGeometry(rect);
}
void resizeEvent(QResizeEvent* ev) override
{
QTreeView::resizeEvent(ev);
updateVertScrollBar();
}
};
Depending on the sizePolicy the updateVertScrollBar method could be called just after data is filled or as presented in the sample implementation the update can occur for each resizeEvent - which should cover various resizing performed to the widget.
EDIT
Additionally removing the blank space left from the shrunk scrollbar would be tricky. First denote that the QTreeView is built from a viewport widget and scrollbars (among others). The issue you now see comes from the fact that viewport plus vertical scrollbar widths (if visible) should match and this is calculated internally.
I stated that it's tricky since there is a load of stuff happening when you try to force the size of these components. Some updates are called in-place some are called through the event loop. You can check this to get more detaile info about the concept. Similar approach is probably applied to QTreeView.
Basically what you would need to do is to stretch the viewport width. This should be probably done during the resizeEvent but calling from there methods like viewport()->setGeometry() might not end well - you might get caught into a loop. You might try blockSignals but I'm not sure this would help. In general if you want to mess with the internals of a given Qt widget you should go through it's implementation at least briefly.

Automatically resizing a window based on its contents

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.

Resize window to fit content

I have a QGLWidget, which I want to resize to a given resolution (bigger than the containing window).
My intention is, that the window expands until the widget fits inside, but can't find a way to do it.
I tried several commands after resizing the QGLWidget to make it work without success.
I will list the results here:
do nothing else: The Widget overlaps the whole window. Eventually it will be resized to fit back into the smaller window
mainWindow.adjustSize(): The widget gets resized to (0, 0)
mainWindow.resize(mainWindow.sizeHint()): see above
mainWindow.resize(mainWindow.minimumSizeHint()): see above
I also read in this thread, that before doing the mainWindow resize I the event loop needs to be run to recalculate the new sizes, so I inserted QCoreApplication::processEvents to do so, without any visible effect.
So how do I resize the window via the widget?
Edit
The GLWidget is not the only widget of the window.
It is embedded in splitter together with a group box.
http://qt-project.org/doc/qt-4.8/qwidget.html#sizePolicy-prop
http://qt-project.org/doc/qt-4.8/qsizepolicy.html#Policy-enum
http://qt-project.org/doc/qt-4.8/qwidget.html#setFixedSize
So assuming that you have your QGLWidget nested inside your QMainWindow as the central widget, you need to set the size policy of your QGLWidget.
For example:
QGLWidget * glw; // in your header for QMainWindow
...
// In your constructor for QMainWindow
glw = new QGLWidget;
this->setCentralWidget(glw);
glw->setFixedSize(500, 500);
this->adjustSize();
Hope that helps.
I have an app that needed to be very similar to your requirements, so I'll post my solution here. An image covering the window which is freely expandable and shrinkable, and can be changed to the original size, and remain expandable / shrinkable after that.
I used a QLabel widget to display the image, but it should work with other widget types too. I created the widget with an initial size and the QSizePolicy::Ignored.
label->resize (w, h); // initial size
label->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored);
The label widget was in a QVBoxLayout with a few buttons in the window, but this may work with other layout types too.
The window and image widget can be resized to the image's original size with this code:
label->resize (w, h); // change to original size
label->setMinimumSize (w, h); // prevent it from collapsing to zero immediately
window->adjustSize (); // resize the window
label->setMinimumSize (0, 0); // allow shrinking afterwards

QT Layout - initial directions

I am new to QT. I'm trying to understand the layout mechanism by trying to implement this small window seen below. It has the following elements under the QWidget that's the main window:
One big QWidget that stretches on all the client area.
Two QWidget containers on the top of the window. Both should have the same height, but the right one stretches horizontally, as the window grows/shrinks.
one button container widget on the top right, with fixed height and width
Large QWidget container filling the rest of the client area, that should resize as the window resizes.
The parent window itself is resizeable.
I'm looking for hints as to what layout I should use. How do I achieve this programatically? define what stretches automatically, what stays with a fix size? and how the proportions are kept where they need to be kept.
I'd appreciate any pointer you may have.
The easiest, and IMHO best, way to accomplish this is via the QHBoxLayout and QVBoxLayouts. You can do this via the designer in QtCreator, but I find it doesn't work perfectly if you need to adapt things over time. If it's a static set of widgets, I do suggest designing it using the QtCreator designer as it'll greatly simplify your life.
If you're going to do it programatically, the main window should be set to use a QVBoxLayout and then two sub-QVBoxLayout's after that, where the bottom one is configured to take any space it can get. Then in the top QVBoxLayout, add a QHBoxLayout with your two upper components.
to set a widget to fixed size in code you call setFixedSize( int h, int w ) on the widget. To do it in Designer click on the widget and look in the property editor in the QWidget section. open the sizePolicy thingy and set horizontal and/or vertical to fixed. Then open Geometry and set the width and Height.
To make them stretch at different ratios in code you use a separate argument when using a box layout. eg layout->addWidget( button1, 1 ); layout->addWidget (button2, 2); this would cause button2 to expand at twice the rate of button1. To do this in designer, open the sizePolicy property of the widgets and set the HorizontalStrech and/or VerticalSretch. Note that the size policy needs to not be Fixed in this case for the direction you want to set the stretch on. Also it will never let a widget shrink below its minimum size (it would rather mess up the ratio than shrink something too small).

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