Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

OsgEarth开发经验记录

发表于 2022-09-21 | 更新于 2022-11-18

OsgEarth嵌入QT5方法

  • 使用osgQT
  • 使用QOpenGLWidget

OsgEarth数字地球显示变形问题

解决方案请参考解决osgearh程序运行后对象变形的问题。

OsgEarth开发时的一些问题

请参考OpenSceneGraph FAQ。

添加HUD到场景的三种方式

作为viewer的子相机;

作为viewer下根节点的一个子节点;

使用CompositeViewer,添加一个HUDView,使得HUDCamera作为HUDView的主相机。

着色器自定义

参考链接

  1. [osgearth]oe学习的一些经验(别人的),by 南水之源.
  2. osgEarth嵌入qt的实现方式,by codeantenna.
  3. 利用Qt来显示OSG并且设置相机的位置,by wb175208.
  4. Qt加载Osg的新方式osgQOpenGL简介,by sun_xf1.
  5. OsgEarth 2.x升级到3.1注意事项,by 孙高勇.
  6. OSGEARTH教程(三)——搭建MFC桌面端程序框架,by 灰信网.
  7. 解决osgearh程序运行后对象变形的问题,by codeantenna.
  8. osg地球变形的解决方案,by 紫沐衙.
  9. OpenSceneGraph FAQ,by 水流云在.
  10. OSG3.4内置Examples(osghud)解析,by 3wwang.
  11. HUD with perspective,by arnaud houegbelo.
  12. how a hud-camera respond to the resize event,by wu xiaodong.
  13. OSG开发概览,by ShaPherD.
  14. OpenGL ES 多目标渲染(MRT),by 字节流动.
  15. [原][译]关于osgEarth::VirtualProgram说明,by 南水之源.
  16. osgearth学习笔记2:星空效果显示,by 新晋小菜鸟.

CPlusPlus之DLL分析

发表于 2022-09-21

使用vcpkg安装各类C++库很方便,但是在使用vcpkg安装osg、osgearth后,使用如下程序测试osg和osgearth,出现了一个小问题,3D模型不显示,说是找不到插件。

刚开始以为是vcpkg安装osg、osgearth出了问题,后面发现将vcpkg中编译生成的osg的plugin放到测试程序所在目录,发现能加载3D模型了,但是渲染纹理失败。

于是自己编译osg源码,发现测试程序能加载3D模型。最终结论是vcpkg编译安装osg了问题。此外,可参考process explorer 查看句柄或者加载的dll,分析测试程序加载的osg插件。

1
2
3
4
5
6
7
8
9
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>

int main(int argc, char *argv[])
{
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("cow.osg"));
return viewer.run();
}

参考链接

  1. process explorer 查看句柄或者加载的dll,by yasi_xi.
  2. osg程序中osgDB::writeNodeFile和osgDB::readNodeFile总是失败,by 妙为.

Goolge C++风格指南学习笔记

发表于 2022-09-19 | 更新于 2022-09-20

背景

C++ 是 Google 的许多开源项目使用的主要开发语言之一。每个 C++ 程序员都知道,该语言具有许多强大的特性,但这种能力带来了复杂性,这反过来又会使代码更容易出错,更难阅读和维护。

本指南的目标是通过详细描述编写 C++ 代码的注意事项来管理这种复杂性。这些规则的存在是为了保持代码库的可管理性,同时仍然允许编码人员高效地使用 C++ 语言功能。

样式,也称为可读性,是我们所说的支配我们的 C++ 代码的约定。术语样式有点用词不当,因为这些约定不仅仅涵盖源文件格式。

风格指南

风格检查

Cpplint 是一个命令行工具,用于按照Google 的 C++ 样式指南检查 C/C++ 文件的样式问题。Cpplint 由 Google Inc. 在google/styleguide开发和维护

参考链接

  1. cpplint,by google.
  2. Google C++ Style Guide,by google.
  3. 四种基本的编程命名规范(匈牙利命名法、驼峰式命名法、帕斯卡命名法、下划线命名法),by f-zyj.

Qt开发实战记录

发表于 2022-09-14 | 更新于 2024-08-13

QT 开发配置

QT 环境配置

请参考:

  • Qt创建Qt Designer自定义控件及使用
  • Qt编写自定义控件及插件的使用
  • 【QT-版本】QT版本对应windows及数据库
  • Qt LIBS .pro文件内相对路径的问题(已解决)

