笔记 QT

概念

qt(音同cute):

跨平台的C++应用程序开发框架,可以用来开发GUI程序。GUI 程序设计的主要内容,就是对界面上各个组件的信号的响应;跨平台:相同的代码可以在任何支持的平台上编译运行,而不需要修改源代码,如Windows和Linux 总参考

三大核心机制(围绕信号与槽的展开):

元对象系统,属性系统,信号与槽(最核心)

qt模块:

数据库,图片动画显示,文件读写等

qt creator:

一个跨平台的qt的IDE集成开发环境,可以辅助开发qt程序

信号和槽执行流程:

本质是回调函数。信号或是传递值,或是传递动作变化;槽函数响应信号或是接收值,或者根据动作变化来做出对应操作。

信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。eg.“按钮被按下”这个信号可以用 clicked() 函数表示,“窗口关闭”这个槽可以用 close() 函数表示,信号和槽机制实现“点击按钮会关闭窗口”的功能,其实就是 clicked() 函数调用 close() 函数的效果。

  1. 预编译器moc查找头文件中的signals,slots,标记出信号和槽

  2. 将信号槽信息存储到一个类的静态变量staticMetaObject里,按声明顺序存放,并建立索引

  3. 当发现有connect连接时,就把信号槽的索引信息放到一个map数据结构(键–值)里,让它们彼此配对

  4. 当某个事件被触发,调用信号函数,并且传递发送信号的对象指针,信号索引,参数列表到active函数

  5. 通过active函数找到在map中找到所有与信号对应的槽索引

  6. 根据槽索引找到槽函数,执行槽函数

优点:类型安全、灵活;缺点:比回调函数慢10倍,因为它需要先定位接收信号的对象,然后安全的遍历所有槽;

connect 函数:信号发送者,信号函数,信号接收者,槽函数(&函数所在类::函数名),参数根据接收者和发送者是否在同一个线程;connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot, Qt::ConnectionType type = Qt::AutoConnection));

如果槽函数很简单,可以直接利用 lambda表达式进行连接,以减少代码量;

Moc:又称“元对象编译器”。当我们编译C++文件时,若类中包含了宏Q_OBJECT(信号和槽必写的宏),则会生成另外一个C++源文件,然后才进行C++的普通编译

文件设计和运行机制:

项目管理文件:.pro存储设置,里面有 QT += core gui(包含的模块,写进去)等;

界面文件.ui,以XML语言描述元件及布局,任何窗体或界面组件都是类封装的;

Widget.cpp中ui→setupUI(this)实现了组建的各种设置,信号与槽的关联

Widget.h类封装可视化设计的界面

MVD:

传统的模型-视图框架MVC(model、view、controler)

MVD:model、view、delegate委托(负责最终显示数据和处理用户交互) ,其行为和传统的MVC是相同的

model:负责将数据库数据获取并提供给view,然后将view所做的对数据的修改更新至真正的数据库中。所以,model负责读写文件、操作数据库、网络通讯等一系列与数据打交道的工作

View:如QListView QtableWidget等,基于抽象基类QAbstractItemView类,当view需要显示某些数据时,它们通过model获取数据,当model的data变化时,它也会自动发dataChanged signal给所有的view以便它们更新;View组织这些数据并显示,但却没有做真正的显示工作,真正的显示工作留给了delegate

delegate:当用户触发了view的edit trigger时(如双击鼠标或回车),view开始beginEditing,delegate会在合适的地方创建一个合适的widget (如line edit或combo box等) 处理用户的输入,用户输入完成以后delegate获取用户的输入并返回。这些输入可以通过调用model保存到数据库中。所以,delegate就是负责最终显示数据和处理用户交互

基础窗口

QWidget

QtWidgets 中 QWidget, QMainWindow, QDialog区别:

QWidget窗口带有最小化最大化退出

QMainWindow窗口也带有最大化最小化和退出,另外窗口最下面有statusbar可以显示设置的消息

QDialog窗口没有最大化和最小化,只有退出,可用于修改信息的跳转窗口

