This commit is contained in:
2023-06-29 11:55:02 +08:00
commit 36e95249b1
1236 changed files with 464197 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
## 坐标
1. Item(图元)坐标:属于局部坐标,通常以图元中心为原点(中心对称)非中心对称类比如dialog类一般以左上角为原点正方向x朝右y朝下。
2. setPos的坐标是父类坐标系的坐标一般对于item位于scene中的应用场景。
3. scene(场景)坐标:属于逻辑坐标 logical coordinates与QPainter相同**以场景中心为原点**正方向x朝右y朝下。
4. 图元原点左上角dialog的原点**与场景原点对齐**,导致图元外边框的左上角顶点在场景中的坐标位置为(负数,负数)。
5. View(视图)坐标属于设备坐标device coordinates与窗口相同**默认以左上点为原点** 正方向x朝右y朝下。
6. 默认场景scene的左上角顶点与视图坐标原点对齐。**显示时默认中心对齐**,当场景大小小于视图大小的时候,将中心对齐,此中指的仍然是整个图元的中心,同时,图元原点与场景原点对齐,场景左上角顶点与视图原点对齐,视图左上角顶点不一定是原点???,此时也将出现视图坐标有正值有负值。
- 1translate()将当前视图坐标原点平移从而实现显示图像的平移变换。由于默认场景的左上角顶点与视图坐标原点对齐translate()将坐标原点平移,也就实现了将场景的平移。
- 2rotate()将当前视图围绕视图坐标原点旋转,从而实现显示图像的旋转变换。
- 3size()返回视图大小默认大小100*30由于视图可以是无限大小而且只有在显示后才创建出实际尺寸因此只有在showEvent中调用 size 函数才能正确显示视图大小否则都是返回默认的100*30因为此时视图尚未显示即尚未形成。
https://www.cnblogs.com/cthu/p/5103551.html
## 常用的QGraphicsItem
https://blog.csdn.net/liang19890820/article/details/53065293
## QGraphics
https://blog.csdn.net/liang19890820/article/details/51966791

View File

@@ -0,0 +1,79 @@
## 注意点
隐藏状态栏时第一个界面不能使用Qt设计师界面类创建项目时不勾选**创建界面**选项)。不然以下方法皆会无效。
## 方法1
修改AndroidManifest.xml中activity的主题。即在`<activity>`标签中添加 `android:theme="@android:style/Theme.NoTitleBar.Fullscreen"`
以下为实例代码:
```
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="an.qt.helloQtQuickApp.QtFullscreenActivity"
android:label="-- %%INSERT_APP_NAME%% --"
android:screenOrientation="unspecified"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTop">
```
如果无效则需要重写QtActivity的onCreate函数。
大致步骤如下:
1. 在项目目录\android\src\目录下创建与包名相同的目录。例如我们要创建的包为an.qt.helloQtQuickApp那么路径为an\qt\helloQtQuickApp。并创建一个Java文件用于定义我们的Activity。文件名可以随便取,我这里的文件名设为QtFullscreenActivity.java。
2. 修改AndroidManifest.xml文件使用我们刚才新定义的Activity。
` <manifest>` 标签中的package改成我们创建的包名。将`<activity>`标签中android:name改成an.qt.helloQtQuickApp.QtFullscreenActivity,即包名.新创建的Activity类名。
>Java文件代码如下
```
package an.qt.helloQtQuickApp;
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.view.WindowManager;
public class QtFullscreenActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private final static String TAG = "QtFullscreen";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
```
详细操作过程可以参看安晓辉的blog
https://blog.csdn.net/foruok/article/details/38265349
## 方法2
大致思路如下使用Qt5.7后在QtAndroid类新增了一个静态函数
```
void QtAndroid::runOnAndroidThread(const QtAndroid::Runnable &runnable)
```
通过它调用以下Java代码
```
Activity activity = (Activity) mContext;
View decorView = activity.getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN);
```
这种方法的好处在于可以在运行时控制是否隐藏状态栏而且不用改AndroidManifest.xml文件移植方便。
详细操作可以见作者Blog
https://blog.csdn.net/jun4331247/article/details/80739662
项目Github
https://github.com/WingNan/QtAndroidFullScreen
### 移植步骤
1. 复制文件jfullscreen.h、jfullscreen.cpp至你的项目目录。复制android/src目录及其内部文件至项目同名目录。
2. 在项目上右键点击“添加现有文件",将以上几个文件添加到项目中。
3. 编辑项目文件(*.pro)添加androidextras模块在Qt+=core gui后面加上androidextras
4. 在app的第一个widget中#include "jfullscreen.h",并在构造函数中加入:
```
JFullScreen *pManager = new JFullScreen;
pManager->fullScreenStickyImmersive();
```
注意创建项目时不能勾选“创建界面”选项并且第一个widget不能使用设计师界面类来创建

View File

@@ -0,0 +1,53 @@
## 字体文件下载
fontawesome-webfont.ttf另一个是pe-icon-set-weather.ttf
fontawesome-webfont.ttf 下载地址http://fontawesome.dashgame.com/
pe-icon-set-weather.ttf 下载地址https://www.pixeden.com/icon-fonts/the-icons-font-set-weather
在pixeden中还有许多其它的图标字体库下载https://www.pixeden.com/icon-fonts
## Code
```
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFontDatabase>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//引入图形字体
int fontId = QFontDatabase::addApplicationFont(":/image/pe-icon-set-weather.ttf"); //加入字体并获取字体ID
QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0); //获取字体名称
QFont iconFont = QFont(fontName);
iconFont.setPixelSize(128); //设置字体大小
ui->lab_e901->setFont(iconFont); //设置Label的字体
ui->lab_e901->setText(QChar(0xe901)); //设置Label的文体
ui->lab_e901->setStyleSheet("color:red;");
QPalette blue_pe;
blue_pe.setColor(QPalette::WindowText,Qt::blue);
ui->lab_e903->setFont(iconFont);
ui->lab_e903->setText(QChar(0xe903));
ui->lab_e903->setPalette(blue_pe);
ui->lab_e905->setFont(iconFont);
ui->lab_e905->setText(QChar(0xe905));
ui->lab_e907->setFont(iconFont);
ui->lab_e907->setText(QChar(0xe907));
}
MainWindow::~MainWindow()
{
delete ui;
}
```
## QFontDatabase
QStringList QFontDatabase::families(QFontDatabase::WritingSystem writingSystem = Any) const
返回可用的字体列表。
QFont QFontDatabase::font(const QString &family, const QString &style, int pointSize) const
返回一个可用的字体对象。

