Qt TabWidget Each tab Title Background Color - c++

This is the original Tabwidget without setting title background color
My customer ask me to do something like this;
Set different background colour for title
All - Yellow
purchase - light blue
POS Sales - light green
Cash Sales - Pink
invoice - light purple
I have try the SetStyleSheet like:
QTabBar {
background-color : Yellow;
}
But all tab Color changed
Somebody know how to setting each QTabBar background color?

These properties can not be set through QSS. To change the style to each tab we must create a custom QTabBar and override its paintEvent method, to be able to change the style of each tab we use the QStyleOptionTab class, but to change the QTabWidget tabbar we need to use the setTabBar method but this is private so you need to create a custom QTabWidget as shown below:
tabwidget.h
#ifndef TABWIDGET_H
#define TABWIDGET_H
#include <QStyleOptionTab>
#include <QStylePainter>
#include <QTabWidget>
class TabBar: public QTabBar
{
public:
TabBar(const QHash<QString, QColor> &colors, QWidget *parent=0):QTabBar(parent){
mColors = colors;
}
protected:
void paintEvent(QPaintEvent */*event*/){
QStylePainter painter(this);
QStyleOptionTab opt;
for(int i = 0;i < count();i++)
{
initStyleOption(&opt,i);
if(mColors.contains(opt.text)){
opt.palette.setColor(QPalette::Button, mColors[opt.text]);
}
painter.drawControl(QStyle::CE_TabBarTabShape, opt);
painter.drawControl(QStyle::CE_TabBarTabLabel,opt);
}
}
private:
QHash<QString, QColor> mColors;
};
class TabWidget : public QTabWidget
{
public:
TabWidget(QWidget *parent=0):QTabWidget(parent){
// text - color
QHash <QString, QColor> dict;
dict["All"] = QColor("yellow");
dict["purchase"] = QColor("#87ceeb");
dict["POS Sales"] = QColor("#90EE90");
dict["Cash Sales"] = QColor("pink");
dict["invoice"] = QColor("#800080");
setTabBar(new TabBar(dict));
}
};
#endif // TABWIDGET_H
And to use it in our QTabWidget in Qt Designer should be promoted for this we right click on the tabwidget and select the menu Promoted Widgets, in my case the previous code is created in the file tabwidget.h so this will be the header file and in the case of Promoted Class Name we use TabWidget, after that we press the buttons Add and Promote obtaining what is shown in the following image:
The final result is shown in the following image:
The complete example can be found in the following link
Python:
from PyQt5 import QtGui, QtWidgets
class TabBar(QtWidgets.QTabBar):
def __init__(self, colors, parent=None):
super(TabBar, self).__init__(parent)
self.mColors = colors
def paintEvent(self, event):
painter = QtWidgets.QStylePainter(self)
opt = QtWidgets.QStyleOptionTab()
for i in range(self.count()):
self.initStyleOption(opt, i)
if opt.text in self.mColors:
opt.palette.setColor(
QtGui.QPalette.Button, self.mColors[opt.text]
)
painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
painter.drawControl(QtWidgets.QStyle.CE_TabBarTabLabel, opt)
class TabWidget(QtWidgets.QTabWidget):
def __init__(self, parent=None):
super(TabWidget, self).__init__(parent)
d = {
"All": QtGui.QColor("yellow"),
"purchase": QtGui.QColor("#87ceeb"),
"POS Sales": QtGui.QColor("#90EE90"),
"Cash Sales": QtGui.QColor("pink"),
"invoice": QtGui.QColor("#800080"),
}
self.setTabBar(TabBar(d))
self.addTab(QtWidgets.QLabel(), "All")
self.addTab(QtWidgets.QLabel(), "purchase")
self.addTab(QtWidgets.QLabel(), "POS Sales")
self.addTab(QtWidgets.QLabel(), "Cash Sales")
self.addTab(QtWidgets.QLabel(), "invoice")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle("fusion")
w = TabWidget()
w.show()
sys.exit(app.exec_())

Related

How to detect when a QWebEngineView widget is opened/closed?