QDIalog

1

QMainWindow

1

内存回收

字符串 

QByteArray

QString

QVariant

日期和时间:QDate、QTime、QDateTime

信号槽

lambda表达式

可以作为槽函数

//不能调用
[](){ 
    //内容
};

//有(),可以调用
[](){ 
    //内容
};()

//简化
connect(sender, &SenderClass::signal, receiver, [=](){内容;});

Qt控件

样式修改

在Qt中,可以使用样式表(StyleSheet)来修改控件的外观。

优先级:具体>一般,后定义>前定义,对象>父类

外部样式表:可以是.qss 或 .css

QTableWidget

参考

设置行高or列宽:->setDefaultSectionSize(50);

//创建一个窗口,作为输入框和列表框的父窗口
QWidget widget;
//设置窗口的标题
widget.setWindowTitle("QTableWidget控件");
//自定义窗口的大小
widget.resize(900,500);
// 在 widget 窗口中添加一个 4 行 3 列的表格
QTableWidget TableWidget(4,3,&widget);
// 表格充满布局
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 设置表格中每一行的内容
TableWidget.setItem(0,0,new QTableWidgetItem("C语言"));

Qt事件

1.事件处理器

2.事件分发器

3.事件过滤器

TCP通信 

服务器端

客户端
 

Details里选择基类:

  • 选择框:

    单选:几个signal触发同一个slot

    复选:通过connectSlotsByName将信号与槽关联(看不到connect函数

  • UI设计

    能用可视化的就用可视化,不行的再手动编写

  • MOC元对象编译器

  • 对话框

removeAllDock();
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Vertical);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
showDock();

文件

文本文件:

QIODevice::ReadOnly 以只读方式打开

WriteOnly/ ReadOnly/ ReadWrite/ Append新增加的内容将被放到结尾/ Truncate重写,原内容将被删除/ Text读取时将行结束符换成/n

QTextPlainEdit:palette里可以改变调色板

22.10.29 整理了歌单的歌里喜欢的句子,全都整理到一起了~

——file.open()

void MainWindow::on_actionQFileOpen_triggered()
{
  QString curPath = QCoreApplication::applicationDirPath();
  QString dlgTitle = "这里打开文件:";
  QString filter = "程序(*.h);;文本(*.txt);;所有文件(*.*)";
  QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
​
  if(fileName.isEmpty()) return;
​
  QFile file(fileName);
​
  if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
      ui->plaintextIO->setPlainText(file.readAll());
      file.close();
      ui->tabWidget->setCurrentIndex(0);
  }
}
void MainWindow::on_actionQFileSave_triggered()
{
    QString curPath = QCoreApplication::applicationDirPath();
    QString dlgTitle = "这里另存文件:";
    QString filter = "程序(*.h);;文本(*.txt);;所有文件(*.*)";
    QString fileName = QFileDialog::getSaveFileName(this, dlgTitle, curPath, filter);
    if(fileName.isEmpty()) return;
​
    QFile file(fileName);
​
    if(file.open(QIODevice::WriteOnly | QIODevice::Text)){
        QString str = ui->plaintextIO->toPlainText();
        QByteArray strBytes = str.toUtf8();
        file.write(strBytes, strBytes.length());
        ui->tabWidget->setCurrentIndex(0);
    }
}

二进制文件:

使用QFile和QDateStream,QFile负责文件的IO设备接口,即与文件的物理交互,QDataStream以数据流的方式读取或写入文件内容

QFileInfo:

QFileInfo类为我们提供了系统无关的文件信息,包括文件的名字和在文件系统中位置,文件的访问权限,是否是目录或符合链接等等。并且,通过这个类,可以修改文件的大小和最后修改、读取时间。同时,QFileInfo类也可以用来取到Qt 资源的相关信息。

  #ifdef Q_OS_UNIX
 
  QFileInfo info1("/home/bob/bin/untabify");
  info1.isSymLink();          // returns true
  info1.absoluteFilePath();   // returns "/home/bob/bin/untabify"
  info1.size();               // returns 56201
  info1.symLinkTarget();      // returns "/opt/pretty++/bin/untabify"
 
  QFileInfo info2(info1.symLinkTarget());
  info2.isSymLink();          // returns false
  info2.absoluteFilePath();   // returns "/opt/pretty++/bin/untabify"
  info2.size();               // returns 56201
 
  #endif

