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.
Related
I've got a struct with two fields, for example:
struct testStruct
{
Q_GADGET
Q_PROPERTY(QString text MEMBER m_text);
Q_PROPERTY(QString value MEMBER m_value);
public:
QString m_text;
QString m_value;
};
There is a QList<testStruct> m_testStructs member of my "AppEngine" class exposed to QML via
Q_PROPERTY(QList<testStruct> testStructs READ testStructs NOTIFY testStructsChanged).
It is filled like that:
testStruct newStruct1, newStruct2;
newStruct1.m_text = "text1";
newStruct1.m_value = "value1";
newStruct2.m_text = "text2";
newStruct2.m_value = "value2";
m_testStructs << newStruct1 << newStruct2;
So I want to see "text" members in ComboBox list and use "value" members in further operations.
In fact QML ComboBox popup shows me the list of objects names when I set ComboBox's "textRole" property to "text" and "valueRole" to "value", but it does nothing for "currentText" or "currentValue" properties when I click the item, only "currentIndex" changes. Also "displayText" remains blank.
This is what I get in console when clicking those items:
qml: currentIndex: 0; currentText: ; currentValue: undefined
qml: currentIndex: 1; currentText: ; currentValue: undefined
So I see that ComboBox gets members of struct, but doesn't want to work with them. What should I do to make "currentText" and "currentValue" members of ComboBox work as they should?
Here are all the needed files:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "appengine.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/qml_testComboBoxStruct/main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
//exposing AppEngine class to QML
AppEngine appEngineObj;
QQmlContext *context = engine.rootContext();
context->setContextProperty("AppEngine", &appEngineObj);
engine.load(url);
return app.exec();
}
my custom class header AppEngine.h
#ifndef APPENGINE_H
#define APPENGINE_H
#include <QObject>
#include <QDebug>
struct testStruct
{
Q_GADGET
Q_PROPERTY(QString text MEMBER m_text);
Q_PROPERTY(QString value MEMBER m_value);
public:
QString m_text;
QString m_value;
};
Q_DECLARE_METATYPE(testStruct)
class AppEngine : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<testStruct> testStructs READ testStructs NOTIFY testStructsChanged);
public:
explicit AppEngine(QObject *parent = nullptr);
QList<testStruct> testStructs();
private:
QList<testStruct> m_testStructs;
signals:
void testStructsChanged();
};
#endif // APPENGINE_H
my custom class cpp file AppEngine.cpp
#include "appengine.h"
AppEngine::AppEngine(QObject *parent)
: QObject{parent}
{
testStruct newStruct1, newStruct2;
newStruct1.m_text = "text1";
newStruct1.m_value = "value1";
newStruct2.m_text = "text2";
newStruct2.m_value = "value2";
m_testStructs << newStruct1 << newStruct2;
qDebug() << "m_testStructs.length():" << m_testStructs.length();
}
QList<testStruct> AppEngine::testStructs()
{
qDebug() << "testStructs()";
return m_testStructs;
}
main.qml
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("C++ struct to QML ComboBox")
ComboBox
{
anchors.centerIn: parent
width: 180
height: 30
id: comboBoxID
textRole: "text"
valueRole: "value"
model: AppEngine.testStructs
onActivated:
{
console.log('currentIndex:', currentIndex, '; currentText:', currentText, ';currentValue:', currentValue);
}
}
}
As I checked in the main.qml model property cant find and understand as you show it is undefined.
qml: currentIndex: 0; currentText: ; currentValue: undefined
qml: currentIndex: 1; currentText: ; currentValue: undefined
from ListView::model property
The model provides the set of data that is used to create the items in
the view. Models can be created directly in QML using ListModel,
ObjectModel, or provided by C++ model classes. If a C++ model class is
used, it must be a subclass of QAbstractItemModel or a simple list.
For example, you can have this :
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("C++ struct to QML ComboBox")
ComboBox
{
id: comboBoxID
anchors.centerIn: parent
width: 180
height: 30
textRole: "text"
valueRole: "value"
model: ListModel {
id : model
ListElement { text: "text1" ; value : "value1" }
ListElement { text: "text2" ; value : "value2" }
ListElement { text: "text3" ; value : "value3" }
ListElement { text: "text4" ; value : "value4" }
}
onActivated:
{
console.log('currentIndex:', currentIndex, '; currentText:', currentText, '; currentValue:', currentValue);
}
}
}
Because you use QML ListModel if you want to define your model from C++ it must be a subclass of QAbstractItemModel or a simple list.
updated :
you need to use QStandardItemModel which inherits from QAbstractItemModel you cant inherit from the abstract interface because of that I use QStandardItemModel
in appengine.h:
#ifndef APPENGINE_H
#define APPENGINE_H
#include <QObject>
#include <QDebug>
#include <QStandardItemModel>
struct testStruct: public QStandardItemModel
{
Q_OBJECT
Q_PROPERTY(QString text MEMBER m_text);
Q_PROPERTY(QString value MEMBER m_value);
public:
QString m_text;
QString m_value;
};
Q_DECLARE_METATYPE(testStruct)
class AppEngine : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<testStruct *> testStructs READ testStructs NOTIFY testStructsChanged);
public:
explicit AppEngine(QObject *parent = nullptr);
QList<testStruct *> testStructs();
private:
QList<testStruct *> m_testStructs;
signals:
void testStructsChanged();
};
#endif // APPENGINE_H
In appengine.cpp
#include "appengine.h"
AppEngine::AppEngine(QObject *parent)
: QObject{parent}
{
testStruct *newStruct1 = new testStruct;
testStruct *newStruct2 = new testStruct;
newStruct1->m_text = "text1";
newStruct1->m_value = "value1";
newStruct2->m_text = "text2";
newStruct2->m_value = "value2";
m_testStructs << newStruct1 << newStruct2;
qDebug() << "m_testStructs.length():" << m_testStructs.length();
}
QList<testStruct *> AppEngine::testStructs()
{
qDebug() << "testStructs()";
return m_testStructs;
}
I have created a minimal working example. I hope it will be understandable. My problem is that I cannot create a model for my top level item in order to access items further. This is how the classes objects architecture looks like:
CTop
x times CMiddle
y times CBottom
This is a tree architecture. Here is the code:
CBottom.h:
#ifndef CBOTTOM_H
#define CBOTTOM_H
#include <QObject>
#include <QtQml>
class CBottom : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
CBottom(QObject *parent = nullptr) : QObject(parent)
{
}
CBottom(const QString& name, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CBottom>("Bottom", 1, 0, "Bottom");
m_name = name;
}
QString name()
{
return m_name;
}
void setName(const QString& name)
{
if (name != m_name)
{
m_name = name;
emit nameChanged();
}
}
signals:
void nameChanged();
private:
QString m_name;
};
#endif // CBOTTOM_H
CMiddle.h:
#ifndef CMIDDLE_H
#define CMIDDLE_H
#include <QObject>
#include <QtQml>
#include <QVector>
#include "cbottom.h"
class CMiddle : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
CMiddle(QObject *parent = nullptr) : QObject(parent)
{
}
CMiddle(const QString& name, const QStringList& bottoms, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CMiddle>("Middle", 1, 0, "Middle");
m_name = name;
foreach (auto bottom, bottoms)
{
m_bottoms.append(new CBottom(bottom));
}
}
QString name()
{
return m_name;
}
void setName(const QString& name)
{
if (name != m_name)
{
m_name = name;
emit nameChanged();
}
}
signals:
void nameChanged();
private:
QString m_name;
QVector<CBottom*> m_bottoms;
};
#endif // CMIDDLE_H
CTop.h:
#ifndef CTOP_H
#define CTOP_H
#include <QObject>
#include <QtQml>
#include "cmiddle.h"
class CTop : public QObject
{
Q_OBJECT
public:
CTop(QObject *parent = nullptr) : QObject(parent)
{
}
CTop(const QStringList& middles, QObject *parent = nullptr) : QObject(parent)
{
qmlRegisterType<CTop>("Top", 1, 0, "Top");
int i = 0;
foreach (auto middle, middles)
{
QStringList bottoms;
bottoms.append("A" + QString(i));
bottoms.append("B" + QString(i));
bottoms.append("C" + QString(i));
i++;
m_middles.append(new CMiddle(middle, bottoms));
}
}
Q_INVOKABLE QVector<CMiddle*>& middles()
{
return m_middles;
}
Q_INVOKABLE CMiddle* middle(const int index)
{
return m_middles[index];
}
private:
QVector<CMiddle*> m_middles;
};
#endif // CTOP_H
main.c:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QString>
#include <QVector>
#include <QStringList>
#include <QVariant>
#include <QQmlContext>
#include "ctop.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStringList middles;
middles.append("FirstMiddle");
middles.append("SecondMiddle");
CTop* top = new CTop(middles);
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("theTop", QVariant::fromValue(top));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml:
import QtQuick 2.9
import QtQuick.Window 2.2
import Top 1.0
Window
{
width: 600
height: 400
visible: true
Repeater
{
model: theTop.middles();
delegate: txtComp;
}
Component
{
id: txtComp;
Text
{
text: name;
}
}
}
The question is: Why isn't the name of the one of the CMiddle objects displayed in the QML code? I wanted to obtain the CMiddle components (to act as a model) from the exported to QML CTop components. If this code worked, I would then go further and made another model for accessing the CBottom objects within each CMiddle object.
For instance, I noticed that this QML code works:
import QtQuick 2.9
import QtQuick.Window 2.2
import Top 1.0
Window
{
width: 600
height: 400
visible: true
Repeater
{
model: theTop;
delegate: txtComp;
}
Component
{
id: txtComp;
Text
{
text: middle(0).name;
}
}
}
It doesnt make much sense, but shows that the CTop component is exposed correctly to the QML part.
Why cant the output Qvector of CMiddle pointers act as a model in the QML part?
QML does not know QList<CMiddle *>, instead you should use QList<QObject *>:
CTop.h
// ...
Q_INVOKABLE QList<QObject*> middles(){
QList<QObject*> objects;
for(CMiddle *m : qAsConst(m_middles)){
objects << m;
}
return objects;
}
// ...
Also another error is that top should not necessarily be a pointer, and you can pass it without using QVariant::fromValue() since it is a QObject:
main.cpp
// ...
CTop top(middles);
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("theTop", &top);
Also in a Repeater to obtain the item of the model using modelData:
main.qml
//...
Component{
id: txtComp;
Text{
text: modelData.name
}
}
//...
The complete project can be found here
I have 2 classes, MyApp and MyAppView. MyApp class will hold other classes and the implementation will be here. (you can call it Manager class or System class). MyAppView class only interacts with main.qml like it'll have lots of "Q_PROPERTY"ies. I think you understand the point. I don't want MyApp will have "Q_PROPERTY"ies.
The scenerio is as the following;
//------------------------------------
//---------------------------main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myapp.h"
#include "myappview.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyAppView>("org.myappview", 1, 0, "MyAppView");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
MyApp myApp;
return app.exec();
}
//------------------------------------
//---------------------------myappview.h
#include <QObject>
class MyAppView : QObject
{
Q_OBJECT
Q_PROPERTY(QString myString READ getMyString NOTIFY myStringChanged)
public:
MyAppView();
QString getMyString() { return m_myString; }
void setMyString(QString newString)
{
m_myString = newString;
emit myStringChanged;
}
signals:
void myStringChanged();
private:
QString m_myString;
}
//------------------------------------
//---------------------------main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import org.myappview 1.0
Window {
visible: true
MyAppView {
id: backend
}
Text {
text: qsTr(backend.myString)
}
}
//------------------------------------
//---------------------------myapp.h
#include <QObject>
#include "myappview.h"
class MyApp : QObject
{
Q_OBJECT
public:
MyApp();
private:
MyAppView appView;
void changeMyStringInAppView()
{
// This will automatically update main.qml
appView.setMyString("This is new string");
}
}
Also it is okay to reaching existing QML instance from MyApp, instead of instantiating QML from MyApp. So the main point is instantiating or reaching View class from Manager class so that I can control it easily. Maybe at some part, my logic is wrong. Please tell me if I am. I'm okay with all the suggestions.
The problem in your code is that the MyAppView of MyApp is different from the one created in QML, so if you update the appView text it will not be reflected in the backend text, so the solution is to expose an object from MyApp to QML with setContextProperty() and will call a function to establish the MyAppView created in QML (Keep in mind to create only one MyApp but you will have the same problem)
// myappview.h
#ifndef MYAPPVIEW_H
#define MYAPPVIEW_H
#include <QObject>
class MyAppView : public QObject
{
Q_OBJECT
Q_PROPERTY(QString myString READ getMyString NOTIFY myStringChanged)
public:
explicit MyAppView(QObject *parent = nullptr) : QObject(parent)
{}
QString getMyString() const { return m_myString; }
void setMyString(const QString & newString)
{
if(m_myString != newString){
m_myString = newString;
emit myStringChanged();
}
}
signals:
void myStringChanged();
private:
QString m_myString;
};
#endif // MYAPPVIEW_H
// myapp.h
#ifndef MYAPP_H
#define MYAPP_H
#include "myappview.h"
#include <QObject>
class MyApp : public QObject
{
Q_OBJECT
public:
explicit MyApp(QObject *parent = nullptr) : QObject(parent),
appView(nullptr)
{}
Q_INVOKABLE void setAppView(MyAppView *value){
appView = value;
}
void changeMyStringInAppView()
{
if(appView)
appView->setMyString("This is new string");
}
private:
MyAppView *appView;
};
#endif // MYAPP_H
// main.cpp
#include "myapp.h"
#include "myappview.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<MyAppView>("org.myappview", 1, 0, "MyAppView");
MyApp myapp;
QTimer::singleShot(1000, &myapp, &MyApp::changeMyStringInAppView);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myapp", &myapp);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
// main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import org.myappview 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MyAppView {
id: backend
}
Text {
text: qsTr(backend.myString)
}
Component.onCompleted: myapp.setAppView(backend)
}
I am trying to expose QList with custom objects (Sample) into QML. Whenever I store those custom objects (they inherits form QObject) into QList<QObject *>, they show up, but without info, but when I try expose them as a QList<Sample *>, they don't.
sample.h
class Sample : public QObject
{
Q_OBJECT
Q_PROPERTY(QString getVar READ getVar WRITE setVar NOTIFY varChanged)
public:
explicit Sample();
//! Returns var
QString getVar() const { return var; }
//! Sets var
void setVar(const QString &a);
signals:
varChanged();
protected:
QString var;
};
Class containing list looks like this
samplecontrol.h
class SampleManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<Sample *> getSampleList READ getSampleList NOTIFY sampleListChanged)
public:
SampleManager(const QString &path);
//! Returns sample list
QList<Sample *> getSampleList() const { return sampleList_; }
signals:
sampleListChanged();
protected:
QList<Sample *> sampleList_;
};
I am setting context with
view_->rootContext()->setContextProperty("slabGridModel", QVariant::fromValue(samplecontrol.getSampleList()));
As I said, when i tired
QList<QObject *> datalist;
datalist.append(sampleManager.getSampleList().first());
datalist.append(sampleManager.getSampleList().last());
it worked. How can I make it work with QList<Sample *>?
Thanks for your help!
You can pass a list of QObjects, but the problem is that it will not notify the view if more elements are added, if you want the view to be notified you must use a model that inherits from QAbstractItemModel. On the other hand how are you doing the datamodel as qproperty it is better to expose the SampleManager:
samplemodel.h
#ifndef SAMPLEMODEL_H
#define SAMPLEMODEL_H
#include "sample.h"
#include <QAbstractListModel>
class SampleModel : public QAbstractListModel
{
Q_OBJECT
public:
using QAbstractListModel::QAbstractListModel;
~SampleModel(){
qDeleteAll(mSamples);
mSamples.clear();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override{
if (parent.isValid())
return 0;
return mSamples.size();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
if (!index.isValid())
return QVariant();
if(role == Qt::UserRole){
Sample *sample = mSamples[index.row()];
return QVariant::fromValue(sample);
}
return QVariant();
}
void appendSample(Sample * sample)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
mSamples << sample;
endInsertRows();
}
QHash<int, QByteArray> roleNames() const{
QHash<int, QByteArray> roles;
roles[Qt::UserRole] = "sample";
return roles;
}
private:
QList<Sample *> mSamples;
};
#endif // SAMPLEMODEL_H
samplemanager.h
#ifndef SAMPLEMANAGER_H
#define SAMPLEMANAGER_H
#include "samplemodel.h"
#include <QObject>
class SampleManager : public QObject
{
Q_OBJECT
Q_PROPERTY(SampleModel* model READ model WRITE setModel NOTIFY modelChanged)
public:
using QObject::QObject;
SampleModel *model() const{
return mModel.get();
}
void setModel(SampleModel *model){
if(mModel.get() == model)
return;
mModel.reset(model);
}
signals:
void modelChanged();
private:
QScopedPointer<SampleModel> mModel;
};
#endif // SAMPLEMANAGER_H
main.cpp
#include "samplemanager.h"
#include "samplemodel.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTime>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
SampleManager manager;
manager.setModel(new SampleModel);
// test
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&manager](){
manager.model()->appendSample(new Sample(QTime::currentTime().toString()));
});
timer.start(1000);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("manager", &manager);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
GridView {
anchors.fill: parent
model: manager.model
delegate:
Rectangle {
width: 100
height: 100
color: "darkgray"
Text {
text: sample.getVar
anchors.centerIn: parent
}
}
}
}
The complete example can be found in the following link.
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_())