LTalk
部分界面
登录界面
学习该项目之前你应该了解
- CMake基础编译 -推荐使用高版本Cmake,最好是兼容交叉编译安卓的版本
- QML技术,Qt库,qt使用5.13.1版本
- Golang,使用Golang go version go1.15.6 windows/amd64
- Docker
- Redis,Mysql,Sqlite:redis
使用到的第3方库
- Qt,gRPC,qtprotobuf,sqlite_orm,fluid
第一章
如何编写基于qml的界面
main函数
#include <QDir>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "framelessquickhelper.h"//framelesshelper第3方库
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
#endif
QApplication a(argc, argv);
QFont font;
font.setPixelSize(20);
font.setWeight(70);
a.setFont(font);
qmlRegisterType<FramelessQuickHelper>("wangwenx190.Utils", 1, 0, "FramelessHelper");//注册第3方库,便于后面qml使用
QQmlApplicationEngine engine;
engine.addImportPath(QCoreApplication::applicationDirPath() + QLatin1String("/lib/qml"));
engine.addImportPath("qrc:/");
engine.load("qrc:/login.qml");//加载登录界面
return a.exec();
}
login.qml
- 如果你使用的和我不是一个版本的Qt那么请修改对应QtQuick的版本否则无法显示
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Controls 2.13
import "qrc:/" as Components //自己内部实现的控件
import wangwenx190.Utils 1.0//framelesshelper
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.12
import Fluid.Controls 1.1 as FluidControls //fluid
import Qt.labs.platform 1.1
FluidControls.ApplicationWindow {
id: window
width: 400
height: 500
visible: true
maximumHeight: 500
maximumWidth: 400
minimumWidth: 400
minimumHeight: 500
color: "#f0f0f0"
title: qsTr("LTalk")
Material.primary: Material.LightBlue
Material.accent: Material.Blue
property int sideMargin: 30
property int _flh_margin: ((window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen)) ? 0 : (1 / Screen.devicePixelRatio)
FramelessHelper {
id: framelessHelper
}
Rectangle {
id: mainContainer
color: "#ffffff"
anchors.fill: parent
clip: true
Keys.onPressed: {
if ((event.key == Qt.Key_Enter) || (event.key == Qt.Key_Return)) {
if(!isInvaild()) {
HttpApiEngine.login(usernameInput.text,passwordInput.text);
}
}
}
Rectangle {
id:toolBtnRect
anchors.right: parent.right
anchors.top: parent.top
z: 10
Row {
anchors.top: parent.top
anchors.right: parent.right
Components.MinisizeButton{
id: minisizeButton
onClicked: window.showMinimized()
Component.onCompleted: framelessHelper.addIgnoreObject(minisizeButton)
}
Components.CloseButton {
id: closeButton
onClicked: window.setVisible(false)
Component.onCompleted: framelessHelper.addIgnoreObject(closeButton)
}
}
}
Rectangle {
id: formSection
color: "#00000000"
anchors.fill: parent
Row {
id:loginMode
anchors.top: parent.top
anchors.topMargin:50
anchors.left:parent.left
anchors.right:parent.right
anchors.leftMargin:sideMargin
anchors.rightMargin:sideMargin
anchors.horizontalCenter: parent.horizontalCenter
Components.UnderlineButton {
id:accoutLogin
width:window.width/2 - sideMargin
height:40
checked:true
text: qsTr("账号登录")
font.pixelSize:20
onClicked: {
accoutLogin.checked = true
qrCodeLogin.checked = false
}
}
Components.UnderlineButton {
id:qrCodeLogin
width:window.width/2 - sideMargin
height:40
text: qsTr("扫码登录")
font.pixelSize:20
onClicked: {
qrCodeLogin.checked = true
accoutLogin.checked = false
}
}
}
TextField {
id: usernameInput
anchors.left: parent.left
anchors.top: loginMode.bottom
anchors.leftMargin: sideMargin
anchors.rightMargin: sideMargin
anchors.topMargin: 40
anchors.horizontalCenter: parent.horizontalCenter
width:300
height:50
font.bold:true
font.letterSpacing : 1
font.pixelSize:22
z: 20
placeholderText:qsTr("请输入账号")
background: Rectangle {
y: usernameInput.height - height - usernameInput.bottomPadding + 8
implicitWidth: 120
height: usernameInput.activeFocus || usernameInput.hovered ? 2 : 1
color: "#aaaaaa"
opacity:0.5
}
}
TextField {
id: passwordInput
anchors.left: parent.left
anchors.top: usernameInput.bottom
anchors.leftMargin: sideMargin
anchors.rightMargin: sideMargin
anchors.topMargin: 30
anchors.horizontalCenter: parent.horizontalCenter
z: 20
width:300
height:50
font.bold:true
font.letterSpacing : 1
font.pixelSize:22
echoMode:TextInput.Password
placeholderText:qsTr("请输入密码")
background: Rectangle {
y: passwordInput.height - height - passwordInput.bottomPadding + 8
implicitWidth: 120
height: passwordInput.activeFocus || passwordInput.hovered ? 2 : 1
color: "#aaaaaa"
opacity:0.5
}
}
Row{
id:passWordRow
anchors.top: passwordInput.bottom
anchors.left: parent.left
anchors.leftMargin: sideMargin
anchors.rightMargin: sideMargin
anchors.right: parent.right
CheckBox {
checked: true
anchors.left: parent.left
font.pixelSize: 16
text: qsTr("记住密码")
Components.StandardButton {
id: forgotPasswordButton
anchors.right:parent.right
text: qsTr("忘记密码")
textColor: "#545454"
buttonColor: "#ffffff"
}
}
Button {
id:loginButton
text: qsTr("登录")
highlighted: true
anchors.top: passWordRow.bottom
anchors.topMargin: 50
anchors.left:passWordRow.left
anchors.right:passWordRow.right
height:60
font.pixelSize:22
font.bold: true
Material.background: Material.Cyan
contentItem: Text {
text: loginButton.text
font: loginButton.font
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
onClicked:{
if(!isInvaild()) {
HttpApiEngine.login(usernameInput.text,passwordInput.text);
}
}
}
Button {
anchors.top: loginButton.bottom
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("企业账号登录")
flat: true
highlighted: true
}
Label {
id: termLabel
color: "#8E8E8E"
text: qsTr("登录即视为同意《服务协议》及《隐私政策》")
anchors.bottomMargin: 10
anchors.bottom: parent.bottom
font.pixelSize: 14
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}
}
}
}
Rectangle {
id: windowFrame
anchors.fill: parent
color: "transparent"
border {
color: framelessHelper.nativeFrameColor
width: window._flh_margin
}
}
FluidControls.SnackBar {
id: snackBar
duration:10000
fullWidth: true
}
Component.onCompleted: framelessHelper.removeWindowFrame()
function isInvaild() {
if(usernameInput.text === "" || usernameInput.text === "") {
snackBar.open("输入框不能为空","重试");
return true;
}
return false;
}
}
UnderlineButton.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
AbstractButton {
id: control
text: qsTr("Button")
font.bold: control.checked
background: Rectangle {
y: control.height - height - control.bottomPadding + 8
implicitWidth: 120
height: control.checked ? 2 : 1
color: control.checked ? control.Material.accentColor : control.Material.hintTextColor
}
contentItem: Text {
text: control.text
font: control.font
color: control.enabled ? control.Material.foreground : control.Material.hintTextColor
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
horizontalAlignment:Text.AlignHCenter
}
}
MinisizeButton.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ToolButton {
id: button
implicitWidth: 45
implicitHeight: 30
contentItem: Image {
anchors.fill: parent
source: "qrc:/resource/icons/button_minimize_black.svg"
}
background: Rectangle {
visible: button.down || button.hovered
color: button.down ? "#808080" : (button.hovered ? "#c7c7c7" : "transparent")
}
}
CloseButton.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ToolButton {
id: button
implicitWidth: 45
implicitHeight: 30
contentItem: Image {
anchors.fill: parent
source: button.down
|| button.hovered ? "qrc:/resource/icons/button_close_white.svg" : "qrc:/resource/icons/button_close_black.svg"
}
background: Rectangle {
visible: button.down || button.hovered
color: button.down ? "#8c0a15" : (button.hovered ? "#e81123" : "transparent")
}
}