一、前言
用惯了自带的messagebox,或者感觉效果不是很好看,或者有界面的特殊美观需求等等,那么就定制吧。
1.单选项提示框
2.双选项提示框
3.滚动选项提示框
4.密码提示框
5.多组合选项提示框1
6.多组合选项提示框2
7.多组合选项提示框3
二、环境
qt57
window10
三、正文
画布多少,直接说核心部分
1.单选项提示框
背景是哥图片,可以自定义为任何不规则图片,然后传输想要显示的文本通过槽函数发送信号,新建一个widget用于显示,打开之后再初始化中加入定时器自动关闭界面,避免长时间没操作。
messagebox1.h
protected:
void paintEvent(QPaintEvent *paintevent);
private slots:
void on_pushButton_clicked();
void receivetext(QString res);
private:
Ui::MessageBox1 *ui;
QPixmap pic;
messagebox1.cpp
#include "messagebox1.h"
#include "ui_messagebox1.h"
MessageBox1::MessageBox1(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessageBox1)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);//设置一直保持在顶端,不可切换其他界面,除非被新界面带此属性覆盖
this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明
pic.load(tr(":/PIC/background/message1.png"));//设置背景
//倒计时关闭界面
for(int i=0;i<10;i++)
QTimer::singleShot(i*1000,this,[=](){ui->pushButton->setText(QString("确认(%1)").arg(9-i));});
QTimer::singleShot(10*1000,this,[=](){this->close();});
ui->pushButton->setFocus();//设置聚焦,作用你懂的
}
MessageBox1::~MessageBox1()
{
delete ui;
}
void MessageBox1::paintEvent(QPaintEvent *paintevent)
{
paintevent->ignore();
QPainter painter(this);
painter.drawPixmap(0, 0, pic);//绘制图像
}
void MessageBox1::on_pushButton_clicked()
{
this->close();
}
void MessageBox1::receivetext(QString res)
{
ui->label->setText(res);
}
ui中加入button和label即可
主函数调用
MessageBox1 * box = new MessageBox1();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
emit sendtext("提示!\r\n这是一个测试消息!");
2.双选项提示框
参考上面的,核心部分就是观测exec返回值0或1,代表是否点击确认,还是点击取消,还是强制或者自动关闭的提示框界面, 默认确认为1,其余为0
在初始化里加入this->reject();//exec返回值为0
在确认按键点击之后加入this->accept();//exec返回值为1
主函数调用
MessageBox2 * box = new MessageBox2();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
emit sendtext("提示!\r\n这是一个测试消息!");
qDebug()<<box->exec();
这里的判断box->exec()返回值就和正常的messagebox使用判断一样了
3.滚动选项提示框
主要就是把第2个的label换成了一个自定义控件,自定义控件的功能是滚动选择,然后绑定一些槽配套使用再传递给主函数即可
messagebox3.h
#ifndef MESSAGEBOX3_H
#define MESSAGEBOX3_H
#include <QDialog>
#include "common.h"
#include "CustomWidget/Slidingselector/slidingselector.h"
namespace Ui {
class MessageBox3;
}
class MessageBox3 : public QDialog
{
Q_OBJECT
public:
explicit MessageBox3(QWidget *parent = 0);
~MessageBox3();
protected:
void paintEvent(QPaintEvent *paintevent);
signals:
void sendchoose(QString);
private slots:
void on_btn_sure_clicked();
void on_btn_false_clicked();
void receivetext(QStringList res,int num);
private:
Ui::MessageBox3 *ui;
QPixmap pic;
QStringList m_strlist;//所有滚动项列表
SlidingSelector *roll;
QString choose;
};
#endif // MESSAGEBOX1_H
messagebox3.cpp
#include "messagebox3.h"
#include "ui_messagebox3.h"
MessageBox3::MessageBox3(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessageBox3)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);//设置一直保持在顶端,不可切换其他界面,除非被新界面带此属性覆盖
this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明
pic.load(tr(":/PIC/background/message2.png"));//设置背景
roll=new SlidingSelector;
roll->show();
ui->horizontalLayout->addWidget(roll);
roll->setMode_Hor_Ver(Vertical);//设置垂直模式
roll->setMode_Num_Str(String);//设置字符串模式
connect(roll,&SlidingSelector::currentStrChanged,[=](QString aaa){
choose=aaa;
//qDebug()<<aaa;
});
//倒计时关闭界面
for(int i=0;i<30;i++)
QTimer::singleShot(i*1000,this,[=](){ui->btn_false->setText(QString("取消(%1)").arg(29-i));});
QTimer::singleShot(30*1000,this,[=](){this->close();});
ui->btn_false->setFocus();//设置聚焦,作用你懂的
}
MessageBox3::~MessageBox3()
{
delete ui;
}
void MessageBox3::paintEvent(QPaintEvent *paintevent)
{
paintevent->ignore();
QPainter painter(this);
painter.drawPixmap(0, 0, pic);//绘制图像
}
void MessageBox3::on_btn_sure_clicked()
{
emit sendchoose(choose);
this->close();
}
void MessageBox3::on_btn_false_clicked()
{
this->close();
}
void MessageBox3::receivetext(QStringList res,int num)
{
m_strlist=res;//m_strlist备用
roll->setRange(res);
choose=res.at(num);//设置当前值,避免直接不改变直接确认返回值无效
roll->setCurrentStr(choose);
//qDebug()<<res;
}
slidingselector自定义控件下载
ui中将label改为horizontalLayout即可
主函数调用
MessageBox3 * box = new MessageBox3();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QStringList,int)),box,SLOT(receivetext(QStringList,int)));
QStringList list;
list<<"str撒撒发生111"<<"str撒撒发生22"<<"str撒撒发生33"<<"str撒撒发生44"<<"str撒撒发生55"<<"str撒撒发生66";
emit sendtext(list,2);
connect(box,&MessageBox3::sendchoose,[=](QString res){
qDebug()<<res;
});
滚动自定义控件简介,可设置为横向或者竖着刷新模式,可设置为数字或者字符串刷新模式,数字模式传入范围值即可,字符串模式传入参数QSteingList即可,可以把目前列表中的值传入让其显示。所有部分颜色均可更改
4.密码提示框
入口函数:
MessageBox4 * box = new MessageBox4();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QString)),box,SLOT(receivetext(QString)));
emit sendtext("sy1234");
qDebug()<<box->exec();
核心代码
//振动效果
void MessageBox4::widgetShake(QWidget *pWidget, int nRange)
{
int nX = pWidget->x();
int nY = pWidget->y();
QPropertyAnimation *pAnimation = new QPropertyAnimation(pWidget,"geometry");
pAnimation->setEasingCurve(QEasingCurve::InOutSine);
pAnimation->setDuration(300);
pAnimation->setStartValue(QRect(QPoint(nX,nY),pWidget->size()));
int nShakeCount = 20; //抖动次数
double nStep = 1.0/nShakeCount;
for(int i = 1; i < nShakeCount; i++){
nRange = i&1 ? -nRange : nRange;
pAnimation->setKeyValueAt(nStep*i,QRect(QPoint(nX + nRange,nY),pWidget->size()));
}
pAnimation->setEndValue(QRect(QPoint(nX,nY),pWidget->size()));
pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
//打开屏幕键盘
void MessageBox4::on_pushButton_keyboard_clicked()
{
//The code from david!!!
PVOID OldValue;
BOOL bRet = Wow64DisableWow64FsRedirection (&OldValue);
QString csProcess="C:\\Windows\\System32\\osk.exe";
QString params="";
ShellExecute(NULL, L"open", (LPCWSTR)csProcess.utf16(), (LPCWSTR)params.utf16(), NULL, SW_SHOWNORMAL);
if ( bRet )
{
Wow64RevertWow64FsRedirection(OldValue);
}
ui->lineEdit->setFocus();
}
void MessageBox4::closeEvent(QCloseEvent *event)
{
HWND appWnd;
appWnd = ::FindWindow(L"OSKMainClass", NULL);
if (appWnd){
SendMessage(appWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
//qDebug() << "closeKeyboard succeed";
}
else{
//qDebug() << "closeKeyboard failed";
}
}
使用原理。传出进入密码,点击确定之后会判断面膜是否正确,若密码正确,则返回exec值为1,若不正确,会提示密码错误
演示效果 :
5.多组合选项提示框1
入口函数:
MessageBox5 * box = new MessageBox5();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QStringList,QStringList)),box,SLOT(receivetext(QStringList,QStringList)));
QStringList list1,list2;
list1<<"str撒撒发生111"<<"str撒撒发生22"<<"str撒撒发生33"<<"str撒撒发生44"<<"str撒撒发生55"<<"str撒撒发生66";
list2<<"aa"<<"bb";
emit sendtext(list2,list1);
connect(box,&MessageBox5::sendchoose,[=](QString res1,QString res2,QDate t1,QDate t2){
qDebug()<<res1<<res2<<t1<<t2;
});
核心代码
MessageBox5::MessageBox5(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessageBox5)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);//设置一直保持在顶端,不可切换其他界面,除非被新界面带此属性覆盖
this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明
pic.load(tr(":/PIC/background/message3.png"));//设置背景
ui->stackedWidget->setCurrentIndex(0);//初始在第一个选项界面选择
QPushButton *groupbtn[4]={ui->btn_sure_8,ui->btn_sure_9,ui->btn_sure_10,ui->btn_sure_11};
for(int i=0;i<4;i++)//切换选项按键
connect(groupbtn[i],&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(i);
groupbtn[i]->setChecked(true);
});
//设备属性选择
roll1=new SlidingSelector;
roll1->show();
ui->horizontalLayout->addWidget(roll1);
roll1->setMode_Hor_Ver(Vertical);//设置垂直模式
roll1->setMode_Num_Str(String);//设置字符串模式
roll1->setMode_One_Ext(OneList);//设置单列模式
connect(roll1,&SlidingSelector::currentStrChanged,[=](QString aaa){
choose1=aaa;
ui->btn_sure_8->setText(choose1);
//qDebug()<<aaa;
});
//部件属性选择
roll2=new SlidingSelector;
roll2->show();
ui->horizontalLayout_2->addWidget(roll2);
roll2->setMode_Hor_Ver(Vertical);//设置垂直模式
roll2->setMode_Num_Str(String);//设置字符串模式
roll2->setMode_One_Ext(OneList);//设置单列模式
connect(roll2,&SlidingSelector::currentStrChanged,[=](QString aaa){
choose2=aaa;
ui->btn_sure_9->setText(choose2);
//qDebug()<<aaa;
});
//起始时间选择
for(int i=0;i<3;i++){
rolltime1[i]=new SlidingSelector;
rolltime1[i]->show();
rolltime1[i]->setMinimumSize(100,250);//设置控件的最小尺寸
ui->gridLayout->addWidget(rolltime1[i],0,i,1,1,Qt::AlignHCenter|Qt::AlignVCenter);
rolltime1[i]->setMode_Hor_Ver(Vertical);//设置垂直模式
rolltime1[i]->setMode_Num_Str(Number);//设置字符串模式
rolltime1[i]->setMode_One_Ext(OneList);//设置单列模式
connect(rolltime1[i],&SlidingSelector::currentValueChanged,[=](int aaa){
if(i==0){
QDate tt;
tt.setDate(aaa,time1.month(),1);
rolltime1[2]->setRange(1,tt.daysInMonth());
if(time1.day()>tt.daysInMonth())
time1.setDate(aaa,time1.month(),tt.daysInMonth());
else
time1.setDate(aaa,time1.month(),time1.day());
rolltime1[2]->setCurrentNum(time1.day());
}
else if(i==1){
QDate tt;
tt.setDate(time1.year(),aaa,1);
rolltime1[2]->setRange(1,tt.daysInMonth());
if(time1.day()>tt.daysInMonth())
time1.setDate(time1.year(),aaa,tt.daysInMonth());
else
time1.setDate(time1.year(),aaa,time1.day());
rolltime1[2]->setCurrentNum(time1.day());
}
else{
time1.setDate(time1.year(),time1.month(),aaa);
}
//qDebug()<<aaa;
ui->btn_sure_10->setText(time1.toString("yyyy-MM-dd"));//刷新显示界面
});
}
//截止时间选择
for(int i=0;i<3;i++){
rolltime2[i]=new SlidingSelector;
rolltime2[i]->show();
rolltime2[i]->setMinimumSize(100,250);//设置控件的最小尺寸
ui->gridLayout_2->addWidget(rolltime2[i],0,i,1,1,Qt::AlignHCenter|Qt::AlignVCenter);
rolltime2[i]->setMode_Hor_Ver(Vertical);//设置垂直模式
rolltime2[i]->setMode_Num_Str(Number);//设置字符串模式
rolltime2[i]->setMode_One_Ext(OneList);//设置单列模式
connect(rolltime2[i],&SlidingSelector::currentValueChanged,[=](int aaa){
if(i==0){
QDate tt;
tt.setDate(aaa,time2.month(),1);
rolltime2[2]->setRange(1,tt.daysInMonth());
if(time2.day()>tt.daysInMonth())
time2.setDate(aaa,time2.month(),tt.daysInMonth());
else
time2.setDate(aaa,time2.month(),time2.day());
rolltime2[2]->setCurrentNum(time2.day());
}
else if(i==1){
QDate tt;
tt.setDate(time2.year(),aaa,1);
rolltime2[2]->setRange(1,tt.daysInMonth());
if(time2.day()>tt.daysInMonth())
time2.setDate(time2.year(),aaa,tt.daysInMonth());
else
time2.setDate(time2.year(),aaa,time2.day());
rolltime2[2]->setCurrentNum(time2.day());
}
else{
time2.setDate(time2.year(),time2.month(),aaa);
}
//qDebug()<<aaa;
ui->btn_sure_11->setText(time2.toString("yyyy-MM-dd"));//刷新显示界面
});
}
//倒计时关闭界面
for(int i=0;i<60;i++)
QTimer::singleShot(i*1000,this,[=](){ui->btn_false->setText(QString("取消(%1)").arg(59-i));});
QTimer::singleShot(60*1000,this,[=](){this->close();});
ui->btn_false->setFocus();//设置聚焦,作用你懂的
}
MessageBox5::~MessageBox5()
{
delete ui;
}
//重绘背景
void MessageBox5::paintEvent(QPaintEvent *paintevent)
{
paintevent->ignore();
QPainter painter(this);
painter.drawPixmap(0, 0, pic);//绘制图像
}
//确认按键
void MessageBox5::on_btn_sure_clicked()
{
emit sendchoose(choose1,choose2,time1,time2);
this->close();
}
//取消按键
void MessageBox5::on_btn_false_clicked()
{
this->close();
}
//传入参数范围
void MessageBox5::receivetext(QStringList res1,QStringList res2)
{
m_strlist1=res1;//m_strlist1备用
roll1->setRange(res1);
choose1=res1.at(0);//设置当前值,避免直接不改变直接确认返回值无效
roll1->setCurrentStr(choose1);
ui->btn_sure_8->setText(choose1);//刷新显示界面
//qDebug()<<res1;
m_strlist2=res2;//m_strlist2备用
roll2->setRange(res2);
choose2=res2.at(0);//设置当前值,避免直接不改变直接确认返回值无效
roll2->setCurrentStr(choose2);
ui->btn_sure_9->setText(choose2);//刷新显示界面
//qDebug()<<res2;
time1=QDate::currentDate().addMonths(-1);//起始时间设置为上个月
rolltime1[0]->setRange(1970,2070);
rolltime1[1]->setRange(1,12);
rolltime1[2]->setRange(1,time1.daysInMonth());
rolltime1[0]->setCurrentNum(time1.year());
rolltime1[1]->setCurrentNum(time1.month());
rolltime1[2]->setCurrentNum(time1.day());
ui->btn_sure_10->setText(time1.toString("yyyy-MM-dd"));//刷新显示界面
//qDebug()<<time1.daysInMonth()<<time1.year()<<time1.month()<<time1.day();
time2=QDate::currentDate();//截止时间设置为今天
rolltime2[0]->setRange(1970,2070);
rolltime2[1]->setRange(1,12);
rolltime2[2]->setRange(1,time2.daysInMonth());
rolltime2[0]->setCurrentNum(time2.year());
rolltime2[1]->setCurrentNum(time2.month());
rolltime2[2]->setCurrentNum(time2.day());
ui->btn_sure_11->setText(time2.toString("yyyy-MM-dd"));//刷新显示界面
//qDebug()<<time2.daysInMonth()<<time2.year()<<time2.month()<<time2.day();
}
原理:就是采用多个滑动选择器组合,配合一些逻辑,时间的改变逻辑占用一些代码行,在年份和月份改变时,日期对应的上限要跟着改变
演示效果:
6.多组合选项提示框2
入口函数
MessageBox6 * box = new MessageBox6();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QStringList)),box,SLOT(receivetext(QStringList)));
QStringList list1;
list1<<"str撒生111"<<"str撒生22"<<"str发生33"<<"st撒发生44"<<"str发生55"<<"s撒发生66";
emit sendtext(list1);
connect(box,&MessageBox6::sendchoose,[=](QString res1,QDate t1,QDate t2){
qDebug()<<res1<<t1<<t2;
});
核心代码同上,删除一项即可
7.多组合选项提示框3
入口函数
MessageBox7 * box = new MessageBox7();
box->show();
box->setAttribute(Qt::WA_DeleteOnClose);//若是关闭界面,则彻底释放资源
connect(this,SIGNAL(sendtext(QString,QString,QString,QString,QStringList)),box,SLOT(receivetext(QString,QString,QString,QString,QStringList)));
QStringList list2;
list2<<"aa"<<"bb";
//emit sendtext("","","","",list2);
emit sendtext("bb","22","333","4444",list2);
connect(box,&MessageBox7::sendtext,[=](QString res1,QString res2,QString res3,QString res4){
qDebug()<<res1<<res2<<res3<<res4;
});
核心代码:
#include "messagebox7.h"
#include "ui_messagebox7.h"
MessageBox7::MessageBox7(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessageBox7)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);//设置一直保持在顶端,不可切换其他界面,除非被新界面带此属性覆盖
this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明
pic.load(tr(":/PIC/background/message5.png"));//设置背景
//倒计时关闭界面
for(int i=0;i<60;i++)
QTimer::singleShot(i*1000,this,[=](){ui->btn_false->setText(QString("取消(%1)").arg(59-i));});
QTimer::singleShot(60*1000,this,[=](){this->close();});
ui->btn_false->setFocus();//设置聚焦,作用你懂的
}
MessageBox7::~MessageBox7()
{
delete ui;
}
void MessageBox7::paintEvent(QPaintEvent *paintevent)
{
paintevent->ignore();
QPainter painter(this);
painter.drawPixmap(0, 0, pic);//绘制图像
}
void MessageBox7::on_btn_sure_clicked()
{
if(ui->lineEdit_1->text().isEmpty()){
ui->label_5->setText("不能为空");
widgetShake(ui->label_5,5);
ui->lineEdit_1->setFocus();
return;
}
else if(m_hascode.contains(ui->lineEdit_1->text())){
ui->label_5->setText("账号存在");
widgetShake(ui->label_5,5);
ui->lineEdit_1->setFocus();
return;
}
else{
ui->label_5->setText("");
}
if(ui->lineEdit_2->text().isEmpty()){
ui->label_6->setText("不能为空");
widgetShake(ui->label_6,5);
ui->lineEdit_2->setFocus();
return;
}
else{
ui->label_6->setText("");
}
emit sendtext(ui->lineEdit_1->text(),ui->lineEdit_2->text(),ui->lineEdit_3->text(),ui->lineEdit_4->text());
this->close();
}
void MessageBox7::on_btn_false_clicked()
{
this->close();
}
void MessageBox7::receivetext(QString res1,QString res2,QString res3,QString res4,QStringList has)
{
ui->lineEdit_1->setText(res1);
ui->lineEdit_2->setText(res2);
ui->lineEdit_3->setText(res3);
ui->lineEdit_4->setText(res4);
m_hascode=has;
m_hascode.removeAt(m_hascode.indexOf(res1));
qDebug()<<m_hascode;
if(res1.isEmpty()&&res2.isEmpty()&&res3.isEmpty()&&res4.isEmpty())
ui->lab_title->setText("用户增加");
else
ui->lab_title->setText("用户修改");
}
//振动效果
void MessageBox7::widgetShake(QWidget *pWidget, int nRange)
{
int nX = pWidget->x();
int nY = pWidget->y();
QPropertyAnimation *pAnimation = new QPropertyAnimation(pWidget,"geometry");
pAnimation->setEasingCurve(QEasingCurve::InOutSine);
pAnimation->setDuration(300);
pAnimation->setStartValue(QRect(QPoint(nX,nY),pWidget->size()));
int nShakeCount = 20; //抖动次数
double nStep = 1.0/nShakeCount;
for(int i = 1; i < nShakeCount; i++){
nRange = i&1 ? -nRange : nRange;
pAnimation->setKeyValueAt(nStep*i,QRect(QPoint(nX + nRange,nY),pWidget->size()));
}
pAnimation->setEndValue(QRect(QPoint(nX,nY),pWidget->size()));
pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
//打开屏幕键盘
void MessageBox7::on_pushButton_keyboard_clicked()
{
//The code from david!!!
PVOID OldValue;
BOOL bRet = Wow64DisableWow64FsRedirection (&OldValue);
QString csProcess="C:\\Windows\\System32\\osk.exe";
QString params="";
ShellExecute(NULL, L"open", (LPCWSTR)csProcess.utf16(), (LPCWSTR)params.utf16(), NULL, SW_SHOWNORMAL);
if ( bRet )
{
Wow64RevertWow64FsRedirection(OldValue);
}
ui->lineEdit_1->setFocus();
}
void MessageBox7::closeEvent(QCloseEvent *event)
{
HWND appWnd;
appWnd = ::FindWindow(L"OSKMainClass", NULL);
if (appWnd){
SendMessage(appWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
//qDebug() << "closeKeyboard succeed";
}
else{
//qDebug() << "closeKeyboard failed";
}
}
原理:就是普通的lineedot输入,传入参数中有当前多有的账号信息判断,进入后删除本身的信息,确定判断是否存在当前存在的账号信息,进行振动提示,输入内容为空也振动提示,注意函数判断空时用isempty,isnull是无效i的
四、结语
世上无难事
暂时总结和使用这7个自定义的messagebox来。有需要的可以下载相关代码和背景图片资源,以及入口函数代码,下载点击这里