I'm adding the discord widget from widgetbot to a grid layout in a way it can expand above other widgets, the problem is, even when the widget is 'closed' the QWebEngineView widget occupies the entire area blocking things below it to be clicked:
I thought of setting a maximum size to the widget when it is opened and another when it's closed so it doesn't overlay other widgets when it's not 'opened'.
I tried installing an event filter but it didn't throw any event when the widget is opened/closed, would like to ask what other way I could detect it?
#include "discordwidget.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
auto wdgt = new DiscordWidget(this);
}
//discordwidget.h
#include <QtWebEngineWidgets>
class DiscordWidget : public QWebEngineView
{
Q_OBJECT
public:
DiscordWidget(QWidget* parent = 0) : QWebEngineView(parent)
{
this->page()->setBackgroundColor(Qt::transparent);
// Tutorial: https://docs.widgetbot.io/embed/crate/tutorial/#getting-started
this->page()->setHtml(R"(
<script src='https://cdn.jsdelivr.net/npm/#widgetbot/crate#3' async defer>
new Crate({
server: '', // Replace with your discord server
channel: '' // ... channel
})
</script>
)");
this->installEventFilter(this);
this->page()->installEventFilter(this);
}
bool eventFilter(QObject *obj, QEvent *e)
{
qDebug() << e->type();
if( e->type() == QEvent::ChildAdded )
{
QChildEvent *ce = static_cast<QChildEvent*>(e);
ce->child()->installEventFilter(this);
}
return false;
}
};

Why does my window not show?

I need to write a GrabWindow, so I derived my class GrabWindow from QQuickWindow:
#include <QtQuickWidgets/QtQuickWidgets>
#include <QString>
class GrabWindow : public QQuickWindow {
Q_OBJECT
public:
explicit GrabWindow(QQuickWindow *parent = nullptr);
public slots:
void capture(QString const &path);
};
// .CPP
#include "grab_window.h"
#include <QImage>
GrabWindow::GrabWindow(QQuickWindow *parent) : QQuickWindow(parent) {
}
void GrabWindow::capture(const QString &path) {
QImage img = this->grabWindow();
img.save(path);
}
After I registered it in QML: qmlRegisterType<GrabWindow>("myapp", 1, 0, "GrabWindow");
And after I defined my window in QML:
import QtQuick 2.4
import QtQuick.Controls 2.2
import QtQuick.Window 2.3
import myapp 1.0
GrabWindow {
id : translationWindow
width : 1024
height : 768
color: "transparent"
visibility: "FullScreen"
visible: true;
signal capture(string path)
MouseArea {
anchors.fill: parent
onClicked: translationWindow.capture("/home/user/saveTest.jpg")
}
}
But it doesn't show on start (I know it's transparent, I mean the grab window doesn't start to show). If instead of GrabWindow I use Window or ApplicationWindow then all works perfectly I am seeing a transparent full-screen window.
What's wrong?
Your GrabWindow is not shown because when you are setting the visible property it's not same as when you use Window's visible property.
Yours is just the visible property of QWindow.
Window does not directly instantiate QQuickWindow, it instantiates a private Qt class QQuickWindowImpl which overrides the visible property with a custom one.
It seems to delay the actual call of the QWindow::setVisible at a later time.
As such, I don't think QQuickWindow is meant to be inherited from. You could try doing visible = true in your Component.onCompleted but I'm not sure it will resolve your problem.
What I would advise you instead is not subclassing QQuickWindow but just creating a new type and pass it the existing Window.
Possible API could be :
Window {
id: myWindow
//...
MouseArea {
anchors.fill: parent
onClicked: WindowGrabber.grab(myWindow, path) //singleton type
}
}
or
Window {
id: myWindow
//...
WindowGrabber { // regular type
id: windowGrabber
window: myWindow
}
MouseArea {
anchors.fill: parent
onClicked: windowGrabber.grab(path) // you could even add a path property in WindowGrabber and not have it as a function parameter if that makes sense for your use case
}
}

How can I add custom widget as Popup menu for ToolButton?