qt文件读写: 7 文件系统和文件读写_astream.writerawdata 如何判断是否写完文件?-CSDN博客

文件目录:

OpenGL + QT

  1. 在UI编辑中拖出OpengGLWidget放置于任何一个想嵌入的窗体中。回到代码编辑中,新建一个c++ header,如"glTriangle.h",它需要继承 QOpenGLWidget 类,并实现对应的三个虚函数就能显示。:void initializeGL() override;  void paintGL() override;  void resizeGL(int width, int height) override;
  2. 新建该类的实现。“glTriangle.cpp”;
  3. 回到UI编辑。右击刚拖出来的OpenGLWidget块体,选择“提升为promoted as”,提升的类名称输入刚才定义的类名,确认headfile是刚才定义的头文件,然后点击添加。关闭对话框后,右击“提升为”,选择刚才创建的类名;
  4. 如果编译链接报错,说找不到对应的库,需要打开工程项目文件xxx.pro,加入一行把openg给link进来。LIBS += -lopengl32;

代码技巧

QPainter

2D绘图(也可以用OPenGL画图,23D),不能实现图形的选择、编辑、拖放、修改

三个主要设置:pen笔触、brush填充的纹路、font

painter.setPen();  //笔触
painter.setBrush();//填充
painter.setFont(); //
painter.setRenderHint(); //设置了brush后,画的是效果即填充
painter.drawxxx(); //绘制图形

Graphics View:提供了一个平面,用于管理和交互大量自定义的2D图形图元,以及一个用于可视化图元的视图窗口小部件,支持缩放和旋转,包含了一套完整的事件体系,包括鼠标(Hover等)、键盘事件。Graphics View使用BSP(二进制空间分区)树来提供非常快速的图元发现,即使有数百万个图元,它也可以实时显示大型场景。 QT图形视图框架(Graphics View)_graphicsview-CSDN博客

Data Visualization:3D数据可视化界面,与Qt Charts类似,两者都是基于Qt Graphics View的图形视图结构,Data Visualization的三维显示功能主要由三种三维图形来实现,分别是三维柱状图类Q3Dbars、三维空间散点类Q3DScatter、三维曲面类Q3DSuface。这3种图形类的父类是QAbstract3DGraph,由QWindow继承而来。 技术小新 | Qt开发指南之Data Visualization模块解读_qtdatavisualization-CSDN博客

widget组件自定义62
  • 采取提升法,新建一个类

  • 重新定义paintevent事件(颜色控制,图形绘制等)

  • 视口:绝对的,绘图设备的任意一个矩形区域的物理坐标,默认=绘图设备的整个矩形区

  • 窗口:对应于视口的矩形区域,但是用逻辑坐标,图形会随着窗口大小变化而变化,窗口坐标的中心在矩形中心,使用窗口坐标不用管实际的物理大小

在创建项目时,基于QWidget就行了,不需要MainWindow

VAO VBO EBO理解:

链接:111 222 333

标准化设备坐标:顶点着色器中处理过后,以(-1,1)之间的小立方体内的空间为准,超出的会被裁剪

顶点着色器:

Download glew-1.5.1-win32.zip (The OpenGL Extension Wrangler Library)

在GPU上创建内存,存储顶点数据