QT 建立带子项目的工程

请参考:

  • Qt 建立带有子项目的工程

使用VS打开QT项目

请参考:

  • 使用VS 打开QT项目

QxORM 使用帮助

请参考:

  • QxORM MySQL使用

QT 核心机制与原理

QT信号槽

请参考:

  • QT信号槽连接两个不同的类
  • Qt信号与槽使用方法最完整总结

QT中paintEvent事件的触发时间

当发生一下情况时会产生绘制事件并调用paintEvent()函数:

  1. 在窗口部件第一次显示时,系统会自动产生一个绘图事件,从而强制绘制这个窗口部件。

  2. 当重新调整窗口部件的大小时,系统也会产生一个绘制事件。

  3. 当窗口部件被其他窗口部件遮挡,然后又再次显示出来的时候,就会对那些隐藏的区域产生一个绘制事件。

osgQOpenGLWidget中paintEvent事件的定时触发

请参考:

  • QObject的timerEvent使用。

QThread线程使用

QThread 的两种使用方法:

请参考:

  • Qt学习:子线程QThread的使用。
  • QThread 的使用方法
  • QT从入门到入土(五(1))——多线程(QThread)

网络通信

请参考:

  • Qt之UDP编程
  • Qt学习(十五)—— 网络通信之UDP
  • Qt网络编程(2):QUdpSocket的基本使用
  • qt hasPendingDatagrams() 函数

QT 控件使用方法

QMenuBar、QMenu、QAction的使用方法

请参考

  • Qt QMenuBar和QMenu以及QAction巧妙的使用方法。
  • qt中的菜单QMenu QAction

Spacer部件使用方法

请参考:

  • Qt Designer的Spacers部件详解

Splitter部件使用方法

请参考:

  • QSplitter分割界面 初始比例

QTableView部件使用方法

请参考:

  • QTableWidget与QTableView的区别
  • Qt5 ui界面下显示数据库内容,tableView用法
  • QTableView实现在表格内直接对数据库内容进行修改、新增和删除等操作

QDateTimeEdit部件

请参考:

  • Qt 之 QDateEdit 和 QTimeEdit
  • QDateEdit 设置为空,显示日历

QComboBox部件

请参考:

  • C++ Qt QComboBox使用教程
  • 2021.6.6:QT——QComboBox下拉框及用法

QGroupBox部件

请参考:

  • 【Qt】界面组织大师:Qt中的容器控件QGroupBox与QTabWidget

QT MVC

请参考:

  • QSortFilterProxyModel实现QTreeView的过滤的缺点和改进
  • QFileSystemModel and QSortFilterProxyModel don’t work well together?
  • QFileSystemModel and QSortFilterProxyModel - root index is not preserved
  • QSortFilterProxyModel的使用

QT 自定义QAbstractListModel

请参考:

  • How to use QAbstractListModel
  • Subclassing QFileSystemModel to filter images by size

自定义控件

请参考:

  • Qt实战12.可自由展开的ToolBox
  • Qt:53—Widget组件的自定义与提升(promoted)
  • Qt创建Qt Designer自定义控件及使用
  • Qt Designer 插件测试报错问题

QT 界面美化

QT资源文件

请参考:

  • QT添加资源文件并使用

QT样式表

请参考:

  • Qt | 关于样式表的使用 QStyleSheet
  • Qt:62—Qt样式表(setStyleSheet函数、.qss文件)
  • QT添加qss文件和资源文件

QT 部署

QT 安装包制作

请参考:

  • Qt5+安装包制作(Qt Installer Framework)

QT 具体实践

请参考:

  • Qt中登录界面跳转到主界面的两种方法

参考链接

  1. Qt实战12.可自由展开的ToolBox,by 罗祥.
  2. Qt匿名函数 - Lambda,by automoblie0.
  3. VS2019 This application failed to start because no Qt platform plugin could be initialized,by KeyeSssss.
  4. Qt 5.15 LTS版本 安装教程 在线安装,by 超级大洋葱806.
  5. Qt之QAbstractButton属性验证,by 小黑屋1024.
  6. Qt update刷新之源码分析(一),by IT文艺男.
  7. QT关键问题解决之paintevent理解,by Jeacean.
  8. Qt中openGL的四个重要事件(initializeGL() resizeGL() paintGL() pdateGL())调用规则,by AplusX.
  9. QOpenGLWidget 揭秘,by SolidMango.
  10. 通过QOpenGLWidget绘制三角形,by 张诺谦.
  11. QT中paintEvent事件的触发时间,by 星辰大海.
  12. QObject的timerEvent使用,by 随便看看.
  13. Qt中QTimer和timerevent的区别与用法,by lusanshui.
  14. Qt学习:子线程QThread的使用,by 壁立千仞无欲则刚.
  15. Qt QMenuBar和QMenu以及QAction巧妙的使用方法,by Imagine Miracle.
  16. qt中的菜单QMenu QAction,by swartz_lubel.
  17. QWidget禁止最大化 ,by mb5fca0c87ea3a4.
  18. How to use QAbstractListModel,by wiki.qt.

