I'm using Qt 5.15.2 on Windows. I have a QTableWidget
which has a bunch of QComboBox
es as cell widgets. The application uses the following stylesheet:
QComboBox:hover{background: yellow;}
QTableView::item:hover{color: red;}
Now when showing the table and hovering over a QComboBox
on the last visible row, the table starts auto-scrolling down, like so:
This doesn't happen if I hover over a normal QTableWidgetItem
on the last visible row as shown on the image.
If I remove either of the hover
keyword from the stylesheet, then things work fine but I lose my style. My guess is that there is a conflict between QTableView::item
and QComboBox
when it's used as a cell widget so I've tried being more explicit about which QComboBox
es the stylesheet should apply to by using
QTableView QComboBox:hover{background: yellow;}
QTableView::item:hover{color: red;}
but that didn't help either. Any suggestions on how to solve this please?
Here is the code I've used for this example:
#include <QTableWidget>
#include <QBoxLayout>
#include <QComboBox>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qApp->setStyleSheet(
"QComboBox{background: yellow;}"
"QTableView::item:hover{color: red;}"
);
auto rows = 100;
auto cols = 5;
auto table = new QTableWidget(rows, cols);
for(auto i = 0; i != rows; ++i)
{
for(auto j = 0; j != cols; ++j)
{
if(j == 0)
{
auto item = new QTableWidgetItem("hello");
table->setItem(i, j, item);
}
else
{
auto cb = new QComboBox();
cb->addItems(QStringList() << "Item1" << "Item2");
table->setCellWidget(i, j, cb);
}
}
}
table->setMinimumSize(800,600);
table->show();
return a.exec();
}
UPDATE
As suggested by this answer, using setAutoScroll(false)
works around the issue of the autoscrolling.
Unfortunately, the table loses the ability to autoscroll when the current item changes with the directional arrows as shown below.
I've also just confirmed that the whole issue described in my post is not reproducible with Qt versions prior to Qt 5.15, so I'm guessing this is a Qt regression bug.
Your QTableWidget
seems to be auto-scrolling when you hover a partially visible item, my guess is that it treats it as a selected cell when hovered, which causes the auto-scroll.
To fix your issue, you can simply do this:
table->setAutoScroll(false);
I applied it to your MRE and it worked.
I came up with the conclusion of your table auto-scrolling by using an eventFilter
, which helped me notice QEvent::Move
of the QComboBox
es, and if they are moving without me moving them, that means it's auto
, so I googled this:
qtablewidget disable ensure visible
Which then led me to this answer.
To get around the auto scroll
disabled for key press
, you can use an event filter to basically switch in on and off, here's how:
main.cpp
#include <QApplication>
#include <QTableWidget>
#include <QComboBox>
#include <QObject>
#include <QEvent>
#include "myEventFilter.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qApp->setStyleSheet(
"QComboBox{background: yellow;}"
"QTableView::item:hover{color: red;}"
);
QString s = "della3";
fprintf(stderr,"%s", s.toLatin1().data());
auto rows = 100;
auto cols = 5;
auto table = new QTableWidget(rows, cols);
for(auto i = 0; i != rows; ++i)
{
for(auto j = 0; j != cols; ++j)
{
if(j == 0)
{
auto item = new QTableWidgetItem("hello");
table->setItem(i, j, item);
}
else
{
auto cb = new QComboBox();
cb->addItems(QStringList() << "Item1" << "Item2");
table->setCellWidget(i, j, cb);
}
}
}
table->setMinimumSize(800,600);
table->setAutoScroll(false);
myEventFilter *filter = new myEventFilter();
table->installEventFilter(filter);
//give the address of table to the QTableWidget pointer of the eventFilter
filter->t=table;
table->show();
return a.exec();
}
myEventFilter.h
#ifndef MYEVENTFILTER_H
#define MYEVENTFILTER_H
#include <QObject>
#include <QEvent>
#include <QTableWidget>
class myEventFilter : public QObject
{
Q_OBJECT
public:
myEventFilter (QObject *parent = nullptr) {};
//I used the below pointer to point at table
//since it won't be able to access otherwise as far as I know
QTableWidget *t;
protected:
bool eventFilter(QObject *obj, QEvent *event) override
{
if(event->type() == QEvent::KeyPress)
{
t->setAutoScroll(true);
}
if(event->type() == QEvent::KeyRelease)
{
t->setAutoScroll(false);
}
return QObject::eventFilter(obj,event);
};
};
#endif // MYEVENTFILTER_H