View File

@@ -0,0 +1,104 @@
## 通用选择器
* 作为选择器,作用于所有的 widget。
类型选择器
类名 作为选择器,作用于它自己和它的所有子类。
```
QFrame {
background: gray;
}
```
## 类选择器
. + 类名 或者 . + class 的属性值 作为选择器(使用 setProperty(“class”, “QSSClassName”) 设置),只会作用于它自己,它的子类不受影响,注意和类型选择器的区别。
```
app.setStyleSheet(".QWidget { background: gray; }"
".RedButton { background: magenta; }");
// .RedButton 将作为类选择器
openButton->setProperty("class", "RedButton");
closeButton->setProperty("class", "RedButton");
```
## ID 选择器
'#' + objectName 作为选择器,只作用于用此 objectName 的对象
```
// #openButton 和 #closeButton 作为 ID 选择器
app.setStyleSheet(".QWidget { background: gray; }"
"#openButton, #closeButton { background: magenta; }");
openButton->setObjectName("openButton");
closeButton->setObjectName("closeButton");
```
## 属性选择器
选择器[属性="值"] 作为选择器,这个属性可用通过 object->property(propertyName) 访问的Qt 里称为 Dynamic Properties。
如上面的程序, openButton 和 closeButton 的背景是洋红色的,但是 saveButton 不受影响,也可以使用属性选择器来实现:
```
app.setStyleSheet(".QWidget { background: gray; }"
"QPushButton[level='dangerous'] { background: magenta; }");
openButton->setProperty("level", "dangerous");
```
属性选择器可以包含多个属性,只需要:
```
QPushButton[level='aaa'],QPushButton[level='bbb'] { background: magenta; }
```
如果有多个属性,则会优先选择匹配数多的样式。
## 包含选择器
英语叫做 Descendant Selectordescendant 的表达比较到位。
选择器之间用空格隔开,作用于 Widget 的 子Widget子Widget 的 子Widget……子子孙孙无穷尽也。
```
QFrame {
background: gray;
}
/* 设置 QFrame 中的 QPushButton 的 QSS */
QFrame QPushButton {
border: 2px solid magenta;
border-radius: 10px;
background: white;
padding: 2px 15px;
}
```
## 子元素选择器
选择器之间用 > 隔开,作用于 Widget 的直接 子Widget注意和包含选择器的区别。
```
QFrame {
background: gray;
}
QFrame > QPushButton {
border: 2px solid magenta;
border-radius: 10px;
background: white;
padding: 2px 15px;
}
```
## 伪类选择器
选择器:状态 作为选择器,支持 ! 操作符,表示 非。
```
QPushButton:hover { color: white }
QCheckBox:checked { color: white }
QCheckBox:!checked { color: red }
```
## Subcontrol 选择器
选择器::subcontrol 作为选择 Subcontrol 的选择器。
有些 widget 是由多个部分组合成的,例如 QCheckBox 由 icon(indicator) 和 text 组成,可以使用 选择器::subcontrol 来设置 subcontrol 的样式:
```
QCheckBox::indicator {
width: 20px;
height: 20px;
}
QCheckBox {
spacing: 8px;
}
```

View File

@@ -0,0 +1,102 @@
## 参考项目
https://blog.csdn.net/liang19890820/article/details/50557240
https://www.cnblogs.com/feiyangqingyun/p/3915657.html
QSS模板网站https://qss-stock.devsecstudio.com/
## 技巧
Qt内置图标封装在QStyle中大概七十多个图标可以直接拿来用。
- SP_TitleBarMenuButton,
- SP_TitleBarMinButton,
- SP_TitleBarMaxButton,
- SP_TitleBarCloseButton,
- SP_MessageBoxInformation,
- SP_MessageBoxWarning,
- SP_MessageBoxCritical,
- SP_MessageBoxQuestion,
## 配色
ElementUI配色https://element.eleme.cn/#/zh-CN/component/color
Brand Color `#409EFF`
**辅助色**
- Success#67C23A
- Warning#E6A23C
- Danger#F56C6C
- Info#909399
**基础色**
- 主要文字#303133
- 常规文字#606266
- 次要文字#909399
- 占位文字#C0C4CC
- 一级边框#DCDFE6
- 二级边框#E4E7ED
- 三级边框#EBEEF5
- 四级边框#F2F6FC
## 边框
- 实线 1px
- 虚线 2px
### 圆角
- 无圆角border-radius: 0px
- 小圆角border-radius: 2px
- 大圆角border-radius: 4px
- 圆形圆角border-radius: 30px
### 投影
- 基础投影 box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
- 浅色投影 box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1)
## QSS设置函数
feiyangqingyun-QWidgetDemo-master/FlatUI<br>
使用函数的方式来生成QSS代码与设置对应的控件。
```
QString BRUI::setPushButtonQss(QPushButton *btn, int radius, int padding,const QString &normalColor,const QString &normalTextColor,const QString &hoverColor,const QString &hoverTextColor,const QString &pressedColor,const QString &pressedTextColor)
{
QStringList list;
list.append(QString("QPushButton{border-style:none;padding:%1px;border-radius:%2px;color:%3;background:%4;}").arg(padding).arg(radius).arg(normalTextColor).arg(normalColor));
list.append(QString("QPushButton:hover{color:%1;background:%2;}").arg(hoverTextColor).arg(hoverColor));
list.append(QString("QPushButton:pressed{color:%1;background:%2;}").arg(pressedTextColor).arg(pressedColor));
QString qss = list.join("");
if(btn)
btn->setStyleSheet(qss);
return qss;
}
```
## 可以参考的UI工程
QSS生成工具StyleDemo。
给QWidget添加属性来控制样式
```
ui->widgetLeft->setProperty("nav", "left");
ui->widgetBottom->setProperty("form", "bottom");
ui->widgetTop->setProperty("nav", "top");
ui->widgetVideo->setProperty("video", true);
```
Qss
```
QWidget[nav="left"] QAbstractButton:checked,QWidget[nav="left"] QAbstractButton:pressed{
color:#386487;
border-style:solid;
border-width:0px 0px 0px 2px;
padding:4px 4px 4px 2px;
border-color:#00BB9E;
background-color:#EAF7FF;
}
```
### 切换器
ImageSwitch
### 日历
lunarcalendarwidget
### 导航按钮
NavButton
## StyleDemo中的CSS
flatwhite.css
lightblue.css
psblack.css