VBO(顶点缓冲对象,是一种管理手段,管理顶点数据;是显存中的一片缓冲区域,存放从内存中提交过来的顶点数据,GPU 绘制时,需要对 VBO 中的数据进行解析,以便将数据正确的提交给着色器中对应的属性,通过调用 glVertexAttribPointer 方法来设置解析规则;

  • 着色器的第一个顶点着色器接受到数据流传入的顶点数据后,会把这些数据放到GPU的显存上面(等同内存),接下来向OpenGL中配置如何去解释这些内存,未来如何发给显卡处理。接下来着色器才会按照我们编的代码做我们想做的事情。 我们设立VBO的原因就是要管理这些内存,这样做有很多好处比如:1.我们可以往一个VBO管理的内存中放很多顶点 的数据,一次性把这些数据都从cpu的数据流上送到GPU(显卡)的显存上,这样节省时间,因为从CPU往 GPU的过程中,要经过很多“关卡”,送一“筐”和送一“卡车”是没有区别的。

VAO(顶点数组对象,不保存实际数据,而是放顶点结构定义,解析顶点数据,上述 glVertexAttribPoint的调用结果被记录到 VAO 中,最终绘制的时候直接通过 VAO 中存储的指针去缓冲区取数据

EBO(索引缓冲对象,用来简化程序的渲染步骤,不是必须设置的东西

在绘制的时候,EBO和VBO都可以看作缓存,它们都被VAO管理着,所以实际渲染中,我们只要绑定VAO就可以了

  • 用于处理图像数据的类

    QImage : 为 I/O 以及直接像素访问和操作而设计和优化的。 QPixmap : 为在屏幕上显示图像而设计和优化的。 QBitmap : 一个继承QPixmap的便利类,保证深度为1。如果QPixmap对象确实是位图,isQBitmap()函数返回true,否则返回false。 QPicture : 一个绘制设备,用于记录和重放 QPainter 命令。

——使用技巧

QOpenGlWidget:
//.pro
QT += widgets opengl openglwidgets
#开头加这个 ! 不然会error LNK 2019 !
​
unix|win32: LIBS += -lOpenGL32
#在末尾加这个
​
//.h
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QOpenGLFunctions>
class Open3d : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    Open3d(QWidget *parent = nullptr);
    ~Open3d();
protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int width, int height) override;
private:
};
​
//.cpp
Open3d::Open3d(QWidget *parent) : QOpenGLWidget(parent)
{
}

提示信息

可以让鼠标放在函数名上时显示提示信息

/** \details
    Returns the global (untranslated) name of this command object.
    
    \remarks
    This name must be unique within the groupName of this command object.
  */
  virtual const OdString globalName() const = 0;

pragma
  • pragma指令:在源代码中碰到 pragma 时,将重写编译器选项所指定的行为

  • pragma 关键字:具有与 #pragma 指令相同的功能。 区别在于,pragma 关键字在宏定义中可内联使用。 #pragma 指令在宏定义中不可用,因为编译器会将指令中的数字符号(“#”)解释为字符串化运算符 (#)。

#define CATCH_ALL_DUAL \
CATCH(COleException, e) \
{ \
_hr = e->m_sc; \
} \
AND_CATCH_ALL(e) \
{ \
__pragma(warning(push)) \
__pragma(warning(disable:6246)) /*disable _ctlState prefast warning*/ \
AFX_MANAGE_STATE(pThis->m_pModuleState); \
__pragma(warning(pop)) \
_hr = DualHandleException(_riidSource, e); \
} \
END_CATCH_ALL \
return _hr; \ 
_Pragma 预处理运算符:类似于 Microsoft 特定的 __pragma 关键字。 对于C,仅在指定 /std:c11 或 /std:c17 时可用。 对于 C++,在所有 /std 模式下都可用

与 #pragma 不同,_Pragma 可用于将 pragma 指令放入宏定义中。 字符串字面量应为在 #pragma 语句后面另外放置的内容。

//忽略掉-Wunused-value, -Wpointer-bool-conversion错误
#define ODA_ASSERT_ONCE(exp)\
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wunused-value\" ") \
_Pragma("clang diagnostic ignored \"-Wpointer-bool-conversion\" ") \
{ static bool was_here = false;\
  if (!was_here && !(exp))\
  { was_here = true;\
OdAssert(#exp, __FILE__, __LINE__);\
  }\
} \
_Pragma("clang diagnostic pop")
​
// #exp 意思是将exp所代表的信息转换成一个串
// 调用
PERFORMSELECTOR([wTarget performSelector:sel withObject:nil];);
​
​
//示例:
#define PRT(exp) printf("exp=%d: string-exp=%s\n" , exp , #exp );
int main()
{
    int num=100;
    PRT( num )
    PRT( 123 )
    printf("i'm here! file:%s line:%d\n" , __FILE__,__LINE__ );
    return 0;
}
//输出:
exp=100: string-exp=num
exp=123: string-exp=123
//i'm here! file:E:\DOC\code\C++\test03\learnc.cpp line:10

FILE

File 这里主要是指:正在编译的文件对应的路径和文件的名称,返回值是一个字符串

char BuildFile[] = __FILE__;
printf("编译文件路径:%s\n", BuildFile);
/*
 编译文件路径:d:/123.cpp
*/

一般情况下,FILELINE 结合一起使用,用于打印代码信息,方便快速定位代码位置

C的一些宏:

DATE 当前日期,一个以 “MMM DD YYYY” 格式表示的字符串常量。

TIME 当前时间,一个以 “HH:MM:SS” 格式表示的字符串常量。

FILE 当前文件名,一个字符串常量。

LINE 当前行号,一个十进制常量。

STDC 当编译器以 ANSI 标准编译时,则定义为 1;判断该文件是不是标准 C 程序。

assert

assert() 的用法像是一种"契约式编程",表达的意思就是,程序在我的假设条件下,能够正常良好的运作,其实就相当于一个 if 语句:

if(假设成立)
     程序正常运行;
else
      报错&&终止程序!(避免由程序运行引起更大的错误)

但是这样写的话,就会有无数个 if 语句,甚至会出现,一个 if 语句的括号从文件头到文件尾,并且大多数情况下,我们要进行验证的假设,只是属于偶然性事件,又或者我们仅仅想测试一下,一些最坏情况是否发生,所以有了 assert()

#include "assert.h"
void assert( int expression );

assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行

使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销

在调试结束后,可以通过在包含 #include 的语句之前插入 #define NDEBUG 来禁用 assert 调用

断言assert 是仅在Debug 版本起作用的宏,它用于检查"不应该"发生的情况

QSettings

QSettings类提供了与平台无关的持久性应用程序设置

用户通常希望应用程序跨会话记住它的设置(窗口大小和位置,选项等)。这些信息通常存储在Windows上的系统注册表中,QSettings的API基于QVariant,允许您以最小的代价保存大多数基于值的类型,如QString、QRect和QImage,而如果需要的是一个非持久的基于内存的结构,可以使用QMap < QString,QVariant >代替

//创建QSettings对象时,必须传递公司或组织的名称以及应用程序的名称。例如,如果产品称为Star Runner,公司称为MySoft,则可以:
QSettings settings("MySoft", "Star Runner");
//QSettings存储设置。每个设置都由一个QString和一个QVariant组成,QString指定设置的名称(键),QVariant存储与键相关的数据。可使用setValue写入设置
settings.setValue("editor/wrapMargin", 68);
//可以使用value()获取设置的值
int margin = settings.value("editor/wrapMargin").toInt();
//可以使用’/'字符作为分隔符来形成分层键,类似于Unix文件路径
settings.setValue("mainwindow/size", win->size());
//如果希望用相同的前缀保存或恢复许多设置,可以用beginGroup()指定前缀,在末尾调用endGroup()
settings.beginGroup("mainwindow");
settings.setValue("size", win->size());
settings.setValue("fullScreen", win->isFullScreen());
settings.endGroup();
url属性

scheme 是一种页面之间跳转的协议,不仅可以用于app之间进行跳转,还可以用于 H5 页面跳转到app页面

URL Schemes 有两个单词:

  • URL,Apple 就是个 URL,我们也叫它链接或网址

  • Schemes,表示的是一个 URL 中的一个位置——最初始的位置,即 ://之前的那段字符。比如 Apple 这个网址的 Schemes 是 https

scheme 协议定义和 http 协议类似,都是标准的 URI 结构:

  • scheme : 协议名称 - 必须

  • host : 协议地址 - 必须

  • port : 协议的端口,可以不填

  • path : 协议路径,可用 / 连接多个

  • query : 携带的参数可用 & 连接多个

  • fragment : 锚点

模态

Qt 之 模态、非模态、半模态

模态对话框

在弹出模态对话框时,除了该对话框整个应用程序窗口都无法接受用户响应,处于等待状态,直到模态对话框被关闭。这时一般需要点击对话框中的确定或者取消等按钮关闭该对话框,程序得到对话框的返回值(即点击了确定还是取消),并根据返回值进行相应的操作,之后将操作权返回给用户。这个时候用户可以点击或者拖动程序其他窗口

非模态对话框

又叫做无模式对话框,即弹出非模态对话框时,用户仍然可以对其他窗口进行操作,不会因为这个对话框未关闭就不能操作其他窗口

半模态对话框

半模态对话框区别于模态与非模态对话框,或者说是介于两者之间,也就是说半模态对话框会阻塞窗口的响应,但是不会影响后续代码的执行

statusBar

状态栏显示的信息分3种:

  1. 一般信息,用QLabel 代表

  2. 永久信息,文本会一直显示在状态栏的最右边。

  3. 临时信息,指定信息现实的时间。时间到即信息消失

//QLabel *locationLabel;
locationLabel = new QLabel("July");
locationLabel->setAlignment(Qt::AlignCenter);
locationLabel->setMinimumSize(locationLabel->sizeHint());
​
//QLabel *aixLabel;
aixLabel = new QLabel("\"CTRL + H\" for help");
​
//Optional
statusBar()->setStyleSheet(QString("QStatusBar::item{border: 0px}")); // 设置不显示label的边框
statusBar()->setSizeGripEnabled(false); //设置是否显示右边的大小控制点
statusBar()->addWidget(locationLabel);
statusBar()->addWidget(aixLabel, 1);
​
QLabel *per1 = new QLabel("Ready1", this);
QLabel *per2 = new QLabel("Ready2", this);
QLabel *per3 = new QLabel("Ready3", this);
statusBar()->addPermanentWidget(per1); //现实永久信息
statusBar()->addPermanentWidget(per2);
statusBar()->insertPermanentWidget(2, per3);
​
statusBar()->showMessage("Status is here...", 3000); // 显示临时信息,时间3秒钟.
​
​
​
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
​
//    QLabel *normal=new QLabel("正常信息",this);
//    ui->statusBar->addWidget(normal);//显示正常信息
​
    ui->statusBar->setSizeGripEnabled(false);//去掉状态栏右下角的三角
​
    ui->statusBar->showMessage(tr("临时信息!"),2000);//显示临时信息2000ms 前面的正常信息被覆盖 当去掉后一项时,会一直显示
​
    QLabel *permanent=new QLabel(this);
    permanent->setFrameStyle(QFrame::Box|QFrame::Sunken);
    permanent->setText(tr("<a href=\"http://tengweitw.ueuo.com\">永久信息</a>"));
    permanent->setOpenExternalLinks(true);//设置可以打开网站链接
    ui->statusBar->addPermanentWidget(permanent);//显示永久信息
​
}