Vue2修改对象的属性值视图不更新解决方法

发表于 2022-09-09 | 更新于 2023-01-31

在使用vuejs开发过程中,有时候出现修改对象属性后,视图并没有更新的问题。下面分析其产生原因并给出解决方法。

产生原因

Vue2使用双向数据绑定,当你把一个普通的 JavaScript 对象传入 Vue2 实例作为 data 选项,Vue2 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

因此,vue2 无法检测 property 的添加或移除。由于 Vue2 会在初始化实例时对 property 执行 getter/setter转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。对于已经创建的实例,Vue允许动态添加根级别的响应式 property。

解决方法

  • Vue.set()

Vue.set(object,key,value)方法一次只能添加一个属性,例如:

1
this.$set(this.message,'b',"我手一杯 品尝你的美");
  • Object.assign或_.extend()

Object.assign或_.extend()可以往数据对象上添加多个属性,但是需要创建同时包含原属性、新属性的对象,从而有效触发watch()方法。例如:

1
this.message = Object.assign({},this.message,{b:'我手一杯 品尝你的美',c:'留下唇印的嘴'})

参考链接

  1. vue修改对象属性,视图不更新this.$set和Vue.nextTick([callback,context]),by 青争小台.
  2. vue响应式数据-修改对象的属性值,视图不更新,by codeantenna.
  3. Vue3的响应式原理?一篇文章,八张图,三心为你解密~,by Sunshine_Lin.
  4. Vue3响应式原理解析,by liy1wen.

MySQL断电崩溃数据恢复方法

发表于 2022-09-08 | 更新于 2023-07-07

服务器使用wamp提供web服务,因断电导致mysql无法启动。下面记录恢复mysql的方法流程。

服务器配置

  • wampserver 3.2.0
  • apache 2.4.41
  • php 7.3.12
  • mysql 8.0.18

mysql数据库恢复过程

故障表现

mysql后台服务无法启动。查找mysql.log日志文件发现innodb数据库引擎报如下错误,说明mysql表空间损坏,线程在数据页中读取不到需要的 page 和数据,因此判断mysql的innodb奔溃了。

1
[ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=86, page number=4]. You may have to recover from a backup.

修复方法

启动mysql后台服务

首先使用mysql的Forcing InnoDB Recovery特性,启动mysql后台服务。打开my.ini配置文件,设置如下:

1
innodb_force_recovery=1

再重启mysql后台服务成功。

innodb_force_recovery 可以设置为 1-6,大的值包含前面所有小于它的值的影响。

1
2
3
4
5
6
7
8
9
10
11
1 (SRV_FORCE_IGNORE_CORRUPT): 忽略检查到的 corrupt 页。尽管检测到了损坏的 page 仍强制服务运行。一般设置为该值即可,然后 dump 出库表进行重建。

2 (SRV_FORCE_NO_BACKGROUND): 阻止主线程的运行,如主线程需要执行 full purge 操作,会导致 crash。 阻止 master thread 和任何 purge thread 运行。若 crash 发生在 purge 环节则使用该值。

3 (SRV_FORCE_NO_TRX_UNDO): 不执行事务回滚操作。

4 (SRV_FORCE_NO_IBUF_MERGE): 不执行插入缓冲的合并操作。如果可能导致崩溃则不要做这些操作。不要进行统计操作。该值可能永久损坏数据文件。若使用了该值,则将来要删除和重建辅助索引。

5 (SRV_FORCE_NO_UNDO_LOG_SCAN): 不查看重做日志,InnoDB 存储引擎会将未提交的事务视为已提交。此时 InnoDB 甚至把未完成的事务按照提交处理。该值可能永久性的损坏数据文件。

