-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
340 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
// | ||
// Created by TURIING on 2023/6/29. | ||
// | ||
|
||
#include "PageSwitcher.h" | ||
|
||
PageSwitcher::PageSwitcher(QWidget *_parent): QWidget(_parent) { | ||
m_textFont = this->font(); | ||
m_textFont.setFamily("微软雅黑"); | ||
m_textFont.setPixelSize(14); | ||
|
||
this->setCursor(Qt::PointingHandCursor); | ||
this->setMouseTracking(true); | ||
|
||
QPalette palette = this->palette(); | ||
palette.setColor(QPalette::WindowText, m_unActiveTextColor); | ||
palette.setColor(QPalette::HighlightedText, m_activeTextColor); | ||
palette.setColor(QPalette::Window, m_unActiveBgColor); | ||
palette.setColor(QPalette::Highlight, m_indicateBarColor); | ||
palette.setColor(QPalette::ToolTipBase, m_messageAlertColor); | ||
this->setPalette(palette); | ||
} | ||
|
||
void PageSwitcher::paintEvent(QPaintEvent *_event) { | ||
QPainter painter(this); | ||
painter.setRenderHint(QPainter::Antialiasing); | ||
painter.setPen(Qt::NoPen); | ||
|
||
drawBackground(painter); | ||
|
||
drawIndicateBar(painter); | ||
|
||
drawText(painter); | ||
|
||
drawMessageAlert(painter); | ||
} | ||
|
||
void PageSwitcher::append(const QString &_text, bool _has_message) { | ||
assert(_text.isEmpty() != true); | ||
|
||
m_item.append(Item { _text, _has_message } ); | ||
|
||
this->resize(computeTotalWidth(m_item.count()), this->height()); | ||
} | ||
|
||
/* | ||
* 绘制文本 | ||
*/ | ||
void PageSwitcher::drawText(QPainter &_painter) const { | ||
_painter.save(); | ||
|
||
_painter.setFont(m_textFont); | ||
|
||
for(auto i = 0; i < m_item.count(); i++) { | ||
if((i == mousePosToIndex() && m_isHover) || m_currentItemIndex == i) | ||
_painter.setPen(palette().highlightedText().color()); | ||
else | ||
_painter.setPen(palette().windowText().color()); | ||
|
||
_painter.drawText(indexToRect(i), Qt::AlignCenter, m_item.at(i).text); | ||
} | ||
|
||
_painter.restore(); | ||
} | ||
|
||
/* | ||
* 返回索引对应的item宽度 | ||
*/ | ||
int PageSwitcher::indexToWidth(int _index) const { | ||
assert(_index >= 0); | ||
assert(_index < m_item.count()); | ||
|
||
|
||
auto textWidth = computeTextWidth(m_item.at(_index).text); | ||
|
||
return m_paddingForHorizon * 2 + textWidth; | ||
} | ||
|
||
/* | ||
* 返回索引对应的item区域 | ||
*/ | ||
QRect PageSwitcher::indexToRect(int _index) const { | ||
assert(_index >= 0); | ||
assert(_index < m_item.count()); | ||
|
||
return QRect(computeTotalWidth(_index), 0, indexToWidth(_index), this->height()); | ||
} | ||
|
||
/* | ||
* 计算文本的宽度占用的像素 | ||
*/ | ||
int PageSwitcher::computeTextWidth(const QString &_text) const { | ||
QFontMetrics fontMetrics(m_textFont); | ||
return fontMetrics.horizontalAdvance(_text); | ||
} | ||
|
||
/* | ||
* 绘制背景 | ||
*/ | ||
void PageSwitcher::drawBackground(QPainter &_painter) const { | ||
_painter.save(); | ||
|
||
_painter.setPen(Qt::NoPen); | ||
_painter.setBrush(palette().window()); | ||
_painter.drawRect(this->rect()); | ||
|
||
_painter.restore(); | ||
} | ||
|
||
/* | ||
* 返回给定索引所指区块的横坐标,即该区块之前的所有区块的宽度和 | ||
*/ | ||
int PageSwitcher::computeTotalWidth(int _index) const { | ||
assert(_index >= 0); | ||
assert(_index <= m_item.count()); | ||
|
||
int widthCumulate = 0; | ||
for(auto i = 0; i < _index; i++) | ||
widthCumulate += indexToWidth(i); | ||
return widthCumulate; | ||
} | ||
|
||
/* | ||
* 绘制指示条 | ||
*/ | ||
void PageSwitcher::drawIndicateBar(QPainter &_painter) const { | ||
_painter.save(); | ||
|
||
_painter.setPen(Qt::NoPen); | ||
_painter.setBrush(palette().highlight().color()); | ||
|
||
auto rect = indexToRect(m_currentItemIndex); | ||
int width; | ||
if(m_item.at(m_currentItemIndex).has_message) | ||
width = computeTextWidth(m_item.at(m_currentItemIndex).text) + 3 + m_messageAlertDiameter; | ||
else | ||
width = computeTextWidth(m_item.at(m_currentItemIndex).text); | ||
|
||
_painter.drawRect(rect.x() + m_paddingForHorizon, (int)(this->height() * 0.80), width, 2); | ||
|
||
_painter.restore(); | ||
} | ||
|
||
void PageSwitcher::mousePressEvent(QMouseEvent *_event) { | ||
auto index = mousePosToIndex(); | ||
if(_event->button() == Qt::LeftButton && m_currentItemIndex != index) { | ||
m_currentItemIndex = index; | ||
this->update(); | ||
emit indexChanged(m_currentItemIndex); | ||
} | ||
QWidget::mousePressEvent(_event); | ||
} | ||
|
||
/* | ||
* 返回鼠标位置对应的区块索引 | ||
*/ | ||
int PageSwitcher::mousePosToIndex() const { | ||
int widthCumulate = 0; | ||
for(auto i = 0; i < m_item.count(); i++) { | ||
widthCumulate += indexToWidth(i); | ||
if(widthCumulate > m_mousePos.x()) | ||
return i; | ||
} | ||
} | ||
|
||
void PageSwitcher::mouseMoveEvent(QMouseEvent *_event) { | ||
m_mousePos = _event->pos(); | ||
this->update(); | ||
|
||
QWidget::mouseMoveEvent(_event); | ||
} | ||
|
||
void PageSwitcher::enterEvent(QEvent *_event) { | ||
m_isHover = true; | ||
this->update(); | ||
|
||
QWidget::enterEvent(_event); | ||
} | ||
|
||
void PageSwitcher::leaveEvent(QEvent *_event) { | ||
m_isHover = false; | ||
this->update(); | ||
|
||
QWidget::leaveEvent(_event); | ||
} | ||
|
||
/* | ||
* 设置默认选中项 | ||
*/ | ||
void PageSwitcher::setCurrentItem(int _index) { | ||
assert(_index >= 0); | ||
assert(_index < m_item.count()); | ||
|
||
m_currentItemIndex = _index; | ||
} | ||
|
||
/* | ||
* 绘制消息提醒小圆点 | ||
*/ | ||
void PageSwitcher::drawMessageAlert(QPainter &_painter) const { | ||
_painter.save(); | ||
|
||
_painter.setBrush(palette().toolTipBase()); | ||
|
||
for(auto i = 0; i < m_item.count(); i++) { | ||
if(m_item.at(i).has_message) { | ||
auto x = computeTotalWidth(i) + m_paddingForHorizon + computeTextWidth(m_item.at(i).text) + 3; | ||
_painter.drawEllipse(x, this->height() * 0.4, m_messageAlertDiameter, m_messageAlertDiameter); | ||
} | ||
|
||
} | ||
|
||
_painter.restore(); | ||
} | ||
/* | ||
* 设置消息提醒 | ||
*/ | ||
void PageSwitcher::setMessageAlert(int _index, bool _has_message) { | ||
assert(_index >= 0); | ||
assert(_index < m_item.count()); | ||
|
||
m_item[_index].has_message = _has_message; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// Created by TURIING on 2023/6/29. | ||
// | ||
|
||
#ifndef QTDEMO_PAGESWITCHER_H | ||
#define QTDEMO_PAGESWITCHER_H | ||
|
||
#include <QWidget> | ||
#include <QVector> | ||
#include <QPainter> | ||
#include <QFontMetrics> | ||
#include <QDebug> | ||
#include <QPalette> | ||
#include <QMouseEvent> | ||
|
||
class PageSwitcher: public QWidget{ | ||
Q_OBJECT | ||
struct Item { | ||
QString text; | ||
bool has_message = false; | ||
}; | ||
public: | ||
explicit PageSwitcher(QWidget *_parent = nullptr); | ||
void append(const QString &_text, bool _has_message = false); | ||
void setCurrentItem(int _index); | ||
void setMessageAlert(int _index, bool _has_message = true); | ||
protected: | ||
void paintEvent(QPaintEvent *_event) override; | ||
void mousePressEvent(QMouseEvent *_event) override; | ||
void mouseMoveEvent(QMouseEvent *_event) override; | ||
void enterEvent(QEvent *_event) override; | ||
void leaveEvent(QEvent *_event) override; | ||
private: | ||
void drawText(QPainter &_painter) const; | ||
void drawBackground(QPainter &_painter) const; | ||
void drawIndicateBar(QPainter &_painter) const; | ||
void drawMessageAlert(QPainter &_painter) const; | ||
|
||
int indexToWidth(int _index) const; | ||
QRect indexToRect(int _index) const; | ||
int computeTextWidth(const QString &_text) const; | ||
int computeTotalWidth(int _index) const; | ||
int mousePosToIndex() const; | ||
private: | ||
QVector<Item> m_item; | ||
int m_currentItemIndex = -1; // 选中的item | ||
QPoint m_mousePos; // 鼠标在控件内的位置 | ||
bool m_isHover = false; // 鼠标是否悬停在控件上 | ||
|
||
/* UI 相关*/ | ||
QFont m_textFont; // 文本所用的字体 | ||
QColor m_unActiveTextColor = QColor(107, 107, 107); // 未激活时文本颜色 | ||
QColor m_activeTextColor = QColor(0, 0, 0); // 激活时文本颜色 | ||
QColor m_unActiveBgColor = QColor(249, 249, 249); // 未激活时的背景色 | ||
QColor m_indicateBarColor = QColor(255, 108, 55); // 指示条的颜色 | ||
QColor m_messageAlertColor = QColor(12, 187, 82); // 消息提醒小圆点的颜色 | ||
const int m_paddingForHorizon = 15; // 每个区块内左右两边的空白大小 | ||
const int m_messageAlertDiameter = 7; // 消息提醒小圆点的直径 | ||
public: signals: | ||
void indexChanged(int _index); | ||
}; | ||
|
||
|
||
#endif //QTDEMO_PAGESWITCHER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.