HTML

<h1>这是一个标题</h1>
<p>这是一个段落</p>

QSS/CSS

setStyleSheet允许定制窗口外观。

针对控件不多的界面可以在UI界面里直接修改,如果是大批的控件就需要CSS,可以通过setStyleSheet。在main函数里面进行添加样式的调用:

#include "mainwindow.h"
#include <QApplication>
#include <QFile>
 
//设置样式
static  void setStyle(const QString &styleName)
{
    QFile file(QString("%1").arg(styleName));
    file.open(QFile::ReadOnly);
    QString css = QLatin1String(file.readAll());
    qApp->setStyleSheet(css);
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    setStyle(":/image/sheet.css");
    MainWindow w;
    w.show();
    return a.exec();
}
 

CSS 指层叠样式表 (Cascading Style Sheets),样式定义如何显示 HTML 元素。参考

CSS 规则由两个主要的部分构成:选择器 + 一条或多条声明。选择器通常是您需要改变样式的 HTML 元素,每条声明 = 一个属性 + 一个。属性(property)是您希望设置的样式属性(style attribute),每个属性有一个值,属性和值被冒号分开。声明总是以分号 ; 结束,声明们以大括号 {} 括起来。

选择器

 通用*  属性[=]  类.  ID#

*{
background:#3B4453;
}/*通用选择器*/
​
QWidget[form="true"],QLabel[frameShape="1"]{
border:1px solid #202835;
border-radius:0px;
}/*属性选择器 [属性="值"] */
​
.QWidget{/*[form="bottom"]455D77*/
background:#4B5463;
}/*类选择器 . + 类名 或者 . + class 的属性值 作为选择器,只会作用于它自己,它的子类不受影响*/
​
#btnNew:hover{
background:black;
}/*ID选择器 # + objectName 只作用于用此 objectName 的对象*/
/*伪类选择器:如:checked、:hover、:!checked*/
​
QWidget[nav="top"] QAbstractButton:hover,QWidget[nav="top"] QAbstractButton:pressed,QWidget[nav="top"] QAbstractButton:checked{
border-style:solid;
border-width:0px 0px 2px 0px;
padding:4px 4px 2px 4px;
border-color:#80C4F1;
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #3F5D87,stop:1 #3F5D81);
}/*包含选择器 用空格隔开*/
​
.QGroupBox::title{
subcontrol-origin:margin;
position:relative;
left:10px;
}
/*选择器::subcontrol 作为选择 Subcontrol 的选择器。
有些 Widget 是由多个部分组合成的,例如 QCheckBox 由 icon(indicator) 和 text 组成,
可以使用 选择器::subcontrol 来只设置 subcontrol 的样式*/