6 (SRV_FORCE_NO_LOG_REDO): 不执行前滚的操作。恢复时不做 redo log roll-forward。使数据库页处于废止状态,继而可能引起 B 树或者其他数据库结构更多的损坏。

注意:

1
2
3
4
5
6
7
8
9
为了安全,当设置参数值大于 0 后,可以对表进行 select, create, drop 操作,但 insert, update 或者 delete 这类操作是不允许的。MySQL 5.6.15 以后,当 innodb_force_recovery 的值大于等于 4 的时候,InnoDB 表处于只读模式。

在值小于等于 3 时可以通过 select 来 dump 表,可以 drop 或者 create 表。MySQL 5.6.27 后大于 3 的值也支持 DROP TABLE;

如果事先知道哪个表导致了崩溃则可 drop 掉这个表。如果碰到了由失败的大规模导入或大量 ALTER TABLE 操作引起的 runaway rollback,则可 kill 掉 mysqld 线程然后设置 innodb_force_recovery = 3 使数据库重启后不进行 rollback。然后删除导致 runaway rollback 的表;

如果表内的数据损坏导致不能 dump 整个表内容。那么附带 order by primary_key desc 从句的查询或许能够 dump 出损坏部分之后的部分数据;

若使用更高的 innodb_force_recovery 值,那么一些损坏的数据结构可能引起复杂的查询无法运行。此时可能只能运行最基本的 select * from table 语句。

修复备份mysql数据库

使用如下命名自动修复数据库:

1
mysqlcheck -u root -p --all-databases --auto-repair

修复完成后,使用如下命令备份重要数据库的数据:

1
2
3
4
5
6
7
8
9
10
# 备份全部数据库(包含存储过程、自定义函数及事件) 
mysqldump -uroot -p --single-transaction -R -E --all-databases > /tmp/all_database.sql

# 备份指定数据库
mysqldump -uroot -p --single-transaction -R -E --databases db1 > /tmp/db1.sql
mysqldump -uroot -p --single-transaction -R -E --databases db1 db2 > /tmp/db1_db2.sql

# 备份部分表
mysqldump -uroot -pxxxxxx --single-transaction db1 tb1 > /tmp/tb1.sql
mysqldump -uroot -pxxxxxx --single-transaction db1 tb1 tb2 tb3 > /tmp/tb.sql

注意:一定要先修复再备份,防止备份数据时因页表错误丢失数据。

完成修复备份后,注释my.ini中innodb_force_recovery,再重启mysql数据库后台服务,如果成功,则修复完成。如果未成功,则准备利用备份数据重建数据库。

wamp备份修复

当mysql遭遇严重错误,修复备份后仍然不能启动,可考虑重装wamp。具体操作如下:

  • 备份整个wamp文件夹,以便保留mysql数据库文件、apache、php关键配置文件等。
  • 重装wamp后,重建mysql数据库,重设apache、php关键配置,参考之前备份的wamp文件夹
  • apache主要配置httpd.conf和httpd-vhost.conf,设置documentroot和vhost
  • php主要配置php.ini文件
1
2
3
4
5
# 针对mysql 8.0.18,使用如下命令修改root密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '123456'

# 通过增加参数 --default-character-set = utf8 解决乱码问题
mysql -u root -p < path_to_import_file --default-character-set = utf8

重装后配置遇到的问题请参考:

  • 关于Apache本地能访问外网不能访问的问题
  • php中的时区设置和php.ini中配置时区的方法
  • 设置修改 Apache 文件根目录 (Document Root)

参考链接

  1. mysql InnoDB crash and recover,by Fisher.
  2. 利用 Forcing InnoDB Recovery 特性解决 MySQL 重启失败的问题,by GlonHo.
  3. INFORMATION_SCHEMA获取元数据,by 十五十六.
  4. MySQLDump的备份小技巧,by MySQL技术.
  5. MYSQL 自带4个默认数据库,by bolang100.
  6. wamp设置mysql8.0.18初始密码问题,by PHPer.
  7. MySQL字符集和排序规则,by 流逝的傷.
  8. 关于Apache本地能访问外网不能访问的问题,by programminghunter.
  9. php中的时区设置和php.ini中配置时区的方法,by quyu.
  10. 设置修改 Apache 文件根目录 (Document Root),by needrunning.
  11. windows 下自动备份mysql数据库,删除以前的数据库文件,by 森林屿麓.
  12. windows下mysql自动备份脚本,by 雪竹子.

Vuejs生成Doc文档示例

