I am new to qt So I don't have much knowledge of sizepolicy and streches of widgets. I have a vertical box layout in which I have first added a Qlabel and then a QTreeWidget and then again a Qlabel. Now the problem is QTreeWidget is taking full space in vertical direction and then after leaving a very big space after QTreeWidget, although only rows exist currently in it, QLabel is added. I want that second Qlabel is added immediately after two rows visible and now when more rows are added then It shift downwards. Can someone suggest me how to do this?
Asked
Active
Viewed 3,643 times
1 Answers
1
I think this is what you meant: UI has in a layout: Label, QTreeWidget, Label, Spacer (Spacer is important becaus else Qt might just expand the labels to fill the window.) Important: In Designer TreeWidget hight to preffered, vertical scrollbar off.
UI Example:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>568</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="my_tree" name="treeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>my_tree</class>
<extends>QTreeView</extends>
<header>my_tree.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
A Overloaded QTreeView (in your case QTreeWidget) is used to get the wanted sizehints: EDIT -- This is a uggly header only definition i called my_tree.h --
#ifndef MY_TREE_H
#define MY_TREE_H
#include <QHeaderView>
#include <QTreeView>
class my_tree: public QTreeView
{
Q_OBJECT
public:
my_tree(QWidget* parent):QTreeView(parent)
{
// Important: if something is shown/hidden we need a new size
connect(this,SIGNAL(expanded( const QModelIndex & )),SLOT(onExpandCollapsed()));
connect(this,SIGNAL(collapsed( const QModelIndex & )),SLOT(onExpandCollapsed()));
};
// QWidget interface
public:
QSize sizeHint() const {return my_size(); };
QSize minimumSizeHint() const { return my_size(); };
private:
QSize my_size() const
{ //QSize tst(sizeHintForColumn(0) + 2 * frameWidth(), sizeHintForRow(0) + 2 * frameWidth());
int neededHight= 2 * frameWidth()+ this->header()->height();
QModelIndex root = this->rootIndex();
QAbstractItemModel* m = this->model();
//if(this->rootIsDecorated())
{
neededHight += recursiveHeightHint(root,m);
}
QSize temp = QTreeView::sizeHint();
temp.setHeight(neededHight);
return QSize(1,neededHight);
}
// we need the size of all visible items -> isExpanded
// the root item is usually shown as a non-Valid index -> !i.isValid()
int recursiveHeightHint(QModelIndex i,QAbstractItemModel* m) const
{
int temp=sizeHintForIndex(i).height();
if(this->isExpanded(i) || !i.isValid())
{
if(m->hasChildren(i))
{
int numRows = m->rowCount(i);
for(int count =0;count<numRows;count++)
temp+=recursiveHeightHint(m->index(count,0,i),m);
}
}
return temp;
}
private slots:
void onExpandCollapsed(){updateGeometry();}
};
#endif // MY_TREE_H
PS: in Designer first place the base Widget and then define it as placeholder for the self designed one.
I used this entry to get to this solution:
-
Thanks for the comment @edisn. I 'll check this and will let you know if this works for me. – user3336091 Feb 16 '15 at 06:47
-
can you please tell me why the width of qsize, when we are returning it in my_size(), is 1? – user3336091 Feb 16 '15 at 08:37
-
This works for me. Thanks for this. Just one problem here is that when I am deleting any item from qtreewidget then the label below qtreewidget does not move up It stays at the same place. Any idea why is this happening? – user3336091 Feb 16 '15 at 09:56
-
11) In my example i dont need the widht, therefore i just added a 1. alternative return the temp element. (I was between two solutions there.) 2) The sizehint is used by updateGeometry(), and i only call that one on colapse or expand, add some of the other signals for modell change, and it schlould work. e.g. 'connect(this,SIGNAL(insertRow(int)),SLOT(onExpandCollapsed()));' – edisn Feb 16 '15 at 18:08