Skip to content

Commit 73ba212

Browse files
author
KhalilSelyan
committedMay 16, 2024
create custom segmented button group/children components
Signed-off-by: KhalilSelyan <khalil@leodrive.ai>
1 parent 5defcdf commit 73ba212

File tree

4 files changed

+252
-0
lines changed

4 files changed

+252
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef CUSTOMSEGMENTEDBUTTON_HPP
2+
#define CUSTOMSEGMENTEDBUTTON_HPP
3+
4+
#include "custom_segmented_button_item.hpp"
5+
6+
#include <QButtonGroup>
7+
#include <QColor>
8+
#include <QHBoxLayout>
9+
#include <QPainter>
10+
#include <QPainterPath>
11+
#include <QPushButton>
12+
#include <QStyleOption>
13+
#include <QWidget>
14+
15+
class CustomSegmentedButton : public QWidget
16+
{
17+
Q_OBJECT
18+
19+
public:
20+
explicit CustomSegmentedButton(QWidget * parent = nullptr);
21+
22+
CustomSegmentedButtonItem * addButton(const QString & text);
23+
QButtonGroup * getButtonGroup() const;
24+
25+
QSize sizeHint() const override;
26+
QSize minimumSizeHint() const override;
27+
28+
Q_SIGNALS:
29+
void buttonClicked(int id);
30+
31+
protected:
32+
void paintEvent(QPaintEvent * event) override;
33+
34+
private:
35+
void drawBorders(QPainter & painter); // Method to draw borders between buttons
36+
37+
QButtonGroup * buttonGroup;
38+
QHBoxLayout * layout;
39+
};
40+
41+
#endif // CUSTOMSEGMENTEDBUTTON_HPP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef CUSTOMSEGMENTEDBUTTONITEM_HPP
2+
#define CUSTOMSEGMENTEDBUTTONITEM_HPP
3+
4+
#include <QColor>
5+
#include <QHBoxLayout>
6+
#include <QPainter>
7+
#include <QPainterPath>
8+
#include <QPushButton>
9+
#include <QStyleOption>
10+
11+
class CustomSegmentedButtonItem : public QPushButton
12+
{
13+
Q_OBJECT
14+
15+
public:
16+
explicit CustomSegmentedButtonItem(const QString & text, QWidget * parent = nullptr);
17+
18+
void setColors(
19+
const QColor & bg, const QColor & checkedBg, const QColor & activeText,
20+
const QColor & inactiveText);
21+
22+
protected:
23+
void paintEvent(QPaintEvent * event) override;
24+
void enterEvent(QEvent * event) override;
25+
void leaveEvent(QEvent * event) override;
26+
27+
private:
28+
QColor bgColor;
29+
QColor checkedBgColor;
30+
QColor hoverColor = QColor("#3C3F41");
31+
QColor inactiveTextColor;
32+
QColor activeTextColor;
33+
bool isHovered = false;
34+
};
35+
36+
#endif // CUSTOMSEGMENTEDBUTTONITEM_HPP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "custom_segmented_button.hpp"
2+
3+
#include <qsizepolicy.h>
4+
5+
CustomSegmentedButton::CustomSegmentedButton(QWidget * parent)
6+
: QWidget(parent), buttonGroup(new QButtonGroup(this)), layout(new QHBoxLayout(this))
7+
{
8+
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
9+
layout->setContentsMargins(0, 0, 0, 0); // Ensure no margins around the layout
10+
layout->setSpacing(0); // Ensure no spacing between buttons
11+
12+
setLayout(layout);
13+
14+
buttonGroup->setExclusive(true);
15+
16+
connect(
17+
buttonGroup, QOverload<int>::of(&QButtonGroup::idClicked), this,
18+
&CustomSegmentedButton::buttonClicked);
19+
}
20+
21+
CustomSegmentedButtonItem * CustomSegmentedButton::addButton(const QString & text)
22+
{
23+
CustomSegmentedButtonItem * button = new CustomSegmentedButtonItem(text);
24+
layout->addWidget(button);
25+
buttonGroup->addButton(button, layout->count() - 1);
26+
27+
return button;
28+
}
29+
30+
QButtonGroup * CustomSegmentedButton::getButtonGroup() const
31+
{
32+
return buttonGroup;
33+
}
34+
35+
QSize CustomSegmentedButton::sizeHint() const
36+
{
37+
return QSize(400, 45); // Adjust the size hint as needed
38+
39+
// return QSize(
40+
// layout->count() * (layout->itemAt(0)->widget()->width()),
41+
// layout->itemAt(0)->widget()->height() + 10);
42+
}
43+
44+
QSize CustomSegmentedButton::minimumSizeHint() const
45+
{
46+
return sizeHint();
47+
}
48+
49+
void CustomSegmentedButton::paintEvent(QPaintEvent *)
50+
{
51+
QPainter painter(this);
52+
painter.setRenderHint(QPainter::Antialiasing);
53+
54+
// Draw background
55+
QPainterPath path;
56+
path.addRoundedRect(rect(), height() / 2, height() / 2);
57+
58+
painter.setPen(QPen(QColor("#8a9297"), 3));
59+
painter.setBrush(QColor("#0F1417"));
60+
painter.drawPath(path);
61+
62+
// Draw borders between buttons
63+
drawBorders(painter);
64+
}
65+
66+
void CustomSegmentedButton::drawBorders(QPainter & painter)
67+
{
68+
painter.setPen(QPen(QColor("#8a9297"), 3)); // Color for the borders
69+
const QList<QAbstractButton *> buttons = buttonGroup->buttons();
70+
for (int i = 1; i < buttons.size(); ++i) {
71+
QAbstractButton * button = buttons[i];
72+
QRect buttonRect = button->geometry();
73+
int x = buttonRect.left();
74+
painter.drawLine(x, 0, x, height());
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include "custom_segmented_button_item.hpp"
2+
3+
CustomSegmentedButtonItem::CustomSegmentedButtonItem(const QString & text, QWidget * parent)
4+
: QPushButton(text, parent),
5+
bgColor("#0F1417"),
6+
checkedBgColor("#354A54"),
7+
inactiveTextColor("#8a9297"),
8+
activeTextColor("#d0e6f2")
9+
{
10+
setCheckable(true);
11+
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
12+
}
13+
14+
void CustomSegmentedButtonItem::setColors(
15+
const QColor & bg, const QColor & checkedBg, const QColor & activeText,
16+
const QColor & inactiveText)
17+
{
18+
bgColor = bg;
19+
checkedBgColor = checkedBg;
20+
activeTextColor = activeText;
21+
inactiveTextColor = inactiveText;
22+
update();
23+
}
24+
25+
// void CustomSegmentedButtonItem::updateSize()
26+
// {
27+
// QFontMetrics fm(font());
28+
// int width = fm.horizontalAdvance(text()) + 40; // Add padding
29+
// int height = fm.height() + 20; // Add padding
30+
// setFixedSize(width, height);
31+
// }
32+
33+
void CustomSegmentedButtonItem::paintEvent(QPaintEvent *)
34+
{
35+
QPainter painter(this);
36+
painter.setRenderHint(QPainter::Antialiasing);
37+
38+
// Determine the button's color based on its state
39+
QColor buttonColor;
40+
if (isHovered && !isChecked()) {
41+
buttonColor = hoverColor;
42+
} else {
43+
buttonColor = isChecked() ? checkedBgColor : bgColor;
44+
}
45+
// Determine if this is the first or last button
46+
bool isFirstButton = false;
47+
bool isLastButton = false;
48+
49+
QHBoxLayout * parentLayout = qobject_cast<QHBoxLayout *>(parentWidget()->layout());
50+
if (parentLayout) {
51+
int index = parentLayout->indexOf(this);
52+
isFirstButton = (index == 0);
53+
isLastButton = (index == parentLayout->count() - 1);
54+
}
55+
56+
// Draw button background
57+
58+
QRect buttonRect = rect().adjusted(1, 1, -1, -1); // Adjust to fill the space;
59+
60+
// make it shorter in height by making both top and bottom 1 less
61+
buttonRect.setTop(buttonRect.top() + 1);
62+
buttonRect.setBottom(buttonRect.bottom() - 1);
63+
QPainterPath path;
64+
int radius = (height() - 2) / 2;
65+
66+
if (isFirstButton) {
67+
path.moveTo(buttonRect.right(), buttonRect.top());
68+
path.arcTo(buttonRect.left(), buttonRect.top() - 0.5, 2 * radius, 2 * radius, 90, 180);
69+
path.lineTo(buttonRect.right(), buttonRect.bottom());
70+
path.lineTo(buttonRect.right(), buttonRect.top());
71+
} else if (isLastButton) {
72+
path.moveTo(buttonRect.left(), buttonRect.top());
73+
path.arcTo(
74+
buttonRect.right() - 2 * radius, buttonRect.top() - 0.5, 2 * radius, 2 * radius, 90, -180);
75+
path.lineTo(buttonRect.left(), buttonRect.bottom());
76+
path.lineTo(buttonRect.left(), buttonRect.top());
77+
} else {
78+
path.addRect(buttonRect);
79+
}
80+
painter.fillPath(path, buttonColor);
81+
82+
// Draw button text
83+
painter.setPen(isChecked() ? activeTextColor : inactiveTextColor);
84+
painter.drawText(rect(), Qt::AlignCenter, text());
85+
}
86+
87+
void CustomSegmentedButtonItem::enterEvent(QEvent * event)
88+
{
89+
isHovered = true;
90+
update();
91+
QPushButton::enterEvent(event);
92+
}
93+
94+
void CustomSegmentedButtonItem::leaveEvent(QEvent * event)
95+
{
96+
isHovered = false;
97+
update();
98+
QPushButton::leaveEvent(event);
99+
}

0 commit comments

Comments
 (0)