插入样式表

外部:使用外部样式表,可以通过改变一个文件来改变整个站点的外观。每个页面使用 <link> 标签链接到样式表。

内部:可以给单个文档加特殊样式,使用 <style> 标签在文档头部定义内部样式表。

内联:

/*外部样式表,从文件 mystyle.css 中读到样式声明*/
<head>
<link rel="stylesheet" type="text/css" href="mystyle.css">
</head>

/*内部样式表,可以使用 <style> 标签在文档头部定义内部样式表*/

/*内联样式,*/

bug

Qt自定义控件:Qt Creator本身是由MSVC2017 32-bit编译的,要保持一致 显式类型缺失(int):把导入导出设置重置,后删掉.suo文件重新打开,选择已有的sdk和生成工具(不知道是哪一步起的作用) 头文件能点进去但提示无法打开:添加附加包含目录

——部分操作

Qpushbutton按纽 Qlable文本图片视频 界面文件.ui—— 界面设计器—— 可以在下方选择,发送者接收者信号和槽—— 也可以在cpp文件里找到ui->setupui(this) 后面用ui->mybutton来找到控件并操作 在所有组件的父类QWidget中,定义了很多事件处理的回调函数,比如keyPressEvent, keyReleaseEvent, MouseMoveEvent等 绘图:

QPainter p; p.begin();
p.drawPixmap(x, y, width, height, 路径);//背景图
Qpen pen;//画家的画笔
pen.setwidth(); pen.setColor(QColor(12,12,0)); p.drawLine(x1, y1, x2, y2);//画直线
Qbrush rush;//画家的画刷
brush.setColor();
brush.setStyle();
p.setBrush(brush);//和pen不同,pen是线的样式,brush是背景填充的样式
p.end();
​
update();//窗口重绘,手动刷新
//QBitmap黑白,透明部分黑色
//QPixmap彩色图片,有透明效果
QBitmap b; b.load("地址"); b.drawPixmap(0,0,pixmap);
//窗口绘图一定在paintevent()里

绘图设备: QPixmap最常用,和平台相关,不能修改,但对屏幕进行了优化 QImage和平台无关,可以对图片修改,在线程中绘图 QPicture保存绘图的状态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值