Qt学习笔记外观篇(五):子类化窗口部件类
来源:互联网 发布:胖胡斐 淘宝商城 编辑:程序博客网 时间:2024/05/14 18:29
如前所述,自定义外观的第三种方法是子类化窗口部件类。子类化窗口类适用于能够经常使用的,具有鲜明特性的部件。子类化窗口类更多的适用于定制功能而非外观。
子类化窗口部件类的过程就是重新实现事件处理函数的过程。
下面是自定义圆形按钮类:
class RoundButton : public QPushButton { Q_OBJECT public: RoundButton(QWidget * parent = 0); RoundButton(const QString & text, QWidget * parent = 0); RoundButton(const QIcon & icon,const QString & text ,QWidget * parent = 0); virtual ~RoundButton();QSize sizeHint();QSize minimumSize(); void setColor(QColor color) { m_color = color; } void setHighlight(QColor highlight) { m_highlight = highlight; } void setShadow(QColor shadow) { m_shadow = shadow; } //Range: 0.0 [invisible] - 1.0 [opaque] void setOpacity(qreal opacity) { m_opacity = opacity; } //Range: 0 [rectangle] - 99 [oval] void setRoundness(int roundness) { m_roundness = roundness; } protected: void paintEvent(QPaintEvent * pe); //void drawButton(QPainter* pe); void enterEvent(QEvent * e); void leaveEvent(QEvent * e); void mousePressEvent(QMouseEvent * e); void mouseReleaseEvent(QMouseEvent * e); private: QRect calculateIconPosition(QRect button_rect, QSize icon_size);void adjustGeometry(); private: bool m_hovered; bool m_pressed; QColor m_color; QColor m_highlight; QColor m_shadow; qreal m_opacity; int m_roundness; };我们需要重新实现paintEvent(),绘制按钮的时候,我们需要参考一些状态:鼠标是否悬停在按钮上,鼠标是否被按下。所以我们需要重新实现其他的一些事件处理函数,来记录这些状态的变化。
RoundButton::RoundButton(QWidget * parent) : QPushButton(parent), m_hovered(false), m_pressed(false), m_color(Qt::gray), m_highlight(Qt::lightGray), m_shadow(Qt::black), m_opacity(1.0), m_roundness(0){}RoundButton::RoundButton(const QString & text, QWidget * parent) : QPushButton(text, parent), m_hovered(false), m_pressed(false), m_color(Qt::gray), m_highlight(Qt::lightGray), m_shadow(Qt::black), m_opacity(1.0), m_roundness(0){}RoundButton::RoundButton(const QIcon & icon,const QString & text ,QWidget * parent) : QPushButton(icon,text,parent), m_hovered(false), m_pressed(false), m_color(Qt::gray), m_highlight(Qt::lightGray),//强光(效果) m_shadow(Qt::black), m_opacity(1.0),// 不透明 m_roundness(0)// 圆,圆度{}RoundButton::~RoundButton(){}QSize RoundButton::sizeHint(){return QSize(200,200);}QSize RoundButton::minimumSize(){return QSize(100,100);}
上面是一些无关紧要的函数。下面是获取鼠标状态的函数:
void RoundButton::enterEvent(QEvent * e){ m_hovered = true; this->repaint(); QPushButton::enterEvent(e);}void RoundButton::leaveEvent(QEvent * e){ m_hovered = false; this->repaint(); QPushButton::leaveEvent(e);}void RoundButton::mousePressEvent(QMouseEvent * e){ m_pressed = true; this->repaint(); QPushButton::mousePressEvent(e);}void RoundButton::mouseReleaseEvent(QMouseEvent * e){ m_pressed = false; this->repaint(); QPushButton::mouseReleaseEvent(e);}
这些函数,确定了鼠标是否按下,是否悬停。下面进入我们自定义外观时最关键的函数paintEvent():
void RoundButton::paintEvent(QPaintEvent * pe) //void RoundButton::drawButton(QPainter* pe){ Q_UNUSED(pe); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing);//抗锯齿处理 //test for state changes QColor button_color; if(this->isEnabled()) { m_hovered ? button_color = m_highlight : button_color = m_color; if(m_pressed) { button_color = m_highlight.darker(250); } } else { button_color = QColor(50, 50, 50); }adjustGeometry();QRect button_rect=this->rect(); //outline painter.setPen(QPen(QBrush(Qt::red), 2.0)); //main button QPainterPath painter_path; //painter_path.addRoundRect(1, 1, button_rect.width() - 2, button_rect.height() - 2, m_roundness, m_roundness); painter_path.addEllipse(0,0,button_rect.height(),button_rect.height()); painter.setClipPath(painter_path); //icon QString text = this->text(); QIcon icon = this->icon(); if(m_pressed==false){ if( !icon.isNull()) { QSize icon_size =button_rect.size(); QRect icon_position = this->calculateIconPosition(button_rect,icon_size); painter.setOpacity(1.0); painter.drawPixmap(icon_position, QPixmap(icon.pixmap(icon_size))); } else { painter.fillPath(painter_path,button_color); QFont font = painter.font(); QFontMetrics fm(font); int width = fm.width(text); int height=fm.height(); QSize text_size =QSize(width,height); QRect text_position = this->calculateIconPosition(button_rect,text_size); painter.setOpacity(1.0); painter.drawText(text_position,text); } }}
具体的过程如下:首先是根据是否悬停,是否按下确定按钮的渲染颜色,然后将按钮的大小调整为正方形,根据正方形得到圆形按钮的轨迹,然后在圆形按钮的区域内绘制图片或者文字。下面是两个辅助函数:adjustGeometry()用于将按钮大小调整为正方形;calculateIconPosition()用于确定文字或图片的绘制位置。
QRect RoundButton::calculateIconPosition(QRect button_rect, QSize icon_size){ int x = (button_rect.width() / 2) - (icon_size.width() / 2); int y = (button_rect.height() / 2) - (icon_size.height() / 2); int width = icon_size.width(); int height = icon_size.height(); QRect icon_position; icon_position.setX(x); icon_position.setY(y); icon_position.setWidth(width); icon_position.setHeight(height); return icon_position;}void RoundButton::adjustGeometry(){QRect buttonRect=this->geometry();int dx=0,dy=0;if(buttonRect.width()>buttonRect.height()){dx=(buttonRect.width()-buttonRect.height())/2;buttonRect.setX(buttonRect.x()+dx);buttonRect.setWidth(buttonRect.height());}else{dy=(buttonRect.height()-buttonRect.width())/2;buttonRect.setY(buttonRect.y()+dy);buttonRect.setHeight(buttonRect.width());}this->setGeometry(buttonRect);/*//QRect button_rect = QRect(1, 1, 40, 40);QRect button_rect =(rect().width()>rect().height())?QRect((rect().width()-rect().height())/2,0,rect().height(),rect().height()):QRect(0,(rect().height()-rect().width())/2,rect().width(),rect().width());this->setFixedSize(button_rect.width(),button_rect.height());*/}
使用:
#include <QApplication>#include<QDialog>#include<QLabel>#include<QLayout>#include"roundbutton.h"int main(int argc, char *argv[]){ QApplication app(argc, argv); QDialog dialog; QLabel label(QObject::tr("hello world"),&dialog); RoundButton button(QObject::tr("hello"),&dialog); button.setIcon(QIcon(QObject::tr(":/images/play.png"))); button.setMinimumSize(100,100);QVBoxLayout layout(&dialog);layout.addWidget(&label);layout.addWidget(&button);dialog.setLayout(&layout); dialog.show(); return app.exec();}
至此,我们三种自定义外观的方法就总结完了,在应用程序级上自定义外观,我们选用qss,但是像圆形按钮之类这些特殊的,经常用的部件,我们可以通过子类化窗口部件来实现,如果是大型应用程序,需要自己的风格,这时候再考虑QStyle。
0 0
- Qt学习笔记外观篇(五):子类化窗口部件类
- Qt学习笔记--窗口部件(Widget)
- Qt学习笔记--窗口部件(Widget)
- Qt学习笔记--窗口部件(Widget)
- Qt学习笔记--窗口部件(Widget)
- QT学习笔记:窗口部件
- 自定义QT窗口部件外观
- 自定义QT窗口部件外观
- Qt学习笔记(三) 自定义窗口部件
- 自定义QT窗口部件外观之QStyle
- Qt笔记_窗口部件
- python3+PyQt5 自定义窗口部件--子类化内置窗口部件
- Qt学习笔记外观篇(三):Qt Style Sheet
- qt学习第四课:子类化窗口
- QT学习--窗口部件类学习
- Qt学习笔记外观篇(一):QPalette调色板
- Qt学习笔记外观篇(二):QStyle
- Qt学习笔记外观篇(六):QLabel
- Oracle join
- Git使用新手入门
- GoodZhang在学Python(十三)--Python3数据get与post提交
- 【算法】数字三角形问题
- Makefile 的几种赋值方式
- Qt学习笔记外观篇(五):子类化窗口部件类
- C++——三种继承方式与三种访问权限的相互组合
- Memcache知识点梳理
- 小编给你说句话
- 海水淡化膜:世韩8040海水淡化膜的综合特性
- T-SQL查询进阶—理解SQL Server中的锁
- servlet细节
- Mac环境下svn命令行的使用
- MapReduce与自然语言处理