PDA

View Full Version : Window with changeable height but width set by the contained widget



stefanadelbert
9th February 2011, 05:17
BACKGROUND

I have a widget, MyWidget, deriving from QWidget. MyWidget contains a class, MyTableView, which derives from QTableView which is in a QVBoxLayout.

MyWidget has setWindowFlags(Qt::Tool) so it is displayed in a window even though it's a child of QMainWindow.

MyTableView has sizeHint overidden to pass back the size of the actual table view based on its headers:


return QSize(horizontalHeader()->sizeHint().width(), verticalHeader()->sizeHint().width());

This means that MyTableView is only as wide as its horizontal header and will change its width along with the horizontal header. The user is able to change the width of MyTableView by changing the width of the columns.

DESIRED BEHAVIOUR

I want the width of the window to expand and contract along with the table view. But I also want the user to be able to change the height of the window. So, the window's width is dictated by the width of the widget, but the window should control its own height or allow its height to be changed by the user.

PROBLEM

If I call MyWidget::layout()->setSizeConstraint(QLayout::SetFixedSize) the layout responds to sizeHint of the widget. This works perfectly for width - as MyTableWidget's width changes the window changes to fit. But this means that the height of the window is determined by the widget's sizeHint too. MyTableView can contain hundreds of rows, so this doesn't work. Is there a way to have SetFixedSize apply only to width for a layout?

I have tried every combination that I can think of (sizeConstraints, sizePolicy, etc.), but I just can't seem to get this working the way I would like it to work.

Does anyone have any ideas? If there was a way to resize the height of MyTableView that would solve the problem, but that would involve resizing the viewport and I don't know how to do that or if it's even possible.

wysota
9th February 2011, 23:56
Unfortunately size constraints work in both directions. You need to reimplement resizeEvent for the table widget and make it adjust its window() size. A bit dirty solution but it will work.

stefanadelbert
10th February 2011, 00:47
Wysota, thanks very much for your reply.

This is what I found on QWidget::window():


QWidget * QWidget::window () const
Returns the window for this widget, i.e. the next ancestor widget that has (or could have) a window-system frame.

If the widget is a window, the widget itself is returned.

Typical usage is changing the window title:


aWidget->window()->setWindowTitle("New Window Title");


So if I understand your suggestions correctly, I could handle a resizeEvent on MyWidget and directly resize its parent window's size. I could thereby limit the width of the parent window to whatever I want it to be (width of sizeHint of MyTableView), but allow the height to change freely. If that works, then it's a pretty nifty solution, albeit dirty.

I'll post back with the results.

:wq

stefanadelbert
3rd March 2011, 01:22
Seems I've found a fairly simple solution to this problem. If the width of a widget is based is based on the width of one of its children, then the child should notify when its width has changed and this way the parent can adjust its width accordingly.

To use my example above, I created a signal on MyTableView called geometriesChanged which is emitted when MyTableView changes width, e.g. column widths are changed. MyWidget handles SIGNAL(geometriesChanged()) by calling setFixedWidth(MyTableView->horizontalHeader()->width()).

The key is that MyWidget set its width based on the width of a child widget using setFixedWidth, but it never calls setFixedHeight, which means that the user can freely adjust the height of MyWidget by dragging the MyWidget's top and bottom window borders. But if the user wants to change the width of MyWidget he needs to change the width of MyTableView which can only be done by changing the column widths of MyTableView.

If anyone actually wants working code to demonstrate this, let me know. I've implemented this solution in the project I'm working on and that code is convoluted at best, so it would take a little work to put a working example of the principle together which is uncluttered by all the other stuff going on.