Qt 框架学习

Qt 框架

一个由C++编写的跨平台的图形化用户界面应用程序框架

Hello World

.pro文件,Qt的工程文件

QT += core gui # 添加core gui模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets # 高于Qt4, 添加QT += widgets; 以兼容Qt4

TARGET = hello # 应用程序名

TEMPLATE = app # 指定makefile类型为app(还有lib)

DEFINES += QT_DEPRECATED_WARNINGS
# 源文件
SOURCES += \
        main.cpp \
        widget.cpp
# 头文件
HEADERS += \
        widget.h
# 窗口文件
FORMS += \
        widget.ui

widget.h

#ifndef WIDGET_H //防止多重编译
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget //继承自QWidget
{
    Q_OBJECT // 使用信号槽需要的宏

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("Hello World");
}

Widget::~Widget()
{
    delete ui;
}

main.cpp

#include "widget.h"
#include <QApplication> // QApplication应用程序类

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); //有且仅有一个应用程序类对象
    
    Widget w; // Widget继承于QWidget,QWdidget是一个窗口基类
    w.show(); // 窗口对象默认隐藏,需要显示调用
    a.exec(); // 执行程序,等待事件发生
	return 0;
	// return a.exec();
}

信号和槽

  1. 信号由signals关键字声明
  2. 信号就是函数的声明,只需声明,不用实现
  3. 信号无返回值,但可以有参数,信号和槽的参数列表顺序要一致
  4. 信号可以重载
  5. 使用 emit 发射信号
  6. 一个信号可以连接多个槽函数(槽函数执行顺序时随机的)
  7. 一个槽函数可以被多个信号连接
  8. 槽函数可以时lambda表达式
  9. 信号可以连接信号
  10. 可以使用disconnect断开信号和槽的连接
  11. QObject* QObject::sender() 可获得信号发送者,需强制类型转换
  • Qt 5信号关联

    connect(&my_class, &MyClass::mySignal, this, &TargetClass::handleSlot);
    
    // 信号重载
    void (MyClass::*fp)(int) = &MyClass::mySignal;  //利用函数指针
    connect(&my_class, fp, this, &TargetClass::handleSlot);
    // 通过强制类型转换,转换为函数指针
    connect(&my_class, static_cast<void (MyClass::*)(int)>(&MyClass::mySignal), this, &TargetClass::handleSlot);
    
  • Qt 4信号关联

    // 槽函数需要用slots关键字修饰
    // SIGNAL, SLOT会将函数名转换为字符串, 不进行错误检查
    connect(&my_class, SIGNAL(mySignal()), this, SLOT(handleSlot()));
    connect(&my_class, SIGNAL(mySignal(int)), this, SLOT(handleSlot(int)));
    
  • 使用Lambda表达式
    [函数对象参数](操作符重载函数参数) mutable exception -> 返回值类型 {函数体}

    // Lambada表达式, Lambada表达式
    // 为C++11新特性, 我们需要在项目文件(.pro)中加入 CONFIG += C++11
    // 可配合信号使用
    int a = 1, b =2;
    connect(&my_class, &MyClass::mySignal, 
     		// = : 可将外部所有局部变量、类中所用成员以值传递方式传入
     		// & : 可将外部所有局部变量以引用方式传入
     		// this : 可将类中所有成员以值传递方式传入
     		// 可直接传入变量例如 [a, &b](){}
    		[=]() mutable
    		{
    			qDebug() << a << b;
    			a ++; // 加上 mutable关键字后使传入变量可变
    		});
    

内存回收机制

  1. 需指定父对象
  2. 需直接或间接继承QObject
  3. 子对象使用new后可以不用delete,Qt会自动回收

Qt 窗口系统

菜单、工具、状态栏

// 菜单栏
QMenuBar *menu_bar = menuBar(); // 其实应该是QMainWindow::menuBar(),只是基类为QMainWindow所以可以不用写作用范围,可以QMenuBar *mBar = new QMenuBer(0); 动态new出来
// 添加菜单
QMenu *file = menu_bar->addMenu("文件");
// 添加菜单项,添加动作
QAction *action_new = file->addAction("新建");
// 关联动作信号
connect(action_new, &QAction::triggered,
            [](){ qDebug() << "新建 被触发";});
file->addSeparator();// 添加分割线

QAction *action_open = file->addAction("打开");
connect(action_open, &QAction::triggered, this,
        	[](){ qDebug() << "打开 被触发";});
