Reputation: 73
I have a QTabWidget
, and I need to trigger an event when i press the area on the tab widget where you normally would see the tab name, accept its an empty space with no tab.
Clicking the red area should trigger an event:
Here is how the result should look like:
Upvotes: 3
Views: 308
Reputation: 3967
What you ask is usually done by a button next to the last tab, same as what modern browsers (chrome, edge, ...) do to ease the creation of new tabs.
We can copy that principle to do what you want, the only difference being that the button will extend far to the right of the widget. IMHO, that is much more convenient and easier to customize than installing an event filter.
In the code below, I added some bits for you to uncomment if you prefer having a smaller button.
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTabBar>
#include <QtWidgets/QTabWidget>
int main(int argc, char** argv)
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(true);
QTabWidget w;
w.addTab(new QWidget(), "Tab 1");
QPushButton* tabButton = new QPushButton(&w);
tabButton->setFlat(true);
tabButton->stackUnder(w.tabBar());
auto moveTabAddButton = [&w, tabButton]()
{
tabButton->move(w.tabBar()->width(), 0);
};
QObject::connect(tabButton, &QAbstractButton::clicked, &w, [&w, &moveTabAddButton]()
{
w.addTab(new QWidget(), QStringLiteral("Tab %1").arg(1 + w.count()));
moveTabAddButton();
}
);
QObject::connect(&w, &QTabWidget::tabCloseRequested, tabButton, moveTabAddButton);
//We make the button so wide it will always cover the space left free by tabs.
tabButton->setFixedSize(100000, w.tabBar()->tabRect(0).height());
//Uncomment the entire next block to turn the button into
//a + button next to the last tab (+ optionally remove the previous line).
//tabButton->setText("+");
//tabButton->setFixedSize(w.tabBar()->tabRect(0).height(),
// w.tabBar()->tabRect(0).height());
//Uncomment the next block of rows to make the button round.
//tabButton->setStyleSheet(QStringLiteral(
// "QPushButton{" \
// "border-radius: %1px;" \
// "}" \
// "QPushButton:hover{" \
// "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," \
// " stop: 0 #f6f7fa, stop: 1 #dadbde); " \
// "}" \
// "QPushButton:pressed{" \
// "background-color: qlineargradient(x1 : 0, y1 : 0, x2 : 0, y2 : 1," \
// " stop : 0 #dadbde, stop: 1 #f6f7fa);" \
// "}" \
//).arg(tabButton->height() / 2));
w.show();
moveTabAddButton();
return a.exec();
}
I let you customize the little bits such as the stylesheets, the margin between the last tab and the button, the icon (instead of text) on the button if you want...
Upvotes: 2
Reputation: 2363
You could install an event filter on your QTabWidget
, and use QMouseEvent
position to detect if it's on the empty space after the tab bar, and add tabs there.
There are many ways you can detect that, here's one of them:
#include <QObject>
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>
#include <QTabWidget>
#include <QTabBar>
class myEventFilter : public QObject
{
Q_OBJECT
public:
myEventFilter (QObject *parent = nullptr) {}
protected:
bool eventFilter(QObject * obj, QEvent * event) override
{
//check if event is a mouse button press
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
//obj is the object that has the event filter installed on
//here it is a QTabWidget, you can get it like this
QTabWidget *tabWidget = static_cast<QTabWidget *>(obj);
//here is where you can have multiple ways to check mouse event position
//you can change it however it suits you
//but be sure it works
if(mouseEvent->position().toPoint().x() > tabWidget->tabBar()->width() &&
mouseEvent->position().toPoint().y() < tabWidget->tabBar()->height())
{
//add tabs here
tabWidget->addTab(new QWidget(),"tab");
}
}
return QObject::eventFilter(obj, event);
}
};
Here's how it looks, I'm clicking on different areas to test that it only adds a tab when clicked on the space after the tab bar:
Notes:
QCursor::pos()
instead of QMouseEvent
, but you'll need to map positions.Upvotes: 2