I have created a custom Widget,it has to be displayed as a popup menu when click on the ToolButton. How I can do this in Qt 5.1.1?
You should create your custom QWidgetAction to add to the popup menu.
This is a sample QWidgetAction :
#include <QWidgetAction>
class myCustomWidgetAction: public QWidgetAction
{
Q_OBJECT
public:
explicit myCustomWidgetAction(QWidget * parent);
protected:
QWidget * createWidget(QWidget *parent);
};
myCustomWidgetAction::myCustomWidgetAction(QWidget * parent):QWidgetAction(parent) {
}
QWidget * myCustomWidgetAction::createWidget(QWidget *parent){
myCustomWidget * widget=new myCustomWidget(parent);
return widget;
}
You can then add your widget to the tool button to be displayed in a popup menu:
myCustomWidgetAction * widgetAction = new myCustomWidgetAction(this);
ui->toolButton->addAction(widgetAction);
myCustomWidget can be any widget. You can add multiple instances of myCustomWidgetAction to the toolButton.

QTooltip for QActions in QMenu

I want to be able to show ToolTips for QMenu items (QActions). The best I have achieved is to connect the hovered signal of the QAction to a QTooltip show:
connect(action, &QAction::hovered, [=]{
QToolTip::showText(QCursor::pos(), text, this);
});
The problem is that sometimes the program will position the tooltip below the menu, specially when changing menus.
Is there any way to force the tooltip to show on top?
Since Qt 5.1, you can use QMenu's property toolTipsVisible, which is by default set to false.
See the related Qt suggestion.
You can subclass QMenu and reimplementing QMenu::event() to intercept the QEvent::ToolTip event and call QToolTip::showText to set the tooltip for the active action :
#include <QtGui>
class Menu : public QMenu
{
Q_OBJECT
public:
Menu(){}
bool event (QEvent * e)
{
const QHelpEvent *helpEvent = static_cast <QHelpEvent *>(e);
if (helpEvent->type() == QEvent::ToolTip && activeAction() != 0)
{
QToolTip::showText(helpEvent->globalPos(), activeAction()->toolTip());
} else
{
QToolTip::hideText();
}
return QMenu::event(e);
}
};
Now you can use your custom menu like :
Menu *menu = new Menu();
menu->setTitle("Test menu");
menuBar()->addMenu(menu);
QAction *action1 = menu->addAction("First");
action1->setToolTip("First action");
QAction *action2 = menu->addAction("Second");
action2->setToolTip("Second action");

How to Add a Button or other widget in QTreeWidget Header?

Can anyone give me a hint on how to place a button in the header of QTreeWidget
A minimal example is more than welcome?
For the person in the comments (and basically anyone else stopping by who might be helped by this), here is the translated python version of the code below:
from PySide2 import QtWidgets, QtCore
import sys
class Header(QtWidgets.QHeaderView):
def __init__(self, orientation, parent=None):
super(Header, self).__init__(orientation, parent)
self.button = QtWidgets.QPushButton('Button text', self)
class TreeWidget(QtWidgets.QTreeWidget):
def __init__(self, parent=None):
super(TreeWidget, self).__init__(parent)
item0 = QtWidgets.QTreeWidgetItem(["Item 0"])
item1 = QtWidgets.QTreeWidgetItem(["Item 1"])
self.addTopLevelItem(item0)
self.addTopLevelItem(item1)
self.createHeader()
def createHeader(self):
header = Header(QtCore.Qt.Horizontal, self)
self.setHeader(header)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = TreeWidget()
w.show()
sys.exit(app.exec_())
#QTreeWidget header is an "stand alone" widget - QHeaderView, so you can set the custom implementation of it.
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QHeaderView>
#include <QPushButton>
class Header
: public QHeaderView
{
public:
Header(QWidget* parent)
: QHeaderView(Qt::Horizontal, parent)
, m_button(new QPushButton("Button", this))
{
}
private:
QPushButton* m_button;
};
class TreeWidget
: public QTreeWidget
{
Q_OBJECT
public:
TreeWidget()
: QTreeWidget(0)
{
QTreeWidgetItem* item0 = new QTreeWidgetItem(QStringList("Item 0"));
QTreeWidgetItem* item1 = new QTreeWidgetItem(QStringList("Item 1"));
addTopLevelItem(item0);
addTopLevelItem(item1);
createHeader();
}
private:
void createHeader()
{
m_header = new Header(this);
setHeader(m_header);
}
private:
Header* m_header;
};
int main(int c, char** v)
{
QApplication a(c, v);
TreeWidget* tw = new TreeWidget();
tw->show();
return a.exec();
}
//QTreeWidget header is an "stand alone" widget - QHeaderView, so you can set the custom implementation of it.