QMenu *option = menu_bar->addMenu("选项");
QAction *action_update = option->addAction("更新");
connect(action_update, &QAction::triggered, this,
        	[](){ qDebug() << "更新 被触发";});

// 工具栏,菜单项的快捷方式
QToolBar *tool_bar = addToolBar("toolBar");
// 工具栏添加快捷键
tool_bar->addAction(action_new);
// 工具栏添加小控件
QPushButton *btn = QPushButton(this);
btn->setText("按钮控件");
tool_bar->addWidget(btn);
connect(btn, &QPushButton::clicked, 
			[](){ qDebug() << "按钮被按下";});

// 状态栏
QStatusBar *status_bar = statusBar();
QLabel *label = new QLabel(this);
label->setText("当前状态");
// addWidget 从左往右添加
status_bar->addWidget(label);
// addPermanentWidget 从右往左添加
status_bar->addPermanentWidget(new QLabel("状态2", this));

核心控件,浮动窗口

// 核心控件
QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit);

// 浮动窗口
QDockWidget *dock = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, dock); // 第一个参数设置默认区域为右边
// 给浮动窗口添加控件
QTextEdit *textEdit = new QTextEdit(this);
dock->setWidget(textEdit);

模态、非模态

// 模态对话框
QDialog dlg;
dlg.exec(); // 阻塞线程,直到结束

// 非模态对话框
QDialog *dlg = new QDialog; // 不指定父对象
dlg->setAttribute(Qt::WA_DeleteOnClose); // 设置属性,关闭时释放
dlg->show();
// 或将dlg改为类成员,直接show();

标准对话框、文件对话框

QMessageBox::about(this, "关于", "内容");
QMessageBox::question(this, "问题", "内容", QMessageBox::Ok|QMessageBox::Cancel);

QString path = QFileDialog::getOpenFileName(this, "打开", "../", 
								"source(*.cpp *h);;images(*png *jpg);;all(*.*)");

常用控件

  • QLineEdit
    QLineEdit *lineEdit = new QLineEdit(this);
    
    lineEdit->setText("输入框数据");
    lineEdit->text(); // 获取数据
    lineEdit->setTextMargins(20,0,0,0); // 设置边缘间隙
    lineEdit->setEchoMode(QLineEdit::Password); // 设置内容显示模式
    
    QStringList list;
    list << "123" << "456" << "789";
    QCompleter *c = new QCompleter(list, this);
    c->setCaseSensitivity(Qt::CaseInsensitive); // 设置不区分大小写
    
    lineEdit->setCompleter(c); // 设置提示
    
  • QLabel
    QLabel *label = new QLabel(this);
    
    label->setText("标签"); // 文字
    
    label->setText("<h1><a href=\"http://wengcx.top\">我的网址</a></h1>"); // 链接, 使用HTML格式
    label->setOpenExternalLinks(true); // 设置为可用外部浏览器打开
    
    label->setPixmap(QPixmap("://source path")); // 图片
    
    QMoive *movie = new QMovie("://source path"); // 动画
    label->setMovie(movie);
    movie->start();
    
    label->setScaledContents(true); // 设置为自适应
    
  • QProgressBar
    QProgressBar *progressBar = new QProgressBar(this);
    progressBar->setMinimum(0); // 设置最低限度
    progressBar->setMaximum(100); // 设置最大限度
    progressBar->setValue(69); // 设置当前值
    

布局

水平、垂直布局
分裂器水平、分裂器垂直布局
窗体布局中、栅格布局

自定义控件

将标准控件类提升为自己写的类 (继承自该标准控件类)

Qt 样式表

通过调用QWidget::setStyleSheet() 或 QApplication::setStyleSheet(),可以为一个独立子部件、整个窗口或是整个应用程序指定一个样式。其语法规则与CSS几乎相同

去了解一下方箱模型

selector{attribute:value}
/* selector选择器 :通常时是一个类名(例如 QPushButton),
   attribute:value :属性名和值 */

