Skip to content

Commit

Permalink
添加按钮宽高比设置,可设置按钮的最大宽度
Browse files Browse the repository at this point in the history
  • Loading branch information
czyt1988 committed Jan 5, 2025
1 parent f7a25f3 commit e329c29
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 59 deletions.
32 changes: 29 additions & 3 deletions src/SARibbonBar/SARibbonBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ int SARibbonBar::PrivateData::systemTabBarHeight() const
*/
int SARibbonBar::PrivateData::calcTabBarHeight()
{
int defaultHeight = systemTabBarHeight();
int fontHeight = q_ptr->fontMetrics().lineSpacing(); // 不要用height,像宋体这种字体,height=12,lineSpacing=14,有些就无法显示
int defaultHeight = systemTabBarHeight();
int fontHeight = q_ptr->fontMetrics().lineSpacing(); // 不要用height,像宋体这种字体,height=12,lineSpacing=14,有些就无法显示
int defaultHeight2 = fontHeight * 1.6;
if (defaultHeight2 < fontHeight + 10) {
defaultHeight2 = fontHeight + 10; // 主要为了满足office2021主题,tab下有个4px的横杠
Expand Down Expand Up @@ -1732,7 +1732,33 @@ void SARibbonBar::setEnableWordWrap(bool on)
*/
bool SARibbonBar::isEnableWordWrap() const
{
return SARibbonToolButton::isEnableWordWrap();
return SARibbonToolButton::isEnableWordWrap();
}

/**
* @brief 文本宽度估算时的宽度比高度系数
* @param fac 系数,默认为1.4,此系数越大,按钮允许的宽度越宽
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果
*
* 此系数和maxwidth取最小值
*/
void SARibbonBar::setButtonTextEllipsisAspectFactor(qreal fac)
{
SARibbonToolButton::setTextEllipsisAspectFactor(fac);
updateRibbonGeometry();
}

/**
* @brief 文本宽度估算时的宽度比高度系数
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果
*
* 此系数和maxwidth取最小值
*/
qreal SARibbonBar::buttonTextEllipsisAspectFactor() const
{
return SARibbonToolButton::textEllipsisAspectFactor();
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/SARibbonBar/SARibbonBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ class SA_RIBBON_EXPORT SARibbonBar : public QMenuBar
void setEnableWordWrap(bool on);
bool isEnableWordWrap() const;

// 文本宽度估算时的宽度比高度系数,超过此系数的宽度时,开始尝试换行或者省略号显示
void setButtonTextEllipsisAspectFactor(qreal fac = 1.4);
qreal buttonTextEllipsisAspectFactor() const;

// 设置pannel的标题栏高度
int pannelTitleHeight() const;
void setPannelTitleHeight(int h);
Expand Down
136 changes: 92 additions & 44 deletions src/SARibbonBar/SARibbonToolButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,19 @@
#include <QScreen>
#include <QProxyStyle>

/**
* @def 定义文字换行时2行文本的矩形高度系数,此系数决定文字区域的高度
*
* fontMetrics.lineSpacing*系数 = 文本区域高度
*/
#define SARIBBONTOOLBUTTON_WORDWRAP_TEXT_FACTOR 2.05

/**
* @def 定义文字不换行时单行文本的矩形高度系数,此系数决定文字区域的高度
*
* fontMetrics.lineSpacing*系数 = 文本区域高度
*/
#define SARIBBONTOOLBUTTON_NOWORDWRAP_TEXT_FACTOR 1.2

/**
* @def 定义小按钮的矩形高度系数,此系数决定文字区域的高度
*
* fontMetrics.lineSpacing*系数 = 文本区域高度
*/
#define SARIBBONTOOLBUTTON_SMALLBUTTON_TEXT_FACTOR 1.4

/**
* @def 文本宽度估算时的宽度比高度系数
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则触发换行估算
*/
#define SARIBBONTOOLBUTTON_WORDWRAP_WIDTH_PER_HEIGHT_RATIO 1.4

/**
* @def 开启此宏会打印一些常见信息
*/
#ifndef SA_RIBBON_TOOLBUTTON_DEBUG_PRINT
#define SA_RIBBON_TOOLBUTTON_DEBUG_PRINT 0
#endif

#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW
#define SARIBBONTOOLBUTTON_DEBUG_DRAW 0
#endif

#if SARIBBONTOOLBUTTON_DEBUG_DRAW
#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT
#define SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT(p, rect) \
do { \
p.save(); \
Expand All @@ -59,10 +36,12 @@
p.drawRect(rect); \
p.restore(); \
} while (0)

#endif
#else
#ifndef SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT
#define SARIBBONTOOLBUTTON_DEBUG_DRAW_RECT(p, rect)
#endif
#endif
namespace SA
{

Expand Down Expand Up @@ -217,8 +196,7 @@ class SARibbonToolButton::PrivateData
int textDrawRectHeight,
const QString& text,
const QFontMetrics& fm,
float widthHeightRatio = SARIBBONTOOLBUTTON_WORDWRAP_WIDTH_PER_HEIGHT_RATIO,
int maxTrycount = 3);
int maxTrycount = 3);
QPixmap createIconPixmap(const QStyleOptionToolButton& opt, const QSize& iconsize) const;
// 获取文字的对其方式
int getTextAlignment() const;
Expand All @@ -240,11 +218,56 @@ class SARibbonToolButton::PrivateData
QSize mSizeHint; ///< 保存计算好的sizehint
bool mIsTextNeedWrap { false }; ///< 标记文字是否需要换行显示
public:
static bool s_enableWordWrap; ///< 在lite模式下是否允许文字换行,如果允许,则图标相对比较小,默认不允许
/**
* @brief 在lite模式下是否允许文字换行
*
* 如果允许,则图标相对比较小,默认不允许
*/
static bool s_enableWordWrap;

/**
* @brief 这个系数决定了文字换行时2行文本的矩形高度
*
* 此值应该大于2
*
* 文本区域高度 = fontMetrics.lineSpacing*系数
*/
static qreal s_twoLineHeightFactor;

/**
* @brief 这个系数决定了单行文本的行高度
*
* 此值应该大于1
*
* 文本区域高度 = fontMetrics.lineSpacing*系数
*/
static qreal s_oneLineHeightFactor;

/**
* @brief 这个系数决定了小按钮文本的行高度
*
* 此值应该大于1
*
* 文本区域高度 = fontMetrics.lineSpacing*系数
*/
static qreal s_smallButtonHeightFactor;

/**
* @brief 文本宽度估算时的宽度比高度系数
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果
*
* 此系数和maxwidth取最小值
*/
static qreal s_textEllipsisAspectFactor;
};

// 静态参数初始化
bool SARibbonToolButton::PrivateData::s_enableWordWrap = false;
bool SARibbonToolButton::PrivateData::s_enableWordWrap = false;
qreal SARibbonToolButton::PrivateData::s_twoLineHeightFactor = 2.05;
qreal SARibbonToolButton::PrivateData::s_oneLineHeightFactor = 1.2;
qreal SARibbonToolButton::PrivateData::s_smallButtonHeightFactor = 1.4;
qreal SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor = 1.4;

SARibbonToolButton::PrivateData::PrivateData(SARibbonToolButton* p) : q_ptr(p)
{
Expand Down Expand Up @@ -623,13 +646,13 @@ int SARibbonToolButton::PrivateData::calcTextDrawRectHeight(const QStyleOptionTo
{
if (SARibbonToolButton::LargeButton == mButtonType) {
if (isEnableWordWrap()) {
return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_WORDWRAP_TEXT_FACTOR + opt.fontMetrics.leading();
return opt.fontMetrics.lineSpacing() * s_twoLineHeightFactor + opt.fontMetrics.leading();
} else {
return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_NOWORDWRAP_TEXT_FACTOR;
return opt.fontMetrics.lineSpacing() * s_oneLineHeightFactor;
}
}
// 小按钮
return opt.fontMetrics.lineSpacing() * SARIBBONTOOLBUTTON_SMALLBUTTON_TEXT_FACTOR;
return opt.fontMetrics.lineSpacing() * s_smallButtonHeightFactor;
}

/**
Expand All @@ -645,12 +668,12 @@ int SARibbonToolButton::PrivateData::estimateLargeButtonTextWidth(int buttonHeig
int textDrawRectHeight,
const QString& text,
const QFontMetrics& fm,
float widthHeightRatio,
int maxTrycount)
{
QSize textSize;
int space = SA_FONTMETRICS_WIDTH(fm, (QLatin1Char(' '))) * 2;
int hintMaxWidth = buttonHeight * widthHeightRatio; ///< 建议的宽度
int space = SA_FONTMETRICS_WIDTH(fm, (QLatin1Char(' '))) * 2;
int hintMaxWidth = qMin(static_cast< int >(buttonHeight * SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor),
q_ptr->maximumWidth()); ///< 建议的宽度
if (isEnableWordWrap()) {
textSize = fm.size(Qt::TextShowMnemonic, text);
textSize.setWidth(textSize.width() + space);
Expand Down Expand Up @@ -709,10 +732,6 @@ int SARibbonToolButton::PrivateData::estimateLargeButtonTextWidth(int buttonHeig
// 范围合理,直接返回
return textSize.width();
}
if (textSize.width() > q_ptr->maximumWidth()) {
// 超出了极限,就返回极限
return q_ptr->maximumWidth();
}
return hintMaxWidth;
}

Expand Down Expand Up @@ -830,7 +849,7 @@ void SARibbonToolButton::mousePressEvent(QMouseEvent* e)
d_ptr->mMenuButtonPressed = false;
//! 注意这里要用QAbstractButton的mousePressEvent,而不是QToolButton的mousePressEvent
//! QToolButton的mousePressEvent主要是为了弹出菜单,这里弹出菜单的方式是不一样的,因此不能执行QToolButton的mousePressEvent
QAbstractButton::mousePressEvent(e);
QToolButton::mousePressEvent(e);
}

void SARibbonToolButton::mouseReleaseEvent(QMouseEvent* e)
Expand Down Expand Up @@ -1198,6 +1217,35 @@ bool SARibbonToolButton::isEnableWordWrap()
return SARibbonToolButton::PrivateData::s_enableWordWrap;
}

/**
* @brief 文本宽度估算时的宽度比高度系数
* @param fac 系数,默认为1.4,此系数越大,按钮允许的宽度越宽
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果
*
* 此系数和maxwidth取最小值
*/
void SARibbonToolButton::setTextEllipsisAspectFactor(qreal fac)
{
if (fac < 0 && qFuzzyIsNull(fac)) {
qWarning() << tr("The TextEllipsisAspectFactor parameter cannot be set to 0 or a negative number"); // cn:textEllipsisAspectFactor不能设置为0或者负数
fac = 1.0;
}
SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor = fac;
}

/**
* @brief 文本宽度估算时的宽度比高度系数
*
* 超过此系数的宽度时,开始尝试换行,例如按钮高度为h,如果单行文本的宽度大于h*系数,则按钮将不进行横向拉伸,类似于maxwidth效果
*
* 此系数和maxwidth取最小值
*/
qreal SARibbonToolButton::textEllipsisAspectFactor()
{
return SARibbonToolButton::PrivateData::s_textEllipsisAspectFactor;
}

bool SARibbonToolButton::event(QEvent* e)
{
switch (e->type()) {
Expand Down
27 changes: 15 additions & 12 deletions src/SARibbonBar/SARibbonToolButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,30 @@ class SA_RIBBON_EXPORT SARibbonToolButton : public QToolButton
explicit SARibbonToolButton(QWidget* parent = nullptr);
explicit SARibbonToolButton(QAction* defaultAction, QWidget* parent = nullptr);
~SARibbonToolButton();
//标记按钮的样式,按钮的样式有不同的渲染方式
// 标记按钮的样式,按钮的样式有不同的渲染方式
RibbonButtonType buttonType() const;
void setButtonType(const RibbonButtonType& buttonType);
//是否是小按钮
// 是否是小按钮
bool isSmallRibbonButton() const;
//是否是大按钮
// 是否是大按钮
bool isLargeRibbonButton() const;
//最小尺寸提示
// 最小尺寸提示
virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE;

//获取间距
// 获取间距
int spacing() const;
//更新尺寸
// 更新尺寸
void updateRect();

virtual QSize sizeHint() const Q_DECL_OVERRIDE;

public:
//在lite模式下是否允许文字换行
// 在lite模式下是否允许文字换行
static void setEnableWordWrap(bool on);
static bool isEnableWordWrap();
// 文本宽度估算时的宽度比高度系数,超过此系数的宽度时,开始尝试换行或者省略号显示
static void setTextEllipsisAspectFactor(qreal fac = 1.4);
static qreal textEllipsisAspectFactor();

protected:
virtual void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE;
Expand All @@ -61,18 +64,18 @@ class SA_RIBBON_EXPORT SARibbonToolButton : public QToolButton
virtual void leaveEvent(QEvent* e) Q_DECL_OVERRIDE;
virtual bool hitButton(const QPoint& pos) const Q_DECL_OVERRIDE;
virtual bool event(QEvent* e) Q_DECL_OVERRIDE;
//事件改变 - 主要为了捕获字体的改变
// 事件改变 - 主要为了捕获字体的改变
virtual void changeEvent(QEvent* e) Q_DECL_OVERRIDE;
virtual void actionEvent(QActionEvent* e) Q_DECL_OVERRIDE;

protected:
//绘制按钮
// 绘制按钮
virtual void paintButton(QPainter& p, const QStyleOptionToolButton& opt);
//绘制图标
// 绘制图标
virtual void paintIcon(QPainter& p, const QStyleOptionToolButton& opt, const QRect& iconDrawRect);
//绘制文本
// 绘制文本
virtual void paintText(QPainter& p, const QStyleOptionToolButton& opt, const QRect& textDrawRect);
//绘制Indicator
// 绘制Indicator
virtual void paintIndicator(QPainter& p, const QStyleOptionToolButton& opt, const QRect& indicatorDrawRect);

private:
Expand Down

0 comments on commit e329c29

Please sign in to comment.