目录
1-三态按钮的实现
2-普通按钮的下拉框
3-复选框
4-单选按钮
5- 工具栏按钮
6-文本标签
7-编辑框
8-进度条
9-组合框
10-按钮对话框
实现目标:按钮的三种状态(按下-释放-进入)切换不同的相似图片达到良好的交互效果
实现思路:继承按钮类重写响应事件
实现继承按钮类如下
#include
#include
class XButton : public QPushButton
{
Q_OBJECT
public:
XButton(QWidget *p=nullptr);
void mousePressEvent(QMouseEvent *e); //处理按下事件
void mouseReleaseEvent(QMouseEvent *e);//处理释放事件
bool event(QEvent *e); //处理鼠标进入按钮事件
//
void setImage(QList& icons);//接受图片方法
private:
QList _icons;//储存图片路径集合
};
-------------------以上是头文件-----以下是源文件实现-------------------
#include "xbutton.h"
#include
#include
XButton::XButton(QWidget *p):QPushButton(p)
{
}
void XButton::mousePressEvent(QMouseEvent *e)
{
setIcon(_icons[2]);
QPushButton::mousePressEvent(e);//交给父类 继续执行按钮的其他 事件。不调用可能导致父类功能缺失
}
void XButton::mouseReleaseEvent(QMouseEvent *e)
{
setIcon(_icons[0]);
QPushButton::mouseReleaseEvent(e);//交给父类 继续执行按钮的其他 事件。不调用可能导致父类功能缺失
}
bool XButton::event(QEvent *e)
{
if(e->type()==QEvent::HoverEnter)//进来 入
{
setIcon(_icons[1]);
}else if(e->type()==QEvent::HoverLeave){//离开 出
setIcon(_icons[0]);
}
return QPushButton::event(e); //交给父类 继续执行按钮的其他 事件。不调用可能导致父类功能缺失
}
void XButton::setImage(QList &icons)
{
//Q_ASSERT(icons.size()==3);//断言
if(icons.size()!=3&& QMessageBox::question(this,"图片缺失3","检查图片参数是否3张,按钮暂不可用")
==(QMessageBox::Yes|QMessageBox::No))
{
//如果图片小于三警告终止程序,但是图片一般是自己放置完整故不作限制操作
}
else{
_icons=icons;
setIcon(_icons[0]);
}
}
main函数中运行如下
#include "widget.h"
#include
#include
#include "xbutton.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.move(200,50);
w.resize(1600,800);
w.show();
XButton *but_santai=new XButton(&w);
but_santai->setGeometry(0,240,200,60);
QList icons;
icons<setVisible(true);
but_santai->setImage(icons);
QObject::connect(but_santai,&XButton::clicked,[](){
qDebug()<<"but_santai";
});
}
其实不推荐这样写下拉框,后面学习才知道,本身按钮的下拉框适应就不是很好,不如用combox,就当学习了,一通万物通.
实现思路:1-创建一个菜单 2-创建一定数量的菜单项 (菜单项设置进菜单 菜单设置进按钮)
#include "widget.h"
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QMenu* menu=new QMenu(&w); //创建 菜单
QAction* action=new QAction();//创建 菜单项
action->setText("第一个菜单项");
action->setIcon(QIcon("mao.jpg"));
action->setCheckable(true);
menu->addAction(action);
QAction* action1=new QAction();//创建 菜单项
action1->setText("第2个菜单项");
action1->setIcon(QIcon("mao1.jpg"));
menu->addAction(action1);
QAction* action2=new QAction();//创建 菜单项
action2->setText("第3个菜单项");
action2->setIcon(QIcon("mao2.jpg"));
menu->addAction(action2);
button1->setMenu(menu);//将菜单加入按钮
QObject::connect(action,&QAction::triggered,[](bool check){ //信号槽 check为信号自带参数
qDebug()<<"action:"<
以下全部实现都写成方法直接声明调用即可。
重点:主要看一下复选框的三种状态 : 未选中(空白) 半选中(方形填充) 全选中(对勾填充)
#include
#include
#include
void init_(QWidget* w)
{
QCheckBox* cBox1=new QCheckBox(QString("100"),w);
cBox1->setGeometry(300,50,50,50);
cBox1->setVisible(true);
//cBox1->setTristate(true);//**打开 三种状态间0-1-2的切换
QObject::connect(cBox1,&QCheckBox::clicked,[](bool check){
qDebug()<<"clicked"<setCheckState(Qt::PartiallyChecked);//半选中状态 setCheckState
}
主要关注单选按钮的互斥表现,在一定容器内只可以有一个为选中状态
#include
#include
#include
#include
void init_radiobutton(QWidget* w)
{
#if 0 //0代表这段被包起来的代码不会执行 1表示可以执行
QRadioButton* r3=new QRadioButton(w);
r3->move(500,20);
r3->setText(QString("单选按钮1"));
r3->setVisible(true);
QRadioButton* r4=new QRadioButton(w);
r4->move(500,40);
r4->setText(QString("单选按钮2"));
r4->setVisible(true);
QButtonGroup* b_group=new QButtonGroup(w);//放入一个容器 展示
b_group->addButton(r3);
b_group->addButton(r4);
#endif
QRadioButton* r1=new QRadioButton(w);
r1->move(400,20);
r1->setText(QString("单选按钮1"));
r1->setVisible(true);
QRadioButton* r2=new QRadioButton(w);
r2->move(400,40);
r2->setText(QString("单选按钮2"));
r2->setVisible(true);
QObject::connect(r1,&QRadioButton::clicked,[](bool check){ //每次点击都会触发
qDebug()<<"r1 clicked"<move(400,60);
pushbutton->setText("选中的单选按钮");
pushbutton->setVisible(true);
QObject::connect(pushbutton,&QPushButton::clicked,[=](){
qDebug()<isChecked()<<" "<isChecked();
});
}
感觉很舒服的按钮下拉效果对比之前极其丝滑
(一个小插曲,比如设置属性的时候 有的是set~开头 有的add~开头。开始我有点分不清什么时候set 什么时候 add 后来总结的时候恍然大悟只要单个设置的基本都是set 只有这个属性可以添加多个东西的时候是add 开头。虽然很简单但是当时一直没想通哈哈 ^猪头^ )
/*
* 思路:创建菜单 创建菜单项 创建工具栏按钮
*/
#include
#include
#include
#include
void ini_toolbutton(QWidget* w)
{
//给工具栏按钮 设置一个菜单
QMenu* menu=new QMenu(w);
QAction* ac1=new QAction();
ac1->setText("工具栏1");
ac1->setIcon(QIcon("mao.jpg"));
ac1->setCheckable(true);//其实这一句可以不写,他的效果会让选中的带上一个持续的状态
menu->addAction(ac1);
QAction* ac2=new QAction();
ac2->setText("工具栏1");
ac2->setIcon(QIcon("mao1.jpg"));
ac2->setCheckable(true);
menu->addAction(ac2);
QObject::connect(ac1,&QAction::triggered,[](bool check){
qDebug()<<"ac1-triggered"<move(400,200);
toolbtn->resize(130,50);
toolbtn->setText("工具栏按钮");
//toolbtn->setIconSize(QSize(60,20));//图片设置大小
//toolbtn->setIcon(QIcon("mao.jpg"));
toolbtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//图片文字样式
toolbtn->setArrowType(Qt::LeftArrow);//设置箭头 可以看做是个图片也受setToolButtonStyle影响
toolbtn->setCheckable(true);//增加可选中状态 会使得按钮保持被选中状态
toolbtn->setVisible(true);
QObject::connect(toolbtn,&QToolButton::clicked,[](bool check){
qDebug()<<"toolbtn:"<setMenu(menu);//将菜单加入 工具栏按钮
//toolbtn->setPopupMode(QToolButton::InstantPopup);//设置点击立即打开菜单 2
toolbtn->setPopupMode(QToolButton::MenuButtonPopup);//设置点击箭头打开菜单 1 优先使用这个 优先使用这个 优先使用这个
//toolbtn->setPopupMode(QToolButton::DelayedPopup);//设置长点击打开菜单 0
//toolbtn->setDefaultAction(ac2);//设置 工具栏按钮 点击默认执行 哪一个菜单项 非要用尽量和 0 1 结合
}
文本标签更多的时候不是显示文字,而是显示图片,还有gif动图 * - *
#include
#include
#include //为了打开网址引入的头 也可以用label自带属性
#include //为了打开网址引入的头 也可以用label自带属性
#include //显示动画
void ini_lable(QWidget* w)
{
QLabel* lab1=new QLabel(w);
//lab1->setText("普通文本标签测试\n换行");
lab1->setText("360网址");//HTML 超链接
lab1->setAlignment(Qt::AlignHCenter);//水平对齐
lab1->setGeometry(400,300,300,60);
lab1->setVisible(true);
lab1->setOpenExternalLinks(true);//可以直接打开网址 超链接不需要引入头文件可以替换下面的0代码
#if 0
QObject::connect(lab1,&QLabel::linkHovered,[=](QString url){
qDebug()<setPixmap(QPixmap("mao.jpg"));//放入图片
lab2->setGeometry(400,450,200,200);
lab2->setScaledContents(true);//将图片自动进行缩放 防止lable过小显示不下图片
lab2->setVisible(true);
//lable标签显示gif动图
QLabel* lab3=new QLabel(w);
lab3->setGeometry(200,450,180,180);
QMovie* movie=new QMovie("gif.gif");//指针写法出了方法可以继续使用
movie->setCacheMode(QMovie::CacheAll);//缓存流畅
lab3->setMovie(movie);
movie->start();//开始动画 一定要记得写
lab3->setVisible(true);
}
区区编辑框,内容很多,尤其是 校验 和 自动填充
/*
* 1-自动补全挺不错的一个功能
* 2-校验功能 尤其是正则表达式 太好用了,就是写一个表达式很漫长。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
void ini_edit(QWidget *w)
{
QLineEdit* edit=new QLineEdit(w);
edit->setGeometry(600,50,200,50);
//edit->setPlaceholderText("请输入密码");//占位符 提示用户输入信息
edit->setVisible(true);
//edit->setEchoMode(QLineEdit::Password);//输入显示模式
//edit->setReadOnly(true);//只读属性
//edit->setMaxLength(5);//字符最大长度
//自动补全内容 4个步骤
QStringList list;
list<<"2022"<<"2023"<<"2024"<<"2025";//创建列表 步骤0
list<<"3033"<<"3034"<<"a1111"<<"A1111";
QStringListModel* stringModel=new QStringListModel();
stringModel->setStringList(list); //将列表放入list模型中 步骤1 (提供模型)
QCompleter* completer=new QCompleter();
//completer->setCompletionMode(QCompleter::PopupCompletion);//默认就是此模式可以不写
completer->setFilterMode(Qt::MatchContains);//默认的字符位要对应也挺好用,改成这个属性更全面
//①-②使用时 模型要是有序排列最好升|大小写敏感要统一否则设置的搜索模式无效
//①-completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);//改变搜索模式为二分法
completer->setCaseSensitivity(Qt::CaseInsensitive);//②大小写不敏感
completer->setModel(stringModel); //将list模型放入completer中 步骤2 (根据模型完成更多的功能)
edit->setCompleter(completer); //设置到edit中 步骤3
//手动补全:比如有的控件没有此功能
completer->setCompletionPrefix("a");//根据字符前缀进行匹配 手动补全
//如果想筛选出A a 大小写不敏感 要在completer->setModel();设置模型之前设置好,不然会导致前缀筛选无效
int i=0;
for(;completer->setCurrentRow(i);i++)//从第一行开始(将当前行设置为指定行) 设置成功返回true
{
qDebug()<<"i:"<currentCompletion() //返回前缀为a的内容 (大小写设置不敏感)
<<"row:"<currentRow() // 序号(当前行)
<<"index:"<currentIndex().row()//模型中的行号
<<"前缀数:"<completionCount();//前缀为a 或 A的总条数(大小写设置不敏感)
}
#if 0
//数据校验-壹
//结合edit->hasAcceptableInput();符合规范返回true
QIntValidator* intval=new QIntValidator();
intval->setRange(2022,2099);//范围2022-2099 不可以阻止用户在界面输入规定之外的字符
QDoubleValidator* doubleval=new QDoubleValidator();
doubleval->setRange(3.00,3.99,2);//范围3-3.99 小数最多2位 不可以阻止用户在界面输入规定之外的字符
QRegExpValidator* regval=new QRegExpValidator();
QRegExp re("20((2[2-9])|([3-9][0-9]))");//正则表达式 可以阻止用户在界面输入规定之外的字符
regval->setRegExp(re); //202[2-9] | 20[3-9][0-9] 范围2022-2099之间
edit->setValidator(regval);
#endif
#if 0
//数据校验-零
//输入数字0-9
//edit->setInputMask("000.000.000.000;_");//输入规则___.___.___.___分号后面只做占位
///permitted的这两个信号 editingFinished returnPressed 可以正常触发
//输入16进制
edit->setInputMask("HH.HH.HH.HH;_");//不加分号后面的占位默认是 空白
///required的这两个信号 editingFinished returnPressed 要在校验完毕后才会触发,不符合规则就不会触发
//大写的H required: 按_下滑键不会移动光标
//edit->setInputMask("hh.hh.hh.hh;_");//不加分号后面的占位默认是 空白
//小写的h permitted: 按_下滑键可以移动光标
//填充日期如下
//edit->setInputMask("0000年00月00日;_");//除规定有意义字符,其他填充字符默认保留
// > < ! 的使用
//edit->setInputMask(">AA后面的转换为大写 <后面的转换为小写 !关闭转换
//转义字符的特殊使用:第一个字母任意A-Z 第二个字符只能为 A
//edit->setInputMask("A\\A");// "\\"双反斜线才是setInputMask规定里的转义字符
//c++: A\\A => A \ A
//Qt:setInputMask: A \ A => A \A
#endif
//signal
QObject::connect(edit,&QLineEdit::textChanged,[=](QString text){//输入和代码输入都会触发
qDebug()<<"textChanged:"<text();
});
QObject::connect(edit,&QLineEdit::returnPressed,[=](){ //回车或return就会触发
qDebug()<<"returnPressed:"<text();
});
QPushButton* btn=new QPushButton(w);
btn->setGeometry(600,100,150,50);
btn->setText(QString("检测edit"));
btn->setVisible(true);
QObject::connect(btn,&QPushButton::clicked,[=](){
qDebug()<text()
<<"是否符合规范"<hasAcceptableInput();//bool 输入的是否符合规范
});
}
注意一下垂直-水平属性
#include
#include
void ini_progressBar(QWidget* w)
{
QProgressBar* progressbar=new QProgressBar(w);
progressbar->setGeometry(600,200,300,50);
progressbar->setRange(0,100);
//progressbar->setRange(0,0);//滚动动画 当不知道大小时可以先设置成这个
progressbar->setValue(50);
//progressbar->setFormat("百分比:%p% 总共的:%m");设置末端数字显示
//progressbar->setOrientation(Qt::Vertical);//垂直方向(将不会显示文字信息)
//progressbar->setInvertedAppearance(true);//进度条方向倒过来显示
progressbar->setVisible(true);
}
关注他的信号和数据填充
#include
#include
#include
void ini_combobox(QWidget* w)
{
//联动操作
//思路1:一个主的 控制 两个副的visible显示 (这样可以自动保留用户上一次的选择项)
//思路2:一个主的 控制 一个副的 选中不同的一级目录时给二级目录填充所需要的数据 (先清空后填充)
QStringList subject;
subject<<"c"<<"c++";
QStringList subject_c;
subject_c<<"c1"<<"c2"<<"c3";
QStringList subject_cpp;
subject_cpp<<"c++1"<<"c++2"<<"c++3";
QComboBox* com1=new QComboBox(w);//一级控制
com1->setGeometry(600,500,100,50);
com1->addItems(subject);
com1->setVisible(true);
QComboBox* com1_1=new QComboBox(w);//二级控制
com1_1->setGeometry(700,500,100,50);
com1_1->addItems(subject_c);
com1_1->setVisible(true);
QComboBox* com1_2=new QComboBox(w);//二级控制
com1_2->setGeometry(700,500,100,50);
com1_2->addItems(subject_cpp);
com1_2->setVisible(false);
QList combox_list;//要放入指针类型为了方便统一处理,也可以单独操作
combox_list<setVisible(true);
combox_list[1]->setVisible(false);
}
else if(index==1)
{
combox_list[0]->setVisible(false);
combox_list[1]->setVisible(true);
}*/
int i=0;
for(;isetVisible(false);//不是选中的都为false
}
}
combox_list[index]->setVisible(true);//选中的设置为true
});
#if 0
QStringList text;
text<<"a2022"<<"a2023"<<"a2024";
QStringList icon;
icon<<"mao.jpg"<<"mao1.jpg"<<"mao2.jpg";
QList data;
data<<2022<<2023<<2024;
QComboBox* combox=new QComboBox(w);
int i=0;
for(;iaddItem(QIcon(icon[i]),text[i],QVariant(data[i]));//添加项
}
combox->setGeometry(600,300,100,50);
//combox->setMaxVisibleItems(2);//最多显示几个,出现滚动条
//combox->setIconSize(QSize(30,30));//设置图标大小
//combox->setSizeAdjustPolicy(QComboBox::AdjustToContents);组合框大小策略一般不需要设置
//signal 参数为int常用 应为常常文字信息只是方便人机交互不一定会数据处理
void (QComboBox::*act_int)(int)=&QComboBox::activated;
QObject::connect(combox,act_int,[=](int index){ //只要选中项就会触发
qDebug()<<"act_int index:"<setVisible(true);
QPushButton* btn=new QPushButton(w);
btn->setGeometry(600,400,80,40);
btn->setText("组合框");
btn->setVisible(true);
QObject::connect(btn,&QPushButton::clicked,[=](){
qDebug()<currentIndex()//选中的第几个
<currentText()//显示的文本信息 方便用户阅读
<currentData().toInt();//核心携带数据 (知道放入的携带数据是int直接转)
});
#endif
}
这个做了解就可 主要还是用它本身的 方便快捷(当然也可以自己添加按钮更优雅)
#include
#include
#include
void ini_dialog(QWidget* w)
{
QDialogButtonBox* dialogbtn=new QDialogButtonBox(w);
dialogbtn->addButton(QDialogButtonBox::Ok);//默认文字显示英文
dialogbtn->addButton(QDialogButtonBox::Cancel);
dialogbtn->addButton(QDialogButtonBox::Reset);
dialogbtn->move(700,600);
//dialogbtn->setOrientation(Qt::Vertical);//按钮垂直排列
dialogbtn->setVisible(true);
#if 0 //添加按钮方式2
QDialogButtonBox* dialogbtn=new QDialogButtonBox(w);
dialogbtn->addButton("确定",QDialogButtonBox::AcceptRole);
dialogbtn->addButton("取消",QDialogButtonBox::RejectRole);
dialogbtn->addButton("重置",QDialogButtonBox::ResetRole);
dialogbtn->move(700,600);
//dialogbtn->setOrientation(Qt::Vertical);//按钮垂直排列
dialogbtn->setVisible(true);
#endif
#if 0 //添加按钮方式1
QPushButton* btn1=new QPushButton(w);
btn1->setText("确定");
QPushButton* btn2=new QPushButton(w);
btn2->setText("取消");
QPushButton* btn3=new QPushButton(w);
btn3->setText("重置");
QDialogButtonBox* dialogbtn=new QDialogButtonBox(w);
dialogbtn->addButton(btn1,QDialogButtonBox::AcceptRole);
dialogbtn->addButton(btn2,QDialogButtonBox::RejectRole);
dialogbtn->addButton(btn3,QDialogButtonBox::ResetRole);
dialogbtn->move(700,600);
//dialogbtn->setOrientation(Qt::Vertical);//按钮垂直排列
dialogbtn->setVisible(true);
#endif
QObject::connect(dialogbtn,&QDialogButtonBox::accepted,[](){
qDebug()<<"accepted";
});
QObject::connect(dialogbtn,&QDialogButtonBox::rejected,[](){
qDebug()<<"rejected";
});
QObject::connect(dialogbtn,&QDialogButtonBox::clicked,[=](QAbstractButton *button){
qDebug()<<"按钮:"<text()<<"role:"<buttonRole(button);
});
}