赞
踩
Hello,大家好,今天给大家分享个比较有趣的小示例,按钮特效,具体效果如下图所示
下面,我们来看看它是如何实现的。
按钮特效,需要用到QWidget的方法:
void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
QGraphicsEffect类是窗口特效的基类,基于该基类,Qt提供了四种便捷类:
不加特效的正常图片
1 QGraphicsBlurEffect //模糊特效
2 QGraphicsColorizeEffect //颜色特效
3 QGraphicsOpacityEffect //透明度特效
4 QGraphicsDropShadowEffect //阴影特效
示例中的按钮使用了阴影特效,其它特效用法类似。
新建一个GUI工程,取名为SwitchButtonWidget ui界面为:
按钮命名格式为“btn行号列号”,并且将这些QPushButton提升为MyButton,MyButton我们后面再定义。
使用这样的命名规则是为了当按下方向键(上下左右键)方便将焦点框切换到对应的按钮上
右键,修改样式表,修改窗口的样式为:
QPushButton {
border-radius: 4px;
border: none;
width: 35px;
height: 35px;
color: rgb(180, 0, 0);
font: bold 25px;
}
QPushButton:hover {
background: rgb(85, 85, 85);
}
QPushButton:pressed{
background: rgb(80, 80, 80);
}
QWidget {
border: 1px solid "#222222";
background-color: "#222222";
}
switchbuttonwidget.h
#ifndef SWITCHBUTTONWIDGET_H
#define SWITCHBUTTONWIDGET_H
#include <QtWidgets>
#include "controltable.h"
namespace Ui {
class SwitchButtonWidget;
}
class SwitchButtonWidget : public QWidget
{
Q_OBJECT
public:
explicit SwitchButtonWidget(QWidget *parent = 0);
~SwitchButtonWidget();
protected:
//重写实现按键事件
void keyPressEvent(QKeyEvent* e);
private:
void createTable();
private:
Ui::SwitchButtonWidget *ui;
ControlTable* table;
};
#endif // SWITCHBUTTONWIDGET_H
switchbuttonwidget.cpp
#include "switchbuttonwidget.h"
#include "ui_switchbuttonwidget.h"
SwitchButtonWidget::SwitchButtonWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SwitchButtonWidget)
{
ui->setupUi(this);
createTable();
}
SwitchButtonWidget::~SwitchButtonWidget()
{
delete ui;
}
void SwitchButtonWidget::keyPressEvent(QKeyEvent *e)
{
int k = e->key();
switch (k)
{
case Qt::Key_Up:
{
table->toUp();
break;
}
case Qt::Key_Down:
{
table->toDown();
break;
}
case Qt::Key_Left:
{
table->toLeft();
break;
}
case Qt::Key_Right:
{
table->toRight();
break;
}
}
}
void SwitchButtonWidget::createTable()
{
QList<ControlList> tmpTable;
ControlList row0;
ControlList row1;
ControlList row2;
ControlList row3;
row0 << ui->btn_0_0 << ui->btn_0_1 << ui->btn_0_2;
row1 << ui->btn_1_0 << ui->btn_1_1 << ui->btn_1_2;
row2 << ui->btn_2_0 << ui->btn_2_1 << ui->btn_2_2;
row3 << ui->btn_3_0 << ui->btn_3_1 << ui->btn_3_2;
tmpTable << row0 << row1 << row2 << row3;
table = new ControlTable(this);
table->setTable(tmpTable);
}
下面是controltable的声明,具体思路已经写在注释里了,这里就不多解释了
controltable.h
#ifndef CONTROLTABLE_H
#define CONTROLTABLE_H
#include <QtWidgets>
typedef QList<QWidget*> ControlList;
class ControlTable: public QObject
{
Q_OBJECT
public:
//注意parent不能为空
ControlTable(QWidget *parent);
void setTable(const QList<ControlList>& t);
//按钮焦点上移
void toUp();
//按钮焦点下移
void toDown();
//按钮焦点左移
void toLeft();
//按钮焦点右移
void toRight();
signals:
void controlSwitched(QWidget* oldControl, QWidget* newControl);
private:
//返回按钮表格第r行所有按钮列表
ControlList rowControls(int r);
//返回按钮表格第c列所有按钮列表
ControlList colControls(int c);
//获取控件行号
int row(QWidget* control);
//获取控件列号
int col(QWidget* control);
//判断行列是否都有效
bool isValid(int r, int c);
//按钮表格最大行数
int rowCount();
//选中btn
void selectControl(QWidget* control);
//返回btnList第index索引位置的后一个按钮
//如果btnList只有一个按钮,则返回按钮本身
QWidget* nextControl(const ControlList& controlList, int index);
//返回btnList第index索引位置的前一个按钮
//如果btnList只有一个按钮,则返回按钮本身
QWidget* preControl(const ControlList& controlList, int index);
//设置特效颜色阴影边框
void setFrame(QWidget *control, const QColor& color);
//取消特效颜色边框
void unSetFrame(QWidget* control);
private:
QWidget* widget;
QWidget* currentContrl; //记录当前焦点所在按钮
QList<ControlList> table;//按钮表格
const char* rowid;
const char* colid;
};
#endif // CONTROLTABLE_H
controltable.cpp
#include "controltable.h"
ControlTable::ControlTable(QWidget *parent):
QObject(parent),rowid("table_row"),colid("table_col")
{
Q_ASSERT(parent);
currentContrl = 0;
widget = parent;
}
/*
按钮表格图解,在阅读代码时,可参考此图解
btn代表按钮 null代表空
-----------------------
col1 col2 col3
row1 btn btn null
row2 null btn null
row3 btn btn btn
-----------------------
SwitchButtonWidget中的成员变量“table”是所有按钮指针和空指针的集合
例如table的第一行列表元素为[btn,btn,null]
在ui界面中,每个按钮的名称都采用 btn_行索引_列索引 的格式命名
这样取名只是为了直接能用ui指定行列
如果不想按照此命名规则排列,可在MyButton中添加行列成员,可达到相同效果
*/
void ControlTable::setTable(const QList<ControlList> &t)
{
bool isSetDefaultControl = false;
table = t;
for (int i = 0; i < rowCount(); ++i)
{
ControlList controList =table.at(i);
for (int j = 0; j < controList.size(); ++j)
{
if (table[i][j])
{
table[i][j]->setProperty(rowid, i);
table[i][j]->setProperty(colid, j);
if (!isSetDefaultControl)
{
selectControl(table[i][j]);
isSetDefaultControl = true;
}
}
}
}
}
void ControlTable::toUp()
{
QWidget* control = currentContrl;
int curRow = row(control);
int curCol = col(control);
if (isValid(curRow, curCol))
{
control = preControl(colControls(curCol), curRow);
selectControl(control);
}
}
void ControlTable::toDown()
{
QWidget* control = currentContrl;
int curRow = row(control);
int curCol = col(control);
if (isValid(curRow, curCol))
{
control = nextControl(colControls(curCol), curRow);
selectControl(control);
}
}
void ControlTable::toLeft()
{
QWidget* control = currentContrl;
int curRow = row(control);
int curCol = col(control);
if (isValid(curRow, curCol))
{
control = preControl(rowControls(curRow), curCol);
selectControl(control);
}
}
void ControlTable::toRight()
{
QWidget* control = currentContrl;
int curRow = row(control);
int curCol = col(control);
if (isValid(curRow, curCol))
{
control = nextControl(rowControls(curRow), curCol);
selectControl(control);
}
}
ControlList ControlTable::rowControls(int r)
{
return table[r];
}
ControlList ControlTable::colControls(int c)
{
ControlList ret;
for (int i = 0; i < rowCount(); ++i)
{
ret.append(table[i][c]);
}
return ret;
}
int ControlTable::row(QWidget *control)
{
if (!control)
{
return -1;
}
if (!control->property(rowid).isValid())
{
return -1;
}
return control->property(rowid).toInt();
}
int ControlTable::col(QWidget *control)
{
if (!control)
{
return -1;
}
if (!control->property(colid).isValid())
{
return -1;
}
return control->property(colid).toInt();
}
bool ControlTable::isValid(int r, int c)
{
return r != -1 && c != -1;
}
int ControlTable::rowCount()
{
return table.size();
}
void ControlTable::selectControl(QWidget *control)
{
QWidget* old= currentContrl;
if (old)
{
unSetFrame(old);
}
setFrame(control, Qt::red);
currentContrl = control;
emit controlSwitched(old, control);
}
QWidget *ControlTable::nextControl(const ControlList &controlList, int index)
{
QWidget * ret = 0;
int tmp = 0;
int size = controlList.size();
for (int i = index+1; i <= size+index; ++i)
{
tmp = i % size;
if (controlList.at(tmp) != 0)
{
ret = controlList.at(tmp);
break;
}
}
return ret;
}
QWidget *ControlTable::preControl(const ControlList &controlList, int index)
{
QWidget* ret = 0;
int tmp = 0;
int size = controlList.size();
for (int i = index-1; i >= index-size; --i)
{
if (i < 0)
{
tmp = i + size;
}
else
{
tmp = i;
}
if (controlList.at(tmp) != 0)
{
ret = controlList.at(tmp);
break;
}
}
return ret;
}
void ControlTable::setFrame(QWidget* control, const QColor &color)
{
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect ();
effect->setBlurRadius(50); //设置模糊半径为50px
effect->setColor(color); //设置阴影颜色
effect->setOffset(0); //设置水平和垂直方向的偏移量都为0
control->setGraphicsEffect(effect); //为控件应用特效
}
void ControlTable::unSetFrame(QWidget* control)
{
control->setGraphicsEffect(0);
}
为了让按钮响应按键操作并统一管理显示特效框,我们自定义MyButton类,继承自QPushButton
mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QPushButton>
class MyButton : public QPushButton
{
Q_OBJECT
public:
MyButton(QWidget* parent = 0);
protected:
void keyPressEvent(QKeyEvent* e);
};
#endif // MYBUTTON_H
mybutton.cpp
#include <QKeyEvent>
#include "mybutton.h"
MyButton::MyButton(QWidget *parent):
QPushButton(parent)
{
}
void MyButton::keyPressEvent(QKeyEvent *e)
{
int k = e->key();
if ( k == Qt::Key_Up
|| k == Qt::Key_Down
|| k == Qt::Key_Left
|| k == Qt::Key_Right)
{
e->ignore();//让这些事件继续上传给父窗口,在本例中指SwitchButtonWidget
}
else
{
e->accept();//停止其它事件向上传播
}
}
OK,到此,所有的代码全部编写完毕,运行程序,不出意外的话将会得到文章开头gif图片的按钮特效程序,使用方向键控制焦点框移动,是不是很酷啊。
好了,关于窗口特效的分享就到这里啦,其它特效使用方法和阴影特效非常类似,小豆君就不在这里一一列举了,最后,喜欢的朋友不要忘记点赞哦,您的支持就是对我最大的鼓励^_^
最近帮着几个小伙伴修改他们的项目代码时发现,他们对C++的语法和特性只是知其然而不知其所以然,所以这里给大家推荐一本可以解决这类问题的经典书《C++编程思想》,我想它的大名就不用我多介绍了,虽然这本书比较老了,但是经典就是经典,想要提高的朋友可以点击下面链接购买
欢迎关注微信公众号-小豆君Qt分享
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。