How to change the size of a QComboBox's QScrollBar? - c++

I'm using a QComboBox with some items to the point that, when the widget that shows all available items in the QComboBox appears, only some of the items are visible with the other accesible through a QScrollBar.
The problem is that the QScrollBar is to thin and I want to make it larger. I did some research on the web and I did found some ways to change the QScrollBar's width (see references below), but the problem is that I simply can't find the method to access the QComboBox's QScrollBar.
So, given this problem, how can I do this change? (I guess you may either present me with a way that don't require me to access the QScrollBar or show how may I access it).
References:
vertical scrollbar width - Direct access and style
How to get scroll bar real width in Qt? - Again by pixlMetric (only access)
How to increase QTableWidget Vertical Scrollbar width? - Using stylesheet (a preferable method if there is a way to make it apply to all QScrollBars available in the project)
Other options are discussed here

Get the combobox's QAbstractItemView via view()
That class inherits from QAbstractScrollArea, thus inherits the verticalScrollBar method
e.g.
QAbstractItemView *qv = combobox.view();
QScrollBar *scrollbar = qv->verticalScrollBar();
// Adjust size via setStyleSheet or hint/width

The scroll bar isn't a member of the QComboBox class, it's a member of the underlying QAbstractItemView. Try something like the following (pseudo-code):
QListView* abby = new QListView();
QWidgetList list = abby->scrollBarWidgets(Qt::AlignRight);
for (auto itr = list.begin(); itr != list.end(); itr++)
{
(*itr)->setMinimumWidth(100);
}
QComboBox combo;
combo.setView(abby);
The scrollbarwidgets returns a widget list of the scroll bars for that alignment. You can then set the properties on the scroll bar pointers.

Related

QWidget::layout() can't return QGridLayout?

I have a QWidget that contains a QGridLayout, which in turn contains a handful of QPushButtons. These are all generated programmatically. Later in the code (separate from where the layout is defined), I need to be able to add more pushbuttons to specific row/column positions in the layout.
I tried using: widget->layout()->addWidget(button, row, col) to reference the layout and add the buttons. However, widget->layout() only returns a generic QLayout item, which does not allow me to specify row and column values. Is there any way to reference a QGridLayout from a specific widget, without having to know the layout by name? I'm using Qt 4.8 if it makes a difference.
You can always cast it to QGridLayout* by dynamic_cast:
auto gridLayout = dynamic_cast<QGridLayout*>(widget->layout());
If you're sure widget->layout() points to your QGridLayout you don't have to check and can use static_cast. Otherwise, check gridLayout against nullptr.

How to find the height of a QDockWidget title bar?

I'm trying to find the height of a QDockWidget title bar in order to do some intelligent sizing of a custom layout, but the title bar is not a separate widget, it's built into the private layout of the dock widget, and there is no member to access it. Is there some other way to find its height?
Yes, you can find the title bar's height using the pixelMetric member function of the dock's QStyle element. You'll probably also want to query the margin as well since it adds space around the title bar and the layout will need to be aware of it. Example:
QDockWidget * myDock = new QDockWidget;
int titleBarHeight = myDock->style()->pixelMetric(QStyle::PM_TitleBarHeight);
int titleBarMargin = myDock->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin);
You can always run QObject::findChild wih a suitable type or object name to find otherwise inaccessible children.

Columns auto-resize to size of QTableView