View File

@@ -0,0 +1,121 @@
## 前言
本人发现有关QML文件之间的通讯的资料不多而且都不太好找所以在这里总结一下方便后续的开发者
## 直接导入qml
目录结构:
```
myapp
|- mycomponents
|- CheckBox.qml
|- DialogBox.qml
|- Slider.qml
|- main
|- application.qml
```
那么可以:
```
import "../mycomponents"
DialogBox {
CheckBox {
// ...
}
Slider {
// ...
}
}
```
但是创建一个命名空间来导入会更好
```
import "../mycomponents" as MyComponents
MyComponents.DialogBox {
// ...
}
```
## qml文件间通讯
3.题回正传直接上代码以StackView管理页面为例
(1)page1.qml跳转到page2.qml传值
```
page1.qml
Rectangle
{
id:rect1
...
MouseArea {
id: maStartQuery
anchors.fill: parent
onClicked:
{
if(!stackView.busy)
stackView.push(Qt.resolvedUrl("qrc:///qml/page2.qml"),
{name:"张三"})//给page2.qml的name传值“张三”,name必须在page2.qml中定义成属性
}
}
...
}
page2.qml定义如下
Rectangle
{
id:rect2
...
property string name:""//要传的值
...
}
```
(2)page2.qml点击"确定"按钮时将结果返回给page1.qml
A.在page1.qml中增加一个函数clickedfunc当点击page2.qml中"确定"按钮时调用;
B.在page2.qml中增加一个属性containerqml用来记录page1.qml
C.在从page1.qml跳转到page2.qml时将rect1传给page2.qml的containerqml属性。
```
page1.qml
Rectangle
{
id:rect1
...
MouseArea {
id: maStartQuery
anchors.fill: parent
onClicked:
{
if(!stackView.busy)
stackView.push(Qt.resolvedUrl("qrc:///qml/page2.qml"),
{name:"张三",containerqml:rect1})
}
}
//当点击page2.qml中"确定"按钮时调用
  function clickedfunc(temp)
{
console.log("改成了:"+temp);
 stackView.pop();//返回到本页
}
...
}
page2.qml
Rectangle
{
id:rect2
...
property variant containerqml: null
property string name:""//要传的值
...
MouseArea {
id: btnOK
anchors.fill: parent
onClicked:
{
containerqml.clickedfunc("李四");//调用page1.qml中的函数实现了传返回值。
}
}
}
```
另一种就是信号与槽

View File

@@ -0,0 +1,163 @@
## color属性
可以使用"blue"、"#RRGGBB"、Qt.rgba()来赋值。具体可以参考QML Basic Type:color
## 手机的横屏模式与竖屏模式
需要修改AndroidManifest.xml中的activity元素的android:screenOrientation属性为"landscape"或"portrait"
## Item组件
1. Item是所有可视元素的基类。
2. 其中一个用处就是可以分组其他可见图元。
3. clip属性如果为true可以裁剪子组件。
4. 通过附加属性Keys来处理按键。详情Keys QML Type
## Text
可以使用HTML修饰过的文本
## Image
1. 如何设置了width与height图片可能会被拉伸此时fillMode属性就可以设置填充模式了。
2. Image默认是阻塞式加载可以通过把asynchronous设为true开启异步模式。可以先显示一个加载图标当status的值为Image.Ready时再显示。
3. source属性是url网络模式会默认开启异步加载此时Image的Progress0。0~1.0、status都会实时更新。
```
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("App")
BusyIndicator{
id:busy;
running: true;
anchors.centerIn: parent;
z:2
}
Text{
id:stateLabel;
visible:false;
anchors.centerIn: parent;
z:3
}
Image{
id:imageViewer;
asynchronous: true;
cache:false;
anchors.fill: parent;
fillMode: Image.PreserveAspectFit;
onStatusChanged: {
if(imageViewer.status===Image.Loading){
busy.running=true;
stateLabel.visible=false;
}else if (imageViewer.status===Image.Ready){
busy.running=false;
}else if(imageViewer.status===Image.Error){
busy.running=false;
stateLabel.visible=true;
stateLabel.text="error";
}
}
}
Component.onCompleted: {
imageViewer.source="http://img.zcool.cn/community/01d881579dc3620000018c1b430c4b.JPG@3000w_1l_2o_100sh.jpg";
}
}
```
## Object类是所有ECMAScript类的基类它具有以下属性
1. constructor指向创建对象的函数对于Object类它指向object()函数。
2. prototype对该对象原型类型的引用可以在运行时改变原型。
3. hasOwnPropety是否拥有某个属性
4. isPrototypeOf判断对象是否为另一个对象的原型。
5. ptopertyIsEnumerable判断给定的杏树是否可以用for in进行枚举。
6. toString()
7. valueOf(),返回最适合该对象的原始值。
## Qt对象
Qt是QML提供的一个全局宿主对象整合了常用的属性、方法与枚举类型。
Qt.application 应用的全局状态
## Connections
适用对象:
1. 你需要将多个对象连接到同一个QML信号上。
2. 你需要在发出信号的对象的作用域之外来建立连接
3. c++导出对象
```
Connections{
target:area;//目标控件(它的信号触发)
on<Signal>:function or code block;//执行代码
}
```
## 连接信号的方式
```
Rectangle {
id: relay
signal messageReceived(string person, string notice)
//可以连接信号或者函数
Component.onCompleted: {
relay.messageReceived.connect(sendToPost)
relay.messageReceived.connect(sendToTelegraph)
relay.messageReceived.connect(sendToEmail)
relay.messageReceived("Tom", "Happy Birthday")
}
function sendToPost(person, notice) {
console.log("Sending to post: " + person + ", " + notice)
}
function sendToTelegraph(person, notice) {
console.log("Sending to telegraph: " + person + ", " + notice)
}
function sendToEmail(person, notice) {
console.log("Sending to email: " + person + ", " + notice)
}
}
```
## component
### 嵌入式组件:
```
Component {
id: redSquare
Rectangle {
color: "red"
width: 10
height: 10
}
}
```
只能包含一个顶层item与id<br>
### 单文件组件
单文件组件不需要加Component
#### 使用Loader
```
Item {
Component {
id: redSquare
Rectangle { color: "red"; width: 10; height: 10 }
}
Loader { sourceComponent: redSquare }
Loader { sourceComponent: redSquare; x: 10 }
}
```
通过sourceComponent加载组件source则可以通过url加载单文件组件。<br>
在加载完成后(onLoaded)后可以通过Loader的item操作已经加载的组件<br>
如果Loader加载的Item想要处理按键事件那么久必须将Loader对象的focus属性设置为true同时也需要对它加载的Item的accepted属性设置为true以免已经被吃掉的事件再传递给Loader。
### ECMAScript中动态创建对象
```
var newObject = Qt.createQmlObject('import QtQuick 2.0; Rectangle {color: "red"; width: 20; height: 20}',
parentItem,
"dynamicSnippet1");
```
或者
```
var component = Qt.createComponent("Button.qml");
if (component.status == Component.Ready)
component.createObject(parent, {"x": 100, "y": 100});
```