发表于 2022-08-27 | 更新于 2023-04-17

文档生成

请参考使用vue+docxtemplater导出word。

文档预览

请参考docx-preview实现移动端word文件预览。

PDF预览

使用docx-preview的文档预览方案不够完善,显示不够完美,因此采用后端使用docxtemplater文档生成,再使用libreoffice-convert转换成pdf,再下载到前端使用pdfjs预览pdf的方案。

开发环境

  • nodejs: v12.18.4
  • express: “^4.18.2”
  • docxtemplater: “^3.36.1”
  • libreoffice-convert: “^1.4.1”
  • spark-md5: “^3.0.2”
  • pdfjs: 2.16.105

注意:在使用libreoffice-convert将docx转换成pdf之前,需要安装libre office软件,使用默认配置安装。

参考链接

  1. 使用vue+docxtemplater导出word,by 实迷途其未远.
  2. 详细|vue中使用PDF.js预览文件实践,by 灵扁扁.
  3. docx-preview实现移动端word文件预览,by LXLong.
  4. vue项目,npm install方式使用pdfjs,by 下一秒.
  5. Vue 实现 PDF 文件在线预览 - 手把手教你写 Vue PDF 预览功能,by 蒋川.
  6. PDF.js访问远程服务器报file origin does not match viewer’s,by 心灵的学霸.
  7. 深入理解xhr responseType blob arrayBuffer document text json使用,by 柚子=_=.
  8. 【实战分享】js生成word(docx),以及将word转成pdf解决方案分享,by 前端开发小陈.
  9. libreoffice-convert not working in nodejs,by stackoverflow.

Vuejs内联编辑简单示例

发表于 2022-08-27 | 更新于 2022-08-28

示例1

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div class="app-container">
<div v-for="field in fields" :key="field.id" class="editable-field">
<template v-if="editedFieldId === field.id">
<input type="text" v-model="field.value" :ref="`field${field.id}`" />
<button class="btn" @click.prevent="toggleEdit">
<template>Save</template>
</button>
</template>
<template v-else>
<span class="editable-text">
{{ field.value }}
</span>
<button class="btn" @click.prevent="toggleEdit(field.id)">Edit</button>
</template>
</div>
</div>
</template>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export default {
name: "InlineEdit",
props: {},
data() {
return {
editedFieldId: null,
fields: [
{
id: 1,
value: "Editable field 1",
},
{
id: 2,
value: "Editable field 2",
},
],
};
},
created() { },
mounted() { },
methods: {
toggleEdit(id) {
if (id) {
this.editedFieldId = id;
this.$nextTick(() => {
if (this.$refs["field" + id]) {
this.$refs["field" + id][0].focus();
}
});
} else {
this.editedFieldId = null;
}
},
},
};

示例2

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div class="container">
<input
type="text"
v-if="edit"
:value="valueLocal"
@blur="onBlur($event)"
@keyup.enter="onKeyEnter($event)"

v-focus
/>
<span v-else @click="edit = true">
{{ valueLocal }}
</span>
</div>
</template>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script>
export default {
name: "ClickToEdit",
props: ["value"],

data() {
return {
edit: false,
valueLocal: this.value,
};
},

watch: {
value: function () {
this.valueLocal = this.value;
},
},

directives: {
focus: {
inserted(el) {
el.focus();
},
},
},

methods:{
onBlur(ev){
this.valueLocal = ev.target.value;
this.edit = false;
this.$emit('input', this.valueLocal);
},
onKeyEnter(ev){
this.valueLocal = ev.target.value;
this.edit = false;
this.$emit('input', this.valueLocal);
}
}
};
</script>

参考链接

  1. Vue Inline edit,by yobyzal.
  2. Building a form with inline editing,by stackoverflow.
  3. Simple inline editable fields with Vue.js,by devrecipes.

遗传算法简介

发表于 2022-08-21

能够生存下来的往往不是最强大的物种,也不是最聪明的物种,而是最能适应环境的物种。

参考链接

  1. 一文读懂遗传算法工作原理(附Python实现),by 深度学习初学者.

写作技巧集锦

发表于 2022-08-13

删掉“我认为”、“我觉得”、“我相信”等

先写标题

写出音乐感

“triad”(三合音)

CTA = call to action

一寸相框

简单和清晰

不说副词

填满画布

参考链接

  1. 10个实用写作技巧,by happy xiao.
上一页1…131415…52下一页

Jack Huang

519 日志
66 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse