Initial size for QMdiSubWindow - c++

Is there a way to define an initial size for a child window widget (inherited from QMdiSubWindow)? I don't want to necessary limit the minimum size or prevent it from being resized, but just to show the window at the first time with a given size.
I've tried to reimplement sizeHint and to define different size policies, but even with those changes the autoAjust call seem to make the window very small (size 200 x 200) when it is first displayed. The window contains a widget with this hierarchy: QVBoxLayout -> QScrollArea -> QLabel. The QLabel is used to show an image with the size 512 x 512.
EDIT: Correct the class to QMdiSubWindow.

you can use resize(int w, int h).
It will not set the maximum and minimum size.
It will just change the initial size of the child window.
Well actually, what it really does is: it changes the "current" size of the child window. But the first current size is the "initial" size. So basically its the same.

To my knowledge, there's no such thing in Qt as a QSubWindow.
However, a call to setGeometry on a QWidget will set its size.

After much searching for an answer, and experimenting, I found this to work for me.
child->parentWidget()->resize(900, 700);
child->parentWidget()->updateGeometry();
child->show();
// child->showMaximized();
You can use showMaximized() in place of show() and the (900, 700) will still be used if the window is later changed to normal.

Related

Qt QGraphicsView - layout not shrinking & sizeHint, minimumSizeHint, etc. not called

I have the following, quite simple setup:
In a QWidget that is displayed as a window (no parent), there is a single QVBoxLayout.
In that QVBoxLayout, there is a single custom QGraphicsView.
The size policy of that custom QGraphicsView is set to Preferred/Preferred and setHeightForWidth set to true (and overwritten in the custom class) - I want to preserve aspect ratio.
The whole constructor of the widget here:
graphicsView = new CustomGraphicsView();
QVBoxLayout *layout = new QVBoxLayout();
layout->setMargin(0);
QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
sp.setHeightForWidth(true);
graphicsView->setSizePolicy(sp);
layout->addWidget(graphicsView);
setLayout(layout);
The setup works, and the aspect ratio is maintained when dragging the width of the window bigger (the height grows with it).
But as soon as I drag the window width smaller, the aspect ratio of the graphics view is maintained, but the height of the window itself won't shrink. The result being a small graphics view with lots of space above and below it that shouldn't be there.
Investigating it further I was trying to find out where things break, so I overloaded all the sizeHint(), minimumSize(), minimumHeight(), etc. functions of my custom graphics view.
Just to discover that not a single one of them is ever being called while I am manually resizing the window. The only thing called as expected is heightForWidth - which returns my calculated value - but its return value is not applied when the window is shrinking.
So, not only do I not know why the layout won't shrink on its own despite having the Preferred vertical policy (which explicity says "The widget can be expanded, but there is no advantage to it being larger than sizeHint()").
I also don't know how the layout gets the size from the widget to begin with. I assumed sizeHint() since all of the documentation permanently refers to it, but that is obviously wrong in this case.
What I already tried is to set the vertical policy to every possible value. None of them would cause the window to grow and shrink as it is supposed to.
My current workaround:
I have added the resizeEvent(...) function to the widget and inside that, I manually resize() the whole widget if its height exceeds the value returned by the heightForWidth() function of the custom graphics widget.
Okay as far as workarounds go, but it leads to heavy flickering (as usual when resizing inside a resizeEvent).
Any ideas on either problem?

Qt: resize() inside custom widget's code doesn't seem to be working

I've created a custom widget, and in its "main" function (CustomWidget::CustomWidget) I've put following code:
int width = 30, height = 20; //example numbers
setMinimumWidth( ((width*8)*zoom) );
setMinimumHeight( ((height*8)*zoom) );
resize( minimumWidth(),minimumHeight() );
(Note: I've changed the Minimum size for it to be scrolled in ScrollArea.)
However, upon compiling the program the size is the one chosen with parent widget's layout.
Additionally, the custom widget's size DOES change if I put the code under a button in MainWindow's code.
PS: I use Qt4, not 5.
If you want your widget to be a specific size you should setFixedWidth() and setFixedHeight() instead. These methods set both the minimum and maximum height and width. When you only set the minimum size you are still saying to the parent layout they can be as big as they want.
Note that depending on your Operating System / Window manager the window may still be resized smaller or larger then your fixed size.
From my experience if you want a widget to be a fixed size and have the window calculated to the best possible value it is best to First set the fixed size, second add the widget to your layout and 3rd show the parent.

resize QMainWindow based on a child widget?

The child-parent hierarchy is the following: mainWindow -> centralWidget -> frame -> widget.
Widget is being resized during the application lifetime, however it is always set to a fixed size. I want the QMainWindow to resize based on that - to have a minimum size that is needed to display all the widgets.
To do that I currently have to do this.
widget->setFixedSize(x, y);
frame->setFixedSize(frame->sizeHint());
centralWidget->setFixedSize(centralWidget->sizeHint());
mainWindow->setFixedSize(mainWindow->sizeHint());
It doesn't work properly if I only resize the main window. All parents of widget need to be resized in order for this to work. Is there a more elegant way? Is it possible to make the main window call resize on all of it's children?
NOTE: All widgets except 'widget' have automatic layout management. So I find it strange that they don't resize themselves based on 'widget'.
It is the job of the layout to determine the size and position of the widgets. So if you explicitly resize a child widget which is inside a layout, you need to ensure that the new size is passed correctly through the layout system. This can be done by ensuring that the widget’s sizeHint() returns the new size. The value returned by the sizeHint() will be used when the layout calculates the new size. So after the sizeHint() has changed, simply call updateGeometry() [qt.nokia.com] that will notify the layout system that the widget has changed and may need to change geometry.
An alternative way to ensure that the parent widget is resized in response to its child being resized, is to call setFixedSize() on the child.
For more details check this...
http://qt-project.org/faq/answer/how_can_i_trigger_the_parent_widget_to_resize_when_its_child_widget_is_resi
You should let layout manage widgets size. As far as i am concerned there is 2 situations:
With layout when you are resizing a parent all children are resizing too regarding the size policy you provided to them. If you choose a fixed policy children will not be resized. So you have to resize them by hand... but it's quit weird.
When you are resizing a child like you are doing, parent is not automatically resized. You need to do it by hand. Fortunately there's a "magic function for that: AdjustSize. If you call it from QMainWindow all widget will be resized to their optimize size. It is possible (I can't test it here) that this does not work at runtime if size policy is set to fixed.
Hope that helps

Getting the size of a QGraphicsView

I want to know the size of a certain QGraphicsView. Its size isn't fixed because the widget is part of a grid layout. I tried using this->ui->myGraphicsView->width() and its height equivalent but these values aren't accurate.
How can I get the current size of a QGraphicsView?
Constantly received 100x30 as the size of my QGraphicsView as well. It turned out I was asking for the size of the QGraphicsView before it was shown.
After moving my initialization code to showEvent, I got the correct dimensions.
If you wanna know the actual size of QGraphicsView, QGraphicsView::size();
If you wanna konw only the content size of QGraphicsView, QGraphisView::viewport().size();
retrieve the width/height in MainWindow's constructor
That is the problem! The widget isn't painted already and you're asking for it's size. Use other events like event, showEvent, paintEvent to get the right size within the initialization process of a widget.
Answer:
After calling MainWindow::show(), then get the size.
Description:
I had the same problem as Pieter. In the widget constructor like MainWindow::MainWindow() you can't get the correct size of the widget like QGraphicsView in Grid Layout because in that constructor the widget's size and location are not determined. Therefore, in MainWindow::MainWindow() you have to call show() and then get the size of the view or other widget.
I have the same problem with you. QGraphicsView.size() is always return (100,30). I have solved this problem in my project.
Check below code is like this
...in a QTabWidget class...
def addANewTab(self):
view = QGraphicsView()
...set view param...
index = self.addTab(view, 'test')
view.size() # it will return (100,30)
self.setCurrentIndex(index)
view.size() # it will return correct size
so like Bigbell Mercy answered , you show make sure QGraphicsView is show!

How to set an initial size of a QScrollArea?

I know that this is a very specific C++ and Qt related question, but maybe someone can help me, anyway ...
See the code below: I want to display an image within a scroll area. The view port of the scroll area shall have a defined initial size. That means, if the image's size is bigger than the initial size of the view port, scroll bars will be visible, otherwise not.
// create label for displaying an image
QImage image( ":/test.png" );
QLabel *label = new QLabel( this );
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new QScrollArea( this );
area->setWidget( label );
// set the initial size of the view port
// NOTE: This is what I'd like to do, but this method does not exist :(
area->setViewPortSize( QSize( 300, 300 ) );
It shall be possible to resize the whole application so that the view port will get another size than the initial one.
Unfortunatelly I was not able to find out, how to set the size of the view port. Qt's layout mechanism seems to set a default size for the view port, but up to now I was not able to change it. Setting a new size with
area->setMinimumSize( QSize( 300, 300 ) );
will actually set the demanded size, but then the scroll area looses the ability to get resized to a size smaller than 300x300.
Any ideas?
I think that you are looking at the problem the wrong way. The QScrollArea is just a widget that you put in a frame or QMainWindow. The size of the widget is controlled by the layout of the widget that contains it.
Take a look at this example from Trolltech: Image Viewer Example
You can try:
class MyScrollArea : public QScrollArea
{
virtual QSize sizeHint() const { return QSize( 300, 300 ); }
};
// create label for displaying an image
QImage image( ":/test.png" );
Label *label = new QLabel;
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new MyScrollArea( this );
area->setWidget( label );
However layout and Qt is amazingly Voodoo. It is IMO its least functional part.
if that doesn't work, try calling QWidget::resize() on various widgets.
Is the scroll area the top level widget? If so, simply call
area->resize(300,300);
If it's inside a hierarchy you need to resize the toplevel appropriately (complex), or set the minimumSize of the area. You could also try to experiment with the LayoutPolicy - assuming the sizeHint is QSize(300,300) you can give it the appropriate size policy according to what's defined in https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
I don't think you can do exactly that very easily, which is (if I'm reading correctly), size the widget so that the internal area is 300x300. You might be able to fudge it, however, since a scroll area is a type of frame, which inherits from QWidget. This means you could just call area->resize( 300 + fudge, 300 + fudge ), where your fudge values account for the extra bit taken up by the frame's drawing.
I'm not sure this would work in a dynamically resizable dialog, however. I haven't ever done anything quite like this.
If you're trying to display an image inside a scroll area, your best bet isn't going with a label.
You should try using a QGraphicsView/QGraphicsScene/QGraphicPixmapItem (instead of the Scroll Area and label). The performance is far better when displaying images. The scroll area and label will re-draw the image very poorly as you move around using the scroll bars.
For example, you have a ".ui" file with a QGraphicsView on the gui called "qgvImageView" and a QImage called "image"...
QGraphicsScene *scene = new QGraphicsScene(qgvImageView);
QPixmap pixTmp(QPixmap::fromImage(image));
QGraphicsPixmapItem * ppixItem = scene->addPixmap( pixTmp );
ppixItem->setPos(0,0);
Check out the QT Documentation. BTW: This was introduced in Qt 4.2
I'm not sure if this will specifically fix the problem, but there is a chance that the QGraphicsView will react better to what you're trying to do.
How about using
area->setGeometry(int x, int y, int w, int h);