├── .gitignore ├── ChangeLogs.md ├── DeployQt.pro ├── LICENSE ├── Qml ├── About │ └── About.qml ├── Common │ ├── ComboBox.qml │ ├── ContentBar.qml │ ├── MyButton.qml │ ├── MyComboBox.qml │ └── RoundRectangle.qml ├── TipsDialog.qml └── main.qml ├── README.md ├── Resource ├── Qtbig.png └── Qtbig_qrcode.jpg ├── Test ├── Qt程序打包工具V1.0.gif ├── Qt程序打包工具V1.0.mp4 ├── Qt程序打包工具V1.0.png └── exe_demo │ ├── Qt_5_12_2_MSVC_2017_x86_Release_QML_Plugin_Test.exe │ ├── Qt_5_12_2_MSVC_2017_x86_Release_QML_Test.exe │ ├── Qt_5_12_2_MSVC_2017_x86_Release_Test.exe │ └── Qt_5_12_2_Mingw_730_x86_Release_Test.exe ├── ToolsModel.cpp ├── ToolsModel.h ├── VersionModel.cpp ├── VersionModel.h ├── app.ico ├── main.cpp ├── qml.qrc └── resources.qrc /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | Thumbs.db 33 | *.res 34 | *.rc 35 | /.qmake.cache 36 | /.qmake.stash 37 | 38 | # qtcreator generated files 39 | *.pro.user* 40 | 41 | # xemacs temporary files 42 | *.flc 43 | 44 | # Vim temporary files 45 | .*.swp 46 | 47 | # Visual Studio generated files 48 | *.ib_pdb_index 49 | *.idb 50 | *.ilk 51 | *.pdb 52 | *.sln 53 | *.suo 54 | *.vcproj 55 | *vcproj.*.*.user 56 | *.ncb 57 | *.sdf 58 | *.opensdf 59 | *.vcxproj 60 | *vcxproj.* 61 | 62 | # MinGW generated files 63 | *.Debug 64 | *.Release 65 | 66 | # Python byte code 67 | *.pyc 68 | 69 | # Binaries 70 | # -------- 71 | *.dll 72 | *.exe 73 | 74 | -------------------------------------------------------------------------------- /ChangeLogs.md: -------------------------------------------------------------------------------- 1 | ## v1.0.1版本 2 | * 修正在mingw编译器编译的程序可能打包不成功的问题。 3 | 4 | ## v1.0版本 5 | * 新增关于页面; 6 | * 完善错误处理; 7 | * 修正若干Bug。 8 | 9 | ## v0.9版本 10 | * 建立打包工具基础功能。 11 | -------------------------------------------------------------------------------- /DeployQt.pro: -------------------------------------------------------------------------------- 1 | #********************************************************** 2 | #Author: Qt君 3 | #微信公众号: Qt君 4 | #QQ群: 732271126 5 | #Email: 2088201923@qq.com 6 | #LICENSE: MIT 7 | #********************************************************** 8 | QT += quick qml core 9 | CONFIG += c++11 10 | 11 | # The following define makes your compiler emit warnings if you use 12 | # any Qt feature that has been marked deprecated (the exact warnings 13 | # depend on your compiler). Refer to the documentation for the 14 | # deprecated API to know how to port your code away from it. 15 | DEFINES += QT_DEPRECATED_WARNINGS 16 | 17 | # You can also make your code fail to compile if it uses deprecated APIs. 18 | # In order to do so, uncomment the following line. 19 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 20 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 21 | 22 | SOURCES += \ 23 | main.cpp \ 24 | VersionModel.cpp \ 25 | ToolsModel.cpp 26 | 27 | RC_ICONS = app.ico 28 | RESOURCES += \ 29 | Resources.qrc \ 30 | Qml.qrc 31 | 32 | # Additional import path used to resolve QML modules in Qt Creator's code model 33 | QML_IMPORT_PATH = 34 | 35 | # Additional import path used to resolve QML modules just for Qt Quick Designer 36 | QML_DESIGNER_IMPORT_PATH = 37 | 38 | # Default rules for deployment. 39 | qnx: target.path = /tmp/$${TARGET}/bin 40 | else: unix:!android: target.path = /opt/$${TARGET}/bin 41 | !isEmpty(target.path): INSTALLS += target 42 | 43 | HEADERS += \ 44 | VersionModel.h \ 45 | ToolsModel.h 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 aeagean 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Qml/About/About.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | import ToolsModel 1.0 10 | import "../Common" 11 | 12 | Rectangle { 13 | id: root 14 | width: 640; height: 480 15 | 16 | MouseArea { anchors.fill: parent } 17 | 18 | Row { 19 | anchors.centerIn: parent 20 | width: parent.width - 10; height: parent.height - 10 21 | spacing: 20 22 | 23 | Column { 24 | y: 10 25 | width: parent.width * 0.25; 26 | spacing: 30 27 | 28 | Column { 29 | width: parent.width; height: width + 40 30 | spacing: 10 31 | 32 | Image { 33 | width: parent.width; height: width 34 | source: "qrc:/Resource/Qtbig.png" 35 | } 36 | 37 | Text { 38 | anchors.horizontalCenter: parent.horizontalCenter 39 | text: "作者: Qt君" 40 | } 41 | } 42 | 43 | Column { 44 | width: parent.width 45 | height: width + 40 46 | clip: true 47 | 48 | Image { 49 | anchors.horizontalCenter: parent.horizontalCenter 50 | width: parent.width + 23; height: width 51 | source: "qrc:/Resource/Qtbig_qrcode.jpg" 52 | } 53 | 54 | Text { 55 | anchors.horizontalCenter: parent.horizontalCenter 56 | text: "扫码关注" 57 | } 58 | } 59 | } 60 | 61 | Column { 62 | id: rightBar 63 | y: 10 64 | width: parent.width * 0.75 - 20 65 | spacing: 15 66 | 67 | Repeater { 68 | model: [ 69 | { 70 | title: "适用范围: ", 71 | content: "1. Window系统;\n2. Qt5.0版本以上编译的程序。" 72 | }, 73 | { 74 | title: "使用方法: ", 75 | content: "1. 将需要打包的程序拖拽到打包工具中;\n2. 选择该程序编译时的Qt版本和编译器版本;\n3. 点击生成;\n4. 最后测试。" 76 | }, 77 | { 78 | title: "注意: ", 79 | content: "程序引入的第三方库需要用户自己复制到运行程序目录下。" 80 | }, 81 | { 82 | title: "获取更多", 83 | content: "" 84 | } 85 | ] 86 | 87 | Item { 88 | width: rightBar.width 89 | height: displayInfo.height 90 | 91 | Column { 92 | id: displayInfo 93 | spacing: 10 94 | Text { 95 | id: title 96 | text: modelData.title 97 | font.pixelSize: 25 98 | } 99 | 100 | Text { 101 | id: content 102 | text: modelData.content 103 | lineHeight: 1.5 104 | } 105 | } 106 | 107 | } 108 | } 109 | 110 | 111 | Repeater { 112 | model: [ 113 | { 114 | content: "源码地址: https://github.com/aeagean/DeployQt", 115 | buttonText: "打开", 116 | url: "https://github.com/aeagean/DeployQt" 117 | }, 118 | { 119 | content: "Big哥网站: http://www.qtbig.com", 120 | buttonText: "打开", 121 | url: "http://www.qtbig.com" 122 | }, 123 | ] 124 | 125 | Item { 126 | width: parent.width 127 | height: 10 128 | 129 | Text { 130 | id: sourceCode 131 | anchors.left: parent.left 132 | anchors.verticalCenter: parent.verticalCenter 133 | text: modelData.content 134 | } 135 | 136 | MyButton { 137 | anchors.right: parent.right 138 | anchors.verticalCenter: parent.verticalCenter 139 | width: 60; height: 20 140 | text: modelData.buttonText 141 | onClicked: toolsModel.openUrl(modelData.url) 142 | } 143 | } 144 | } 145 | 146 | Item { 147 | width: parent.width; height: 55 148 | 149 | MyButton { 150 | x: 150 151 | anchors.verticalCenter: parent.verticalCenter 152 | width: 80; height: 35 153 | text: "返回" 154 | onClicked: root.visible = false 155 | } 156 | } 157 | } 158 | } 159 | 160 | ToolsModel { 161 | id: toolsModel 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Qml/Common/ComboBox.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | Item { 11 | id: root 12 | 13 | /// 此属性拥有组合框中当前项的索引。默认值为-1,当count为0时-1,其他情况为0或其他。 14 | property alias currentIndex: _listView.currentIndex 15 | 16 | /** 17 | * @brief: 此属性拥有组合框中当前项的文本。 18 | * @note: read-only 19 | */ 20 | property string currentText: _listView.currentText 21 | 22 | /// 此属性为组合框提供数据模型。 23 | property alias model: _listView.model 24 | 25 | /// 此属性可以判断组合框是否被按下。按钮可以通过触摸或按键事件按下。 26 | property alias pressed: mouseArea.pressed 27 | 28 | /// 此属性可以判断组合框是否处于展开状态。 29 | property bool down: false; 30 | 31 | /** 32 | * @brief: 组合框中项数。 33 | * @note: read-only 34 | */ 35 | property alias count: _listView.count 36 | 37 | /** 38 | * @brief 该属性为组合框代理项。 39 | * @note: 自定义delegate需要手动设置down属性与currentIndex属性以隐藏下拉列表和设置下拉列表当前项。 40 | */ 41 | property Component delegate: _private.defaultDelegate 42 | 43 | /// 用于设置指示器,标识组合框是否处于展开状态。常用的设置为三角形指示器。 44 | property Component indicator: _private.defaultIndicator 45 | 46 | /// 用于设置组合框的可视项。 47 | property Component contentItem: _private.defaultContentItem 48 | 49 | /// 用于设置组合框的可视项的背景。 50 | property Component background: _private.defaultBackground 51 | 52 | /// 用于设置下拉框的背景项,设置其宽高可以限制下拉框的大小。默认展示下拉框的三个项目。 53 | property Component popup: _private.defaultPopup 54 | 55 | width: 150; 56 | height: 40 57 | 58 | /// background 59 | Loader { 60 | id: backgroundId 61 | sourceComponent: background 62 | } 63 | 64 | /// contentItem 65 | Item { 66 | width: contentItemId.item.width 67 | height: contentItemId.item.height 68 | 69 | Loader { 70 | id: contentItemId 71 | sourceComponent: contentItem 72 | } 73 | 74 | MouseArea { 75 | id: mouseArea 76 | anchors.fill: parent 77 | onReleased: root.down = !root.down 78 | } 79 | } 80 | 81 | /// indicator 82 | Loader { 83 | id: indicatorId 84 | sourceComponent: indicator 85 | } 86 | 87 | /// popup 88 | /// 下拉列表ListView 89 | Loader { 90 | id: popupId 91 | y: contentItemId.item.height 92 | visible: root.down 93 | clip: true 94 | sourceComponent: popup 95 | 96 | ListView { 97 | id: _listView 98 | z: popupId.item.z + 1 99 | property string currentText: "" 100 | width: popupId.item.width 101 | height: popupId.item.height 102 | clip: true 103 | delegate: root.delegate 104 | onCurrentIndexChanged: currentText = model[currentIndex] 105 | } 106 | } 107 | 108 | /* Private */ 109 | QtObject { 110 | id: _private 111 | property Component defaultDelegate: Rectangle { 112 | width: root.width; height: root.height 113 | 114 | Text { 115 | anchors.verticalCenter: parent.verticalCenter 116 | anchors.left: parent.left 117 | anchors.leftMargin: 20 118 | /* 鼠标进入会显示对应高亮文字。 */ 119 | color: delegateMouseArea.isEnter ? "#4cbeff" : "black" 120 | text: modelData 121 | font.bold: true 122 | font.pixelSize: 17 123 | } 124 | 125 | Rectangle { 126 | id: line 127 | anchors.horizontalCenter: parent.horizontalCenter 128 | anchors.bottom: parent.bottom 129 | width: parent.width - 40 130 | height: 1 131 | color: "#e6e8ea" 132 | /* 最后一个项不隐藏分隔线。 */ 133 | visible: index !== root.count - 1 134 | } 135 | 136 | MouseArea { 137 | id: delegateMouseArea 138 | property bool isEnter: false 139 | anchors.fill: parent 140 | hoverEnabled: true /* 开启鼠标实时捕抓。 */ 141 | onEntered: isEnter = true 142 | onExited: isEnter = false 143 | onClicked: { 144 | /* 当选项被选中后需要用户设置down的状态为false,以让下拉列表收起来。 */ 145 | /* 还需设置currentIndex的值,以至于可以刷新contentItem的文字显示。 */ 146 | root.down = false 147 | root.currentIndex = index 148 | } 149 | } 150 | } 151 | 152 | property Component defaultIndicator: Item { 153 | width: root.width; height: root.height 154 | 155 | /* 三角形指示器 */ 156 | Item { 157 | anchors.verticalCenter: parent.verticalCenter 158 | anchors.verticalCenterOffset: 2 159 | anchors.right: parent.right 160 | anchors.rightMargin: 15 161 | clip: true 162 | width: 2*height; height: 7 163 | 164 | Rectangle { 165 | anchors.horizontalCenter: parent.horizontalCenter 166 | anchors.verticalCenter: parent.verticalCenter 167 | anchors.verticalCenterOffset: -parent.height/2 168 | width: Math.sqrt(parent.width*parent.width*2)/2; height: width 169 | color: root.down ? "white" : "#4cbeff" 170 | rotation: 45 171 | } 172 | } 173 | } 174 | 175 | property Component defaultContentItem: Rectangle { 176 | width: root.width; height: root.height 177 | color: root.down ? "#4cbeff" : "white" 178 | border.width: root.down ? 0 : 1 179 | border.color: "#d5d5d5" 180 | 181 | /* 显示当前下拉列表选中的内容 */ 182 | Text { 183 | anchors.verticalCenter: parent.verticalCenter 184 | anchors.left: parent.left 185 | anchors.leftMargin: 20 186 | color: root.down ? "white" : "#333333" 187 | text: root.currentText 188 | font.bold: true 189 | font.pixelSize: 17 190 | } 191 | } 192 | 193 | property Component defaultBackground: Item { } 194 | 195 | /* 设置popup可以设置下拉框的高度和宽度 */ 196 | property Component defaultPopup: Rectangle { 197 | width: root.width; height: root.count < 3 ? root.count * root.height : root.height * 3 198 | border.color: "#d5d5d5" 199 | border.width: 2 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Qml/Common/ContentBar.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | Item { 11 | id: root 12 | property alias text: content.text 13 | default property alias items: row.children 14 | 15 | Row { 16 | id: row 17 | Item { 18 | width: root.width*0.3 19 | height: root.height 20 | 21 | Text { 22 | id: content 23 | anchors.centerIn: parent 24 | font.pixelSize: 17 25 | } 26 | } 27 | } 28 | 29 | Component.onCompleted: { 30 | items[1].width = root.width*0.7 - 5 31 | items[1].height = root.height 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Qml/Common/MyButton.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | RoundRectangle { 11 | id: root 12 | property alias text: content.text 13 | signal clicked() 14 | 15 | color: mouseArea.pressed ? "#4cbeff" : "white" 16 | radius: 8 17 | border.color: mouseArea.pressed ? "#00000000" : "#d5d5d5" 18 | 19 | Text { 20 | id: content 21 | anchors.centerIn: parent 22 | color: mouseArea.pressed ? "white" : "#333333" 23 | font.pixelSize: 17 24 | } 25 | 26 | MouseArea { 27 | id: mouseArea 28 | anchors.fill: parent 29 | onClicked: root.clicked() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Qml/Common/MyComboBox.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | ComboBox { 11 | id: root 12 | model: ["One", "Two", "Three", "Four", "Five"] 13 | 14 | background: Item { } 15 | 16 | contentItem: RoundRectangle { 17 | width: root.width; height: root.height 18 | color: root.down ? "#4cbeff" : "white" 19 | radius: 8 20 | radiusCorners: root.down ? (Qt.AlignLeft | Qt.AlignRight | Qt.AlignTop) : 21 | (Qt.AlignLeading | Qt.AlignRight | Qt.AlignTop | Qt.AlignBottom) 22 | 23 | border.color: root.down ? "#00000000" : "#d5d5d5" 24 | 25 | Text { 26 | anchors.verticalCenter: parent.verticalCenter 27 | anchors.left: parent.left 28 | anchors.leftMargin: 20 29 | color: root.down ? "white" : "#333333" 30 | text: root.currentText 31 | font.bold: true 32 | font.pixelSize: 17 33 | } 34 | } 35 | 36 | indicator: Item { 37 | width: root.width; height: root.height 38 | 39 | Item { 40 | anchors.verticalCenter: parent.verticalCenter 41 | anchors.right: parent.right 42 | anchors.rightMargin: 20 43 | width: Math.sqrt(_triangle.width*_triangle.width*2); height: width/2 44 | clip: true 45 | 46 | Rectangle { 47 | id: _triangle 48 | anchors.horizontalCenter: parent.horizontalCenter 49 | anchors.bottom: parent.bottom 50 | anchors.bottomMargin: parent.height/4 51 | width: 12; height: width 52 | color: root.down ? "white" : "#4cbeff" 53 | rotation: 45 54 | } 55 | } 56 | } 57 | 58 | delegate: Item { 59 | width: root.width; height: root.height 60 | 61 | Text { 62 | anchors.verticalCenter: parent.verticalCenter 63 | anchors.left: parent.left 64 | anchors.leftMargin: 20 65 | color: delegateMouseArea.isEnter ? "#4cbeff" : "black" 66 | text: modelData 67 | font.bold: true 68 | font.pixelSize: 17 69 | } 70 | 71 | Rectangle { 72 | id: line 73 | anchors.horizontalCenter: parent.horizontalCenter 74 | anchors.bottom: parent.bottom 75 | width: parent.width - 40 76 | height: 1 77 | color: "#e6e8ea" 78 | visible: index !== root.count - 1 79 | } 80 | 81 | MouseArea { 82 | id: delegateMouseArea 83 | property bool isEnter: false 84 | anchors.fill: parent 85 | hoverEnabled: true 86 | onEntered: isEnter = true 87 | onExited: isEnter = false 88 | onClicked: { 89 | root.down = false 90 | root.currentIndex = index 91 | } 92 | } 93 | } 94 | 95 | popup: Rectangle { 96 | width: root.width; height: root.count < 3 ? root.count * root.height : root.height * 3 97 | border.color: "#d5d5d5" 98 | border.width: 1 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /Qml/Common/RoundRectangle.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | Rectangle { 11 | id: root 12 | property int radiusCorners: Qt.AlignLeft | Qt.AlignRight | Qt.AlignTop | Qt.AlignBottom /* Default: */ 13 | /* 14 | Qt.AlignLeft | Qt.AlignLeft | Qt.AlignRight | Qt.AlignLeft | Qt.AlignLeft | 15 | Qt.AlignRight | Qt.AlignTop | Qt.AlignTop | Qt.AlignRight | Qt.AlignRight | 16 | None:0 Qt.AlignTop | Qt.AlignBottom Qt.AlignBottom Qt.AlignTop Qt.AlignBottom 17 | Qt.AlignBottom 18 | ***************** ************* *************** *************** ************* ***************** 19 | * * * * * * * * * * * * 20 | * * * * * * * * * * * * 21 | * * * * * * * * * * * * 22 | * * * * * * * * * * * * 23 | * * * * * * * * * * * * 24 | * * * * * * * * * * * * 25 | * * * * * * * * * * * * 26 | ***************** ************* *************** *************** ***************** ************* 27 | */ 28 | 29 | Repeater { 30 | model: [ { 31 | x: 0, 32 | y: 0, 33 | visible: internal.aligns(Qt.AlignLeft | Qt.AlignTop), 34 | radius: root.radius 35 | }, 36 | { 37 | x: root.width - root.radius, 38 | y: 0, 39 | visible: internal.aligns(Qt.AlignRight | Qt.AlignTop), 40 | radius: root.radius 41 | }, 42 | { 43 | x: 0, 44 | y: root.height - root.radius, 45 | visible: internal.aligns(Qt.AlignLeft | Qt.AlignBottom), 46 | radius: root.radius 47 | }, 48 | { 49 | x: root.width - root.radius, 50 | y: root.height - root.radius, 51 | visible: internal.aligns(Qt.AlignRight | Qt.AlignBottom), 52 | radius: root.radius 53 | } ] 54 | 55 | Rectangle { 56 | x: modelData.x; y: modelData.y 57 | width: modelData.radius; height: width 58 | visible: !modelData.visible 59 | color: parent.color 60 | } 61 | } 62 | 63 | QtObject { 64 | id: internal 65 | 66 | function aligns(direction) { 67 | return (root.radiusCorners & direction) === direction 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Qml/TipsDialog.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | 10 | Rectangle { 11 | id: root 12 | property alias text: content.text 13 | 14 | color: "#90000000" 15 | visible: false 16 | 17 | MouseArea { anchors.fill: parent } 18 | 19 | Rectangle { 20 | anchors.centerIn: parent 21 | width: root.width * 0.7; 22 | height: root.height * 0.4; 23 | radius: 8 24 | 25 | Text { 26 | id: content 27 | anchors.centerIn: parent 28 | font.pixelSize: 20 29 | } 30 | } 31 | 32 | Timer { 33 | id: delayTimer 34 | repeat: false 35 | onTriggered: hide() 36 | } 37 | 38 | function show(content) { 39 | root.text = content 40 | visible = true 41 | } 42 | 43 | function hide() { 44 | visible = false 45 | } 46 | 47 | function delayHide(msecond) { 48 | delayTimer.interval = msecond 49 | delayTimer.start() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Qml/main.qml: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | import QtQuick 2.0 9 | import QtQuick.Window 2.2 10 | import VersionMode 1.0 11 | 12 | import "./Common" 13 | import "./About" 14 | 15 | Window { 16 | id: root 17 | visible: true 18 | flags: Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint 19 | | Qt.WindowTitleHint | Qt.WindowCloseButtonHint 20 | | Qt.CustomizeWindowHint | Qt.WindowSystemMenuHint 21 | | Qt.WindowMinimizeButtonHint | Qt.WindowStaysOnTopHint 22 | width: 640 23 | height: 480 24 | title: qsTr("Qt程序打包工具v1.0.1") 25 | 26 | DropArea { 27 | anchors.fill: parent; 28 | onEntered: { 29 | var isValid = true 30 | 31 | if (! drag.hasUrls) 32 | isValid = false; 33 | 34 | if (drag.urls.length !== 1) 35 | isValid = false; 36 | 37 | var suffix = drag.urls[0].substr(-4, 4) 38 | if (suffix !== ".exe" && suffix !== ".EXE") 39 | isValid = false; 40 | 41 | if (! isValid) { 42 | drag.accepted = false 43 | } 44 | else { 45 | _private.lineEnable = true 46 | } 47 | } 48 | 49 | onExited: _private.lineEnable = false 50 | 51 | onDropped: { 52 | _private.lineEnable = false 53 | var firstUrl = drop.urls[0] 54 | var lastSlashPosition = firstUrl.lastIndexOf('/')+1 55 | var displayFile = firstUrl.substring(lastSlashPosition) 56 | 57 | _private.displayExeFile = displayFile 58 | versionMode.exeFile = firstUrl.substr(8) // remove prefix "file:///" 59 | } 60 | 61 | } 62 | 63 | Column { 64 | anchors.verticalCenter: parent.verticalCenter 65 | width: parent.width 66 | spacing: 15 67 | 68 | ContentBar { 69 | z: 2 70 | width: parent.width 71 | height: 40 72 | text: "选择Qt版本" 73 | 74 | MyComboBox { 75 | model: versionMode.qtVersionList 76 | onCurrentTextChanged: versionMode.qtVersion = currentText 77 | } 78 | } 79 | 80 | ContentBar { 81 | z: 1 82 | width: parent.width 83 | height: 40 84 | text: "选择编译器版本" 85 | 86 | MyComboBox { 87 | model: versionMode.compilerVersionList 88 | onCurrentTextChanged: versionMode.compilerVersion = currentText 89 | } 90 | } 91 | 92 | Item { 93 | width: parent.width 94 | height: 240 95 | 96 | Rectangle { 97 | anchors.centerIn: parent 98 | width: parent.width - 8; height: parent.height - 4 99 | color: "#fafbfc" 100 | radius: 4 101 | border.color: "#e1e4e8" 102 | border.width: 2 103 | 104 | Rectangle { 105 | anchors.centerIn: parent 106 | width: parent.width - 8; height: parent.height - 8 107 | color: "#dddddd" 108 | visible: _private.lineEnable 109 | radius: parent.radius 110 | } 111 | 112 | Text { 113 | id: exeFileText 114 | property string defaultText: "拖拽程序到此处" 115 | anchors.centerIn: parent 116 | color: text === defaultText ? "gray" : "black" 117 | font.pixelSize: 30//text === defaultText ? 30 : 20 118 | text: _private.displayExeFile.length === 0 ? defaultText : _private.displayExeFile 119 | } 120 | } 121 | } 122 | 123 | MyButton { 124 | anchors.horizontalCenter: parent.horizontalCenter 125 | width: parent.width - 10 126 | height: 40 127 | text: "生成" 128 | onClicked: { 129 | if (versionMode.exeFile.length === 0) { 130 | tipsDialog.show("请添加目标程序") 131 | tipsDialog.delayHide(1500) 132 | return 133 | } 134 | 135 | tipsDialog.show("正在生成") 136 | delayCreate.start() 137 | } 138 | } 139 | 140 | Row { 141 | anchors.horizontalCenter: parent.horizontalCenter 142 | width: parent.width - 10 143 | spacing: 5 144 | 145 | MyButton { 146 | width: (parent.width - 5)/2 147 | height: 40 148 | text: "测试" 149 | onClicked: { 150 | if (versionMode.exeFile.length === 0) { 151 | tipsDialog.show("请添加目标程序") 152 | tipsDialog.delayHide(1500) 153 | return 154 | } 155 | 156 | tipsDialog.show("正在打开[" + _private.displayExeFile + "]") 157 | 158 | delayTest.start() 159 | } 160 | } 161 | 162 | MyButton { 163 | width: (parent.width - 5)/2 164 | height: 40 165 | text: "关于" 166 | onClicked: aboutDialog.visible = true 167 | } 168 | } 169 | } 170 | 171 | About { 172 | id: aboutDialog 173 | visible: false 174 | } 175 | 176 | TipsDialog { 177 | id: tipsDialog 178 | anchors.fill: parent 179 | } 180 | 181 | VersionMode { 182 | id: versionMode 183 | } 184 | 185 | QtObject { 186 | id: _private 187 | property bool lineEnable: false 188 | property string displayExeFile: "" 189 | } 190 | 191 | Timer { 192 | id: delayCreate 193 | repeat: false; 194 | interval: 300 195 | onTriggered: { 196 | if (! versionMode.create()) { 197 | tipsDialog.show("生成失败, 请检查编译器是否存在。") 198 | tipsDialog.delayHide(3000) 199 | } 200 | else { 201 | tipsDialog.show("生成成功") 202 | tipsDialog.delayHide(2000) 203 | } 204 | } 205 | } 206 | 207 | Timer { 208 | id: delayTest 209 | repeat: false; 210 | interval: 300 211 | onTriggered: { 212 | if (! versionMode.test()) { 213 | tipsDialog.show("测试失败,切换编译器试试。") 214 | tipsDialog.delayHide(1500) 215 | } 216 | else { 217 | tipsDialog.delayHide(500) 218 | } 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | | 下载地址 | 2 | | --- | 3 | | [打包工具运行文件](https://github.com/aeagean/DeployQt/releases/download/v1.0.1/QtDeploy-v1.0.1.rar) | 4 | 5 | # Qt程序打包工具(最新版本v1.0.1) 6 | > 由于Qt软件提供的windeployqt采用命令行操作,打包程序起来相对繁琐。而现有大多数的打包工具又不能针对Qt而打包,往往是一些库打包不成功,又或者操作繁琐。如果有一个可视化的傻瓜式的打包工具就好了。也就是这一原因,决定写这个基于Windows系统的可视化Qt打包程序,并开源其代码供大家一起学习进步。 7 | 8 |  9 | 10 | ## 1. 适用范围 11 | * Window系统; 12 | * Qt5.0版本以上release版本编译的程序; 13 | * 暂时不支持debug版本打包,后续会添加。 14 | 15 | ## 2. 使用方法 16 | 1. 将需要打包的程序拖拽到打包工具中; 17 | 2. 选择该程序编译时的Qt版本和编译器版本; 18 | 3. 点击生成; 19 | 4. 最后测试。 20 | 21 | ## 3. 注意 22 | * 不能打包引入的第三方库,需要自己复制到程序运行目录下 23 | 24 | ## 4. 下载使用(最新版本v1.0.1) 25 | * [最新源代码下载地址](https://github.com/aeagean/DeployQt/archive/master.zip) 26 | * [最新执行文件下载地址](https://github.com/aeagean/DeployQt/releases/download/v1.0.1/QtDeploy-v1.0.1.rar) 27 | 28 | ## 5. 关于更新 29 | * 了解最新版本详见: [更新记录](https://github.com/aeagean/DeployQt/blob/master/ChangeLogs.md) 30 | * 获取版本列表: [版本列表](https://github.com/aeagean/DeployQt/releases) 31 | 32 | ## 6. 关于作者 33 | |Qt君公众号(每天更新)|Qt君| 34 | |---|---| 35 | |Qt君个人网站|[www.qtbig.com](http://www.qtbig.com)| 36 | |QQ交流群|732271126| 37 | 38 |
39 |
40 |
微信扫一扫关注公众号
41 | 42 | -------------------------------------------------------------------------------- /Resource/Qtbig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Resource/Qtbig.png -------------------------------------------------------------------------------- /Resource/Qtbig_qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Resource/Qtbig_qrcode.jpg -------------------------------------------------------------------------------- /Test/Qt程序打包工具V1.0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/Qt程序打包工具V1.0.gif -------------------------------------------------------------------------------- /Test/Qt程序打包工具V1.0.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/Qt程序打包工具V1.0.mp4 -------------------------------------------------------------------------------- /Test/Qt程序打包工具V1.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/Qt程序打包工具V1.0.png -------------------------------------------------------------------------------- /Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_QML_Plugin_Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_QML_Plugin_Test.exe -------------------------------------------------------------------------------- /Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_QML_Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_QML_Test.exe -------------------------------------------------------------------------------- /Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/exe_demo/Qt_5_12_2_MSVC_2017_x86_Release_Test.exe -------------------------------------------------------------------------------- /Test/exe_demo/Qt_5_12_2_Mingw_730_x86_Release_Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aeagean/DeployQt/594463aee2b78f55b1539aaaf89fb95c58c8a896/Test/exe_demo/Qt_5_12_2_Mingw_730_x86_Release_Test.exe -------------------------------------------------------------------------------- /ToolsModel.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | Author: Qt君 3 | 微信公众号: Qt君(首发) 4 | QQ群: 732271126 5 | Email: 2088201923@qq.com 6 | LICENSE: MIT 7 | **********************************************************/ 8 | #include "ToolsModel.h" 9 | #include