/* 设置3个选择器的样式(前景色, 背景色, 图片, 字体) */
QCheckBox, QComBox, QSpinBox{
	color:rgb(0, 0, 0);
	background-color:white;
	border-image:url(://source path);
	font:bold;
}

/* Qt使用
   对于指定部件 */
QPushButton *btn = new QPushButton(this);
btn->setStyleSheet("QPushButton{"
	"color:rgb(0, 0, 0);"
	"background-color:white;"
	"font:bold;"
}");
/* 伪状态(默认和按下时) */
btn->setStyleSheet("QPushButton{"
	"color:rgb(0, 0, 0);"
	"background-color:white;"
	"}"
	"QPushButton:pressed{"
	"color:rgb(255, 255, 255);"
	"background-color:black;"
	"}"
}")

/* 当前对象 */
this->setStyleSheet("QCheckBox{"
	"color:rgb(0, 0, 0);"
	"background-color:white;"
	"font:bold;"
}");

/* 对于整个应用程序 */
QApplication a(argc, *argv);
a->setStyleSheet("QCheckBox{"
	"color:rgb(0, 0, 0);"
	"background-color:white;"
	"font:bold;"
}");

Qt 事件系统

事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称

  1. Qt 使用一个对象代表一个事件,所有事件类都继承于 QEvent。
  2. 在Qt中任何QObject的子类实例都可以接收和处理事件
  3. QApplication对象通过调用 exec() 开始Qt事件循环来监听应用程序的事件,当有事件发生时,Qt 会产生一个与之对应的事件对象(QEvent子类实例)。Qt 会将这个事件对象传递给QObject的 event(),该函数按照事件对象的类型将对象给相应的处理函数 /(注:这些处理函数都是虚函数,需要继承实现)

重写部件事件处理函数

例如: keyPressEvent()、mousePressEvent()等, 该方法只用于处理特定部件的的特定事件

void MyWidget::keyPressEvent(QKeyEvent *e) // 重写键盘事件
{
	qDebug() << (char)e->key(); // key() 返回值为枚举, 强制转换后为键盘字符
}
void MyWidget::timerEvent(QTimerEvent *e) // 重写定时器事件
{
	static int s = 0;
    if(e->timerId()==timer_id) // 一个定时器事件有一个身份标识, 此处timer_id为自定义类成员以保存事件id
    {
        qDebug() << s++;
        if(s==10)
        {
            this->killTimer(timer_id); // 结束 timer_id 对应事件
        }
    }
}
void MyWidget::closeEvent(QCloseEvent *e) // 重写关闭事件
{
	int r = QMessageBox::infomation(this, "提示", "确定关闭?", "是的", "取消");
	if(!r)
    {
        // 关闭窗口时
        e->accept(); // 处理关闭事件,接收事件,使得事件不会再往下传递
    }
    else
    {
        // 取消时
        e->ignore(); // 忽略事件,使得事件往下传递
    }
}

重写event()

QObject::event() 可以在事件到达默认处理函数之前获得该事件,用于事件的分发

bool MyWidget::event(QEvent *e) // 重写事件分发
{
    switch (e->type()) // type()函数返回事件类型的枚举
    {
    case QEvent::Close:
        closeEvent(static_cast<QCloseEvent*>(e));
        return true; // 忽略此事件,不再传递
    default:
        return QWidget::event(e); // 继续将事件传递
    }
}

重写事件过滤器

Qt提供事件过滤器来实现在一个部件中监控其它多个部件的事件,它不是一个类,只是有两个函数( QObject::installEventFilter()、QObject::eventFilter())组成的一种操作,用来完成一个部件对其它部件的监视

 // 为部件安装事件过滤器
ui->label->installEventFilter(this); // this表示在当前部件中监视该事件, 为 QObject * 类型
ui->button->installEventFilter(this);

// 重写事件过滤器
bool MyWidget::eventFilter(QObject *watched, QEvent *e)
{
    if(watched==ui->label) // 判断部件对象类型
    {
        if((static_cast<QMouseEvent *>(e))->type()==QEvent::MouseButtonPress) //判断事件对象类型
        {
            qDebug() << "鼠标在label处按下";
            // return true; // 让事件不再往下传递,标明已处理
        }
    }
    else if(watched==ui->button)
    {
    	if((static_cast<QMouseEvent *>(e))->type()==QEvent::MouseButtonPress)
        {
            qDebug() << "鼠标在button处按下";
            // return true;
        }
    }
    return QWidget::eventFilter(watched, e);
}

发送事件

Qt 提供发送事件的功能

bool QCoreApplication::sendEvent(QObject *receiver, QEvent *e);
bool QCoreApplication::postEvent(QObject *receiver, QEvent *e, int priority=Qt::NormalEventPriority)
// 区别: 前者会立即处理给定事件; 而后者会将事件放到等待调度队列,当下一次主事件循环运行时才会处理

// 发送键盘事件到QLineEdit部件对象line_edit
QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
QApplication::sendEvent(line_edit, event);

// 可以自定义事件, 需继承QEvent

待续

关于静态编译:https://www.cnblogs.com/ike_li/p/6860089.html

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值