View File

@@ -0,0 +1,113 @@
## 前言
最近在为单位做一个简单的手机App基于Qt技术栈的选择了QtQuick来开发。不得不说QtQucik开发的确舒服很多东西都不用写就可以只用UI定义起来也比较自由。但是本人想通过cookie来作为登陆验证时就发现QtQuick实现起来相当麻烦。主要是没有文档资料只找到一篇qyvlik写的。我也不想直接用WebEngine
## 不带cookie
可以使用XMLHttpRequest比较坑的是官方竟然没有任何案例不过Api都是与js的XmlHttpRequest一样的以下是qyvlik封装的一套分辨操作函数
```
//通过Json对象输出url的query字符串
function urlQuery(jsonObject) {
var query = "";
var i = 0;
for(var iter in jsonObject) {
if(i > 0) {
query += "&";
}
query += iter +"=" + encodeURI(jsonObject[iter]);
i++;
}
// console.log("url query:", query);
return query;
}
//设置头
function setHeader(xhr, headers) {
//"Content-Type":"application/x-www-form-urlencoded"
for(var iter in headers) {
xhr.setRequestHeader(iter, headers[iter]);
}
}
//这里我修改了一下函数的形参从使用的角度来看回调函数一般都会有但是headers不一定要设置所以调换了一下位置
function ajax(method, url, callable,headers,data) {
headers = headers || {};
callable = callable || function(xhr) {
console.log("没有设置callable使用默认log函数")
console.log(xhr.status);
console.log(xhr.responseText);
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState == xhr.DONE) {
callable(xhr);
}
}
xhr.open(method, url);
setHeader(xhr, headers);
if("GET" === method) {
xhr.send();
} else {
xhr.send(data);
}
}
```
为了能够重复利用本人将这些代码都放入一个js文件中之后使用导入的方式重复利用。注意导入的命名控件首字母需要大写
```
import "xmlhttprequest.js" as XmlHttpRequest
```
使用:
```
var jsonObject={user:"admin",password:Qt.md5("123")};
XmlHttpRequest.ajax("GET","http://192.168.3.108:3000/landing"+"?"+XmlHttpRequest.urlQuery(jsonObject),function(xhr){
console.log(xhr.status);
console.log(xhr.responseText);
if(JSON.parse(xhr.responseText).message==="ok") {
stack.push("qrc:/resource/qml/listview.qml",{stack:stack,uifont:uifont});
}else{
message.show("用户名或者密码错误!",2000);
}
});
```
## 带cookie
因为XmlHttpRequest是不能带有cookie的所以只能通过c++导出QNetworkAccessManager、QNetworkRequest、QNetworkReply具体的代码可以参考https://github.com/qyvlik/QmlNetwork。qyvlik封装了一套QML对象我直接拿来用了很可惜他的使用说明写的不太详细有一些操作需要直接看他写的微信案例才能搞定。
```
NetworkAccessManager { id: manager }
NetworkResponse { id: response }
NetworkRequest { id: request }
Buffer { id: buffer }
function initWebWeiXinInfo() {
var url = "http://192.168.3.108:3000/landing";
var data = {
user:"admin",
password:"123"
};
if(buffer.isOpen()) {
buffer.close();
}
buffer.data = JSON.stringify(data);
if(!buffer.open(IODevice.ReadOnly)) {
console.log(buffer.errorString());
}
request.clear();
request.url = url;
// request.setHeader("Cookie", cookie);
request.setHeader("Content-Type", "application/json")
request.ioDevice = buffer;
connectSignalOnce(response.finished,function() {
console.log("data:", buffer.data)
var headers = response.getAllResponseHeaders();
for(var iter in headers) {
console.log(headers[iter]);
}
console.log(response.responseContent);
});
manager.post(request, response);
}
```
## 结语
感觉qyvlik封装的东西比较多需求上本人也就用用Get与Post以及cookie以后有时间会重新封装一个简单版本。

View File

@@ -0,0 +1,118 @@
## 自定义控件样式
请在Qt帮助索引中输入Customizing a Control进行查看<br>
不过实际用下来感觉除非你想自己实现一套效果复杂的UI或是创造一个全新控件比如给UI添加模糊、虚化等ShaderEffect效果。不然不推荐用这个。比如本人就是想把CheckBox的大小改小同时不改变显示样式这个就很难办到。<br>
## 系统自带的几种主题风格
1. Default Style
2. Fusion Style
3. Imagine Style
4. Material Style
5. Universal Style
其中Imagine Style是使用图片定制风格图片需要按照指定的命名来放置具体操作请看文档
http://doc.qt.io/qt-5/qtquickcontrols2-imagine.html
### 在c++中使用QQuickStyle
```
QQuickStyle::setStyle("Material");
```
具体内容请在帮助索引中搜索 QQuickStyle
### 命令行中设置
```
./app -style material
```
### 在Qt的环境变量中设置
```
QT_QUICK_CONTROLS_STYLE=universal ./app
```
### 使用配置文件
```
[Controls]
Style=Material
```
官方的gallery案例用的是这种。
网上有个哥们用的是:
```
if (sty == "mat") {
qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2material.conf");
} else {
qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2universal.conf");
}
```
本人用的是gallery案例中的方式感觉通过设置环境变量来指定对应的conf不太灵活所以上述方式仅供参考。<br>
想要看懂conf文件需要看以下两篇文档
## Qt Quick Controls 2 Configuration File
文档http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
在默认情况下将文件放置于:/qtquickcontrols2.conf也就是根目录就会生效需要设置QQuickStyle
### Controls Section
Style定义全局控件样式
### XXXX Section
对对应的style进行设置
### Font Configuration
设置字体,有以下几个属性:
1. Family
2. PointSize
3. PixelSize
4. StyleHint
5. Weight
6. Style
### Palette Configuration
Palette我不太清楚是干什么的
## Material Style
文档http://doc.qt.io/qt-5/qtquickcontrols2-material.html#material-theme-attached-prop<br>
你可以单独给某一些控件设置style,以下是对应的属性:
### accent
```
Button {
text: qsTr("Button")
highlighted: true
Material.accent: Material.Orange
}
```
### background
```
Button {
text: qsTr("Button")
highlighted: true
Material.background: Material.Teal
}
```
### elevation
控制阴影的属性
```
Pane {
width: 120
height: 120
Material.elevation: 6
Label {
text: qsTr("I'm a card!")
anchors.centerIn: parent
}
}
```
### foreground
```
Button {
text: qsTr("Button")
Material.foreground: Material.Pink
}
```
### primary
### theme
三个可选项:
1. Material.Light
2. Material.Dark
3. Material.System
```
Pane {
Material.theme: Material.Dark
Button {
text: qsTr("Button")
}
}
```
## 自定义主题
文档http://doc.qt.io/qt-5/qtquickcontrols2-customize.html#creating-a-custom-style
推荐http://www.cnblogs.com/Fuss/archive/2015/03/20/4353698.html<br>
代码没怎么看Control用的是1.0可以作为参考Github上有关这种UI定制的代码还是比较多建议先去知乎搜索 “请问有哪些优质又开源的qml应用”

View File

@@ -0,0 +1,291 @@
## 参考网址
https://blog.csdn.net/wsj18808050/article/details/54234956
Qt获取屏幕物理长度和宽度CM
https://blog.csdn.net/wsj18808050/article/details/54345537
Qt5.8新特新QtLite使用方法以及缩减应用体积的效果
https://blog.csdn.net/wsj18808050/article/details/55808104
QML 中的屏幕适配问题
https://blog.csdn.net/qyvlik/article/details/51241425
QT59HTTP POST GET COOKIE 网络编程
```c++
#include <QNetworkCookie> //单个cookie
#include <QNetworkCookieJar> //储存cookie
```
https://blog.csdn.net/qq_16234613/article/details/53783391
qt 获取部分的cookie信息 如何把获取的cookie转换为QString类型 正则表达式
https://blog.csdn.net/qq_22403265/article/details/51333226
### cookiebrowser使用webview载入cookie
```
m_store = m_webview->page()->profile()->cookieStore();
m_store->loadAllCookies();
```
### QML Settings 小的示例
Setting 可以存储一些变量就想配置文件一样
https://www.cnblogs.com/hbrw/p/6744094.html
### 直接导入qml
Importing QML Document Directories
目录结构:
```
myapp
|- mycomponents
|- CheckBox.qml
|- DialogBox.qml
|- Slider.qml
|- main
|- application.qml
```
那么可以:
```
import "../mycomponents"
DialogBox {
CheckBox {
// ...
}
Slider {
// ...
}
}
```
但是创建一个命名空间来导入会更好
```
import "../mycomponents" as MyComponents
MyComponents.DialogBox {
// ...
}
```
### qml文件间通讯
3.题回正传直接上代码以StackView管理页面为例
(1)page1.qml跳转到page2.qml传值
```
page1.qml
Rectangle
{
id:rect1
...
MouseArea {
id: maStartQuery
anchors.fill: parent
onClicked:
{
if(!stackView.busy)
stackView.push(Qt.resolvedUrl("qrc:///qml/page2.qml"),
{name:"张三"})//给page2.qml的name传值“张三”,name必须在page2.qml中定义成属性
}
}
...
}
page2.qml定义如下
Rectangle
{
id:rect2
...
property string name:""//要传的值
...
}
```
(2)page2.qml点击"确定"按钮时将结果返回给page1.qml
A.在page1.qml中增加一个函数clickedfunc当点击page2.qml中"确定"按钮时调用;
B.在page2.qml中增加一个属性containerqml用来记录page1.qml
C.在从page1.qml跳转到page2.qml时将rect1传给page2.qml的containerqml属性。
```
page1.qml
Rectangle
{
id:rect1
...
MouseArea {
id: maStartQuery
anchors.fill: parent
onClicked:
{
if(!stackView.busy)
stackView.push(Qt.resolvedUrl("qrc:///qml/page2.qml"),
{name:"张三",containerqml:rect1})
}
}
//当点击page2.qml中"确定"按钮时调用
  function clickedfunc(temp)
{
console.log("改成了:"+temp);
 stackView.pop();//返回到本页
}
...
}
page2.qml
Rectangle
{
id:rect2
...
property variant containerqml: null
property string name:""//要传的值
...
MouseArea {
id: btnOK
anchors.fill: parent
onClicked:
{
containerqml.clickedfunc("李四");//调用page1.qml中的函数实现了传返回值。
}
}
}
```
另一种就是信号与槽
### QtQuick 母版页
```
//~ Panel.qml
Item {
property alias headerHeight: headerLoader.height
property alias footerHeight: footerLoader.height
property Component headerComponent: null
readonly property Item headerItem: headerLoader.item
Loader {
id: headerLoader
width: parent.width
height: 40
sourceComponent: headerComponent
Binding {
target: headerLoader.item
property: "anchors.fill"
value: headerLoader
}
}
property Component footerComponent: null
readonly property Item footerItem: footerLoader.item
Loader {
id: footerLoader
width: parent.width
height: 40
anchors.bottom: parent.bottom
Binding {
target: footerLoader.item
property: "anchors.fill"
value: footerLoader
}
}
property Component contentComponent: null
readonly property Item contentItem: contentLoader.item
Loader {
id: contentLoader
width: parent.width
anchors.top: headerLoader.bottom
anchors.bottom: footerLoader.top;
Binding {
target: contentLoader.item
property: "anchors.fill"
value: contentLoader
}
}
}
Panel {
headerComponent: Rectangle {
color: "black"
}
footerComponent: Rectangle {
color: "black"
}
contentComponent: ListView {
delegate: Rectangle { width: parent.width; height: 40; color: "green" }
model: 10
}
}
```
### 全局单例模式
1. 入口文件的 id 和属性
2. 静态 JavaScript 文件
3. qml 单例QML 实现
4. qml 单例c++ 实现
5. 注册上下文属性
### 表单提交不包括cookies
```
function urlQuery(jsonObject) {
var query = "";
var i = 0;
for(var iter in jsonObject) {
if(i > 0) {
query += "&";
}
query += iter +"=" + encodeURI(jsonObject[iter]);
i++;
}
// console.log("url query:", query);
return query;
}
```
```
function setHeader(xhr, headers) {
//"Content-Type":"application/x-www-form-urlencoded"
for(var iter in headers) {
xhr.setRequestHeader(iter, headers[iter]);
}
}
function ajax(method, url, headers, data, callable) {
headers = headers || {};
callable = callable || function(xhr) {
console.log(xhr.responseText);
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState == xhr.DONE) {
callable(xhr);
}
}
xhr.open(method, url);
setHeader(xhr, headers);
if("GET" === method) {
xhr.send();
} else {
xhr.send(data);
}
}
```
如果带有指定名称的头部已经被指定了,这个头部的新值就是:之前指定的值,加上逗号、空白以及这个调用指定的值。
如果 open() 调用指定了认证资格XMLHttpRequest 自动发送一个适当的 Authorization 请求头部。但是,你可以使用 setRequestHeader() 来添加这个头部。类似地,如果 Web 服务器已经保存了和传递给 open() 的 URL 相关联的 cookie适当的 Cookie 或 Cookie2 头部也自动地包含到请求中。可以通过调用 setRequestHeader() 来把这些 cookie 添加到头部。XMLHttpRequest 也可以为 User-Agent 头部提供一个默认值。如果它这么做,你为该头部指定的任何值都会添加到这个默认值后面。
有些请求头部由 XMLHttpRequest 自动设置而不是由这个方法设置,以符合 HTTP 协议。这包括如下和代理相关的头部:
Host
Connection
Keep-Alive
Accept-charset
Accept-Encoding
If-Modified-Since
If-None-Match
If-Range
Range
### XMLHttpRequest设置cookie的问题
https://segmentfault.com/a/1190000004322487
### 如何获取指定objectName的QObject

View File

@@ -0,0 +1,23 @@
## 信号与槽
信号与槽都可以在qml中访问
### Q_INVOKABLE宏
在定义一个类的成员函数时使用Q_INVOKABLE宏来修饰就可以让该方法被元对象系统调用。也就是注册到元对象系统中
例如:
```
Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);
```
### Q_ENUMS宏
使用Q_ENUMS(枚举名)的方式来注册枚举类型
### Q_PROPERTY宏
Q_PROPERTY宏用来定义可通过元对象系统访问的属性通过它定义的属性可以在QML中访问、修改也可以通过在属性变化时发射特定信号。
### 注册一个QML可用类型
1. 实现c++类
2. 注册QML类型
3. 在QML中导入类型
4. 在QML中创建由c++导出的类型的实例并使用
#### 注册QML类型
1. qmlRegisterSingletonType() 用来注册单例类型
2. qmlRegisterType() 注册非单例类型
3. qmlRegisterTypeNotAvailable() 注册一个类型用来占位
4. qmlRegisterUncreateableType() 注册具有附加属性的附加类型

View File

@@ -0,0 +1,24 @@
## subdirs
新建项目-其他项目-子目录项目。
### 手动填在已有项目
直接在
```
TEMPLATE = subdirs
SUBDIRS += \
AssetEncrypt \
OutlineTool \
TechnicalSupport
```
### 编译顺序
不推荐使用顺序构建命令,因为这会损失多线程构建的性能优势。官方推荐使用编译依赖:
```
# 创建编译依赖以控制编译顺序
TechnicalSupport.depends = AssetEncrypt
TechnicalSupport.depends = OutlineTool
```
## pri
用于管理公共common pri在Pro使用include(****.pri)引入。

103
07-Other/Qt/Qt总览.md Normal file
View File

@@ -0,0 +1,103 @@
## Qt大佬blog
专栏《Qt 实战一二三》
http://blog.csdn.net/column/details/qshare.html
qyvlik
https://blog.csdn.net/qyvlik/
## QT自定义精美换肤界面
http://www.cnblogs.com/feiyangqingyun/p/3915657.html
Qt之自定义界面窗体缩放-跨平台终极版)
http://blog.csdn.net/liang19890820/article/details/50557240
## QTableView Model
QTabelView根据一行记录中的内容自动调整列宽度
http://bbs.csdn.net/topics/390639311
Qt Model/View 学习笔记 (七)
http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html
QT在QTableView中使用各种自定义委托
http://www.linuxidc.com/Linux/2012-07/66820.htm
QT中Qtableview视图表格中点击表头进行排序
http://www.cnblogs.com/googly/p/4584264.html
Qt之模型/视图(实时更新数据)
http://blog.sina.com.cn/s/blog_a6fb6cc90101hhse.html
## Qt读取excel文件
### 可以用QSqlDatabase::addDatabase("QODBC"),这个挺不错
```
QStringList referList;
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" + dir.filePath("test.xlsx"));
if(db.open())
{
QSqlQuery query("select * from [Sheet1$A:A]",db); // Select range, place A1:B5 after $
while (query.next())
{
QString dataStr= query.value(0).toString();
if(dataStr != "0")
{
referList << dataStr;
}
}
}
```
## 移植QT5.6到嵌入式开发板
http://blog.csdn.net/lizuobin2/article/details/52673494
## 判断release与debug
```
#ifdef QT_NO_DEBUG
qDebug() << "release mode";
#else
qDebug() << "debug mode";
#endif
```
## [Qt]新增UAC功能之requireAdministrator
https://blog.csdn.net/luols/article/details/49996369
https://blog.csdn.net/aqtata/article/details/17222691
## 如何把一个Qt项目拆成多个Qt子项目pro、pri使用
https://blog.csdn.net/lee353086/article/details/70808057
Qt Creator管理多个项目
https://blog.csdn.net/csxiaoshui/article/details/44102873
## 在Qt程序退出前时执行函数
https://stackoverflow.com/questions/8165487/how-to-do-cleaning-up-on-exit-in-qt
## Qt自定义委托在QTableView中绘制控件、图片、文字
http://blog.csdn.net/zhi379/article/details/28412189
## 加密你的SQLite
http://foggry.com/blog/2014/05/19/jia-mi-ni-de-sqlite/
## QML分辨率适配
QML 中的屏幕适配问题
http://blog.csdn.net/qyvlik/article/details/51241425
QML怎么适配不同的设备
http://blog.csdn.net/zhx6044/article/details/44180819
## QGraphicsView
QGraphicsView 框架学习(一)、图形元素的编辑
https://blog.csdn.net/wishfly/article/details/77817091?locationNum=3&fps=1
Qt基础——获取QGraphicsScene的缩略图即导出到图片
https://blog.csdn.net/lcl_data/article/details/8731892
Qt绘图之QGraphicsScene QGraphicsView QGraphicsItem详解
https://www.cnblogs.com/cy568searchx/p/3502242.html
Qt 之图形视图框架
https://blog.csdn.net/liang19890820/article/details/51966791
QGraphicsView 框架学习(一)
https://blog.csdn.net/firebolt2002/article/details/46583589
基于Qt QGraphicsView的多点触摸绘图
https://www.cnblogs.com/visonme/p/5435330.html
QGraphicsScene 管理 QGraphicsItem单击/选择/移动/缩放/删除)
https://blog.csdn.net/liang19890820/article/details/53504323

View File

@@ -0,0 +1,70 @@
## 前言
因为Sqlite的源代码中只提供了Sqlite3_key()的接口没有实现。所以Qt中的Sqlite没有密码功能。于是我找了一下资料并且总结一下思路。现成的方法在最后。
## SQLite历代版本与下载
所有ReleaseTag:https://www.sqlite.org/cgi/src/taglist
SQLite不提供明确的下载地址所以地址需要开发者去猜……也就是通过最新的地址以及你所需要的版本号去推
例如:
- sqlite-amalgamation-3240000https://www.sqlite.org/2018/sqlite-amalgamation-3240000.zip
- sqlite-dll-win32-x86-3240000.ziphttps://www.sqlite.org/2018/sqlite-dll-win32-x86-3240000.zip
- sqlite-dll-win64-x64-3240000.ziphttps://www.sqlite.org/2018/sqlite-dll-win64-x64-3240000.zip
- sqlite-amalgamation-3270200.ziphttps://www.sqlite.org/2019/sqlite-amalgamation-3270200.zip
- sqlite-dll-win64-x64-3270200.ziphttps://www.sqlite.org/2019/sqlite-dll-win64-x64-3270200.zip
注意:
- 年份
- 版本号的小数点位在百位上
## 解决思路与大致过程
编写一个QSQLDriver Plugins并且实现Sqlite3_key()。
### 大致步骤
- 在QtCreator中文件-新建文件或者项目-Library-c++Library来创建QSQLDriver Plugins库类型选择Qt Plugin
- 下载Qt源代码并将\qtbase\src\plugins\sqldrivers\sqlite下的qsql_sqlite_p.h与qsql_sqlite.cpp文件复制到新建的插件目录下。
- 修改2个文件中类名与创建插件的类名一致。并且修改open()函数(具体的请看参考资料)。
- 下载sqlite源代码并且实现Sqlite3_key()注意该函数被宏设置为不编译。可以通过在项目中设置来解决也可以在头文件中直接设置宏为1来解决。
- Sqlite3_key()的实现方法可以参考wxsqlite3或CipherSqlite。
## 现成的解决方法
国人编写的插件QtCipherSqlitePlugin。经测试5.14.2 MSVC2017 x64可以使用。使用起来很方便直接用Qt打开sqlitecipher文件夹中的工程直接切成release模式编译即可。
作者推荐的方法是将编译出lib与dll都放入源代码中的不过我个人还是喜欢使用在项目中直接加载Plugin的方式来实现。这样可以方便后续的项目迁移与后续维护。大致代码如下
```
QPluginLoader driverload(qApp->applicationDirPath()+"/plugin/sqldrivers/sqlitecipher.dll");
if(driverload.load())
{
QSqlDriverPlugin *plugin=qobject_cast<QSqlDriverPlugin*>(driverload.instance());
if(plugin)
{
QSqlDriver *driver=plugin->create("SQLITECIPHER");
QSqlDatabase db;
db=QSqlDatabase::addDatabase(driver);
db.setDatabaseName("mydatabase.db");
db.setPassword("123456");
if(db.open())
{
QSqlQuery qry(db);
qry.exec("create table t_trade(order_id varchar(100))");
qry.exec("insert into t_trade(order_id) values('10001')");
qry.exec("insert into t_trade(order_id) values('10002')");
qry.exec("select * from t_trade");
while(qry.next())
{
qDebug()<<qry.value(0).toString();
}
}
}
}
```
PS.debug与release的dll是不通用的所以需要编译两份dll并且载入时进行判断
- QtCipherSqlitePlugin地址
https://github.com/devbean/QtCipherSqlitePlugin
- 编译方法https://github.com/devbean/QtCipherSqlitePlugin/wiki/How-to-compile
- 使用方法https://github.com/devbean/QtCipherSqlitePlugin/wiki/How-to-use
## 参考资料
- https://www.devbean.net/2012/07/qt-sqlite-plugin-with-encryption/
- https://www.cnblogs.com/WushiShengFei/p/9707244.html

View File

@@ -0,0 +1,163 @@
## 前言
最近有个pdf的需求Qt竟然没有显示pdf的api着实令人郁闷。之后我尝试用了poppler但是光配置编译工程就相当麻烦了没有cmake等开源项目编译经验的人完全一脸懵逼。PDFium也是同理手头上没有vpn也无法尝试。感觉Mupdf编译器起来比较简单所以就来用了一下。
本人使用的版本是Mupdf1.12.0+Qt5.9.3+vs2015
## 下载Mupdf库
https://mupdf.com/downloads/
## 编译Mupdf
在mupdf-1.12.0-source\platform\win32目录下就有现成的mupdf.sln。
这里需要注意:这个工程默认使用的是/MT而Qt MSVC默认用的是/MD,所以需要修改编译工程设置。我们这里只需要在编译工程中修改就可以了。
以下是一些有关QMake中设置运行库属性 /md /md /mt /mtd 的相关参考
- http://blog.csdn.net/caoshangpa/article/details/51416077
- http://www.cnblogs.com/codingmylife/archive/2010/05/08/1730832.html
- http://www.voidcn.com/article/p-hhosrsia-hq.html
工程里默认生成的是都是静态库请注意根据测试需要的分别是libmupdf.lib、libresources.lib、libthirdparty.lib这三个库只使用了docs\examples\example.c的代码使用别的函数可能需要再编译别的工程
分别修改解决方案中的libmupdf、libthirdparty、libresources这三个工程将debug下改成/MDdrelease下改成/MD编译即可得到这3个文件。其中libresources只有release版本的所以debug模式下我也引用这个文件。
## 在Qt工程中引入Mupdf静态库
- 引入lib文件
- 新建一个工程在工程的图标上右键——添加库——外部库。平台只勾选windows链接选择静态之后选择对应的库就可以了。本人将debug与release编译的分别放在debug与release文件夹中
- 添加包含目录
- 将Mupdf目录中的include复制到工程目录下本人又新建了一个mupdf将所有文件都放在里面了
- 本人是这么写的,具体可以参考源代码:
- `INCLUDEPATH += $$PWD/mupdf/include/`
之后运行QMake。
## 编写代码进行测试
```c++
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QDebug>
#include <QImage>
#include <QPixmap>
#include <QLabel>
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
char *input = const_cast< char* >("document.pdf");
float zoom, rotate;
int page_number, page_count;
fz_context *ctx;
fz_document *doc;
fz_pixmap *pix;
fz_matrix ctm;
int x, y;
//第一页为0
page_number=1;
//100%缩放比
zoom=100;
//旋转为0
rotate=0;
//创建上下文
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
if (!ctx)
{
qDebug()<<stderr<<"cannot create mupdf context";
return;
}
//注册文档控制
fz_try(ctx)
fz_register_document_handlers(ctx);
fz_catch(ctx)
{
qDebug()<<stderr<<"cannot register document handlers:"<< fz_caught_message(ctx);
fz_drop_context(ctx);
return;
}
//打开文档
fz_try(ctx)
doc = fz_open_document(ctx, input);
fz_catch(ctx)
{
qDebug()<<stderr<< "cannot open document:"<< fz_caught_message(ctx);
fz_drop_context(ctx);
return;
}
//取得总的页数
fz_try(ctx)
page_count = fz_count_pages(ctx, doc);
fz_catch(ctx)
{
qDebug()<<stderr<< "cannot count number of pages:"<< fz_caught_message(ctx);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return;
}
if (page_number < 0 || page_number >= page_count)
{
qDebug()<<stderr<< "page number out of range: "<< page_number + 1<<"page count:"<<page_count;
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return;
}
//计算缩放以及旋转
fz_scale(&ctm, zoom / 100, zoom / 100);
fz_pre_rotate(&ctm, rotate);
//渲染pixmap
fz_try(ctx)
pix = fz_new_pixmap_from_page_number(ctx, doc, page_number, &ctm, fz_device_rgb(ctx), 0);
fz_catch(ctx)
{
qDebug()<<stderr<< "cannot render page: %s\n"<< fz_caught_message(ctx);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return;
}
//渲染成图片
// unsigned char *samples = fz_pixmap_samples(ctx, pix);
unsigned char *samples = pix->samples;
int width = fz_pixmap_width(ctx, pix);
int height = fz_pixmap_height(ctx, pix);
QImage image(samples, width, height,QImage::Format_RGB888);
QLabel *label=new QLabel;
label->setPixmap(QPixmap::fromImage(image));
ui->layout->addWidget(label);
// if (!image.save("a.png")) {
// return;
// }
//回收内存
fz_drop_pixmap(ctx, pix);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
}
Widget::~Widget()
{
delete ui;
}
```
## 参考代码 
https://github.com/blueroseslol/QtMupdf
找到一个之前有人封装的库不过经过测试是无法成功编译的不过可以参考一下mupdf库的用法。
https://github.com/xiangxw/mupdf-qt
别的参考:
http://blog.csdn.net/chenyijun/article/details/42582977