I am new to Qt and I have just managed to make a QTableView work with my model. It has fixed 3 columns. When I open a window, it look ok but when i resize the window, the QTableView itself gets resized but columns' width remains the same. Is there any build-in way to make it work? I want columns to resize to fit the edges of QTableView every the the window gets resized.
This code equally stretches each column so that they fit the table's width.
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
Docs:
QHeaderView::setSectionResizeMode
See resize modes here.
There is a header flag to ensure that the QTableView's last column fills up its parent if resized. You can set it like so:
table_view->horizontalHeader()->setStretchLastSection(true);
However, that does not resize the other columns proportionately. If you want to do that as well, you could handle it inside the resizeEvent of your parent thusly:
void QParent::resizeEvent(QResizeEvent *event) {
table_view->setColumnWidth(0, this->width()/3);
table_view->setColumnWidth(1, this->width()/3);
table_view->setColumnWidth(2, this->width()/3);
QMainWindow::resizeEvent(event);
}
QParent class is subclass of QMainWindow.
Widgets QTableView, QTreeView and their derived classes (such as QTableWidget) have this two usefull methods:
QHeaderView* horizontalHeader() const;
QHeaderView* verticalHeader() const;
If you open documentation for a class QHeaderView, you will find methods that set up appearance and behavior of row or column header for item views. You can resolve your problem by one of these methods:
void QHeaderView::stretchLastSection( bool stretch )
As Davy Jones mentioned.
Example:
QTableView *table = new QTableView();
table->horizontalHeader()->setStretchLastSection(true);
void QHeaderView::setResizeMode( ResizeMode mode )
As mode you can set QHeaderView::Stretch or QHeaderView::ResizeToContents.
Unfortunately this method have a drawback - after it's apply you will not be able to change size of columns (or rows) manually (in GUI) or programmatically.
Example:
QTableView *table = new QTableView();
table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
In PyQt5 you can achieve this in your table_widget by doing:
header = table_widget.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)

resize problem in scroll area

Hello everyone, here is my code:
myplot *p = new myplot(gao.structpayloadgraph,
gao1.structpayloadgraph,
gao.structcol-2, "payload");
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->scrollArea->setWidgetResizable(false);
p->resize(ui->scrollArea->size().width(), ui->scrollArea->size().height());
ui->scrollArea->setWidget(p);
I want p to take up the full available space of the scrollbar area and fit itself. However, the appearance looks 'squeezed' even though I called the resize function. What should I do to achieve the desired effect?
You have to treat the scroll area content widget as a normal QWidget. If you want automatic resize and you must use layouts in Qt. Try the following :
QVBoxLayout layout = new QVBoxLayout( ui->scrollAreaContent);
layout->setMargin(0);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
ui->scrollAreaContent->setLayout( layout);
layout->addWidget(p);
NOTE: ui->scrollAreaContent is a guess, but I think you are using ui files and default content widget is named like that ...
Go to the top right of the QT creator designer screen (Object, Class), right click on the QScrollArea row and select the "Lay Out" menu item, choose a layout (eg vertical or horizontal layout), make sure that your QWidget has a minimum or above size policy. Your scroll widget should now resize with the layout.

QListWidget that resizes instead of scrolls

How do you change the behavior of a QListWidget so that it resizes its height instead of choosing a (seemingly arbitrary) height and adding scrollbars? See screenshot:
The QListView's should fill up as much space horizontally as they can (creating as many "columns," if you will.) Then they wrap and make as many rows as necessary to fit all the items. These calculations should be adjusted as the window is resized. This is all working fine.
However, what I want to happen is that instead of the height staying the same, the QListView should grow or shrink vertically and never need any scrollbars. The scrolling, if necessary, will be handled on the parent QWidget that hosts all of the labels and lists. It seems like once the height of the QListWidget is established (not sure where its default is coming from), it never changes. It is too big in some cases (see second "Test" list above) and too small in others (see first "blank maps" list above.)
The layout above is nothing surprising: two QLabel's and two QListWidget's in a QVBoxLayout. Here are the properties I have set on the QListWidget's:
setMovement(QListView::Static);
setResizeMode(QListView::Adjust);
setViewMode(QListView::IconMode);
setIconSize(QSize(128, 128));
(I already tried setting the horizontal and vertical scrollbar policies, but that just turns the scrollbars off, clipping the content. Not what I want.)
Maybe you could this without using QListWidget. The Qt's examples contain a new layout class, QFlowLayout, which could be useful. With the following kind of widget hierarchy you could get multiple groups with labels and they all would be inside one QScrollArea.
QScrollBox
QVBoxLayout
QLabel "Blank maps"
QWidget
QFlowLayout
your own widgets showing map images and labels
QLabel "Text"
QWidget
QFlowLayout
your own widgets
The problem is that this kind of solution would create much more widgets than QListWidget based solution. So if you have hundreds of items in your list, this might not be the best solution.
There is a protected member function called contentsSize() in QListView. It is used to calculate the required minimum(), maximum(), and pageStep() for the scrollbars (as mentioned here).
Can you subclass the QListView class and make use of that information? I suggest you recalculate the size of your widget in the same function where you add contents to it. While somewhat lacking elegance, this appears to be a pretty reliable solution.