当前位置: 首页 > article >正文

八、系统托盘与配置面板

没有人会把你变得越来越好,时间和经历只是陪衬。

支撑你变得越来越好的,是你自己坚强的意志、修养、品行、以及不断的反思和经验。

人生最好的贵人,就是努力向上的自己。

一、系统托盘

1、资源文件夹

新建资源文件夹,我们需要把图片相关资源都放到这里,

这里我们新建一个 icon 文件夹,并且放入一个 cloud.png 图片作为系统托盘图标。

2、代码实现

我们使用 QMenu  来创建系统托盘菜单,使用 QAction 来定义菜单项,并且绑定对应的菜单触发事件,具体代码如下: 

void MainWindow::initSysTrayIcon(){
    ptrSysTrayIcon = new QSystemTrayIcon(QIcon(":/icon/cloud.png"), this);
    // 创建托盘菜单
    QMenu *trayMenu = new QMenu();

    // 添加设置菜单项
    QAction *settingsAction = new QAction("设置", this);
    QObject::connect(settingsAction, &QAction::triggered, this, &MainWindow::openSettingsWindow);
    trayMenu->addAction(settingsAction);

    // 添加退出菜单项
    QAction *exitAction = new QAction("退出", this);
    QObject::connect(exitAction, &QAction::triggered, this, &QCoreApplication::quit);
    trayMenu->addAction(exitAction);

    // 将菜单关联到托盘图标
    ptrSysTrayIcon->setContextMenu(trayMenu);

    // 显示托盘图标
    ptrSysTrayIcon->show();
}

3、显示托盘

在主窗口构造方法设置系统托盘,

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    initWindowSettings();
    initSysTrayIcon();
}

void MainWindow::initSysTrayIcon(){
    ptrSysTrayIcon = new QSystemTrayIcon(QIcon(":/icon/cloud.png"), this);
    // 创建托盘菜单
    QMenu *trayMenu = new QMenu();

    // 添加设置菜单项
    QAction *settingsAction = new QAction("设置", this);
    QObject::connect(settingsAction, &QAction::triggered, this, &MainWindow::openSettingsWindow);
    trayMenu->addAction(settingsAction);

    // 添加退出菜单项
    QAction *exitAction = new QAction("退出", this);
    QObject::connect(exitAction, &QAction::triggered, this, &QCoreApplication::quit);
    trayMenu->addAction(exitAction);

    // 将菜单关联到托盘图标
    ptrSysTrayIcon->setContextMenu(trayMenu);

    // 显示托盘图标
    ptrSysTrayIcon->show();
}

运行之后,我们就可以在系统托盘中看到自定义的图标,并且右键后可以显示自定义的两个菜单。

二、配置面板

通过系统托盘菜单,我们需要跳转到对应的配置面板,对模型人物进行参数调整。

1、配置面板UI

UI 设计:添加角色下拉框,用来切换角色,添加三个滑动条分别控制 X 轴、Y 轴以及模型缩放比例,

2、UI 插槽

UI 头文件添加 slots,绑定控件事件,

#ifndef SETTINGSWINDOW_H
#define SETTINGSWINDOW_H

#include <QMainWindow>

#include <QScreen>
#include <QGuiApplication>

namespace Ui {
class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit SettingsWindow(QWidget *parent = nullptr);
    ~SettingsWindow();
private slots:
    void onComboBoxRoleIndexChanged(int index);
    void onScaleValueChanged(int value);
    void onTranslateXValueChanged(int value);
    void onTranslateYValueChanged(int value);
private:
    Ui::SettingsWindow *ui;
};

#endif // SETTINGSWINDOW_H

切换人物,

void SettingsWindow::onComboBoxRoleIndexChanged(int index){
    qDebug() << "onComboBoxRoleIndexChanged, Selected Index:" << index;
    LAppLive2DManager::GetInstance()->ChangeScene(index);
}

模型缩放,

void SettingsWindow::onScaleValueChanged(int value)
{
    // Scale [0,1]
    qDebug() << "Scale Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->Scale(value*0.01f,value*0.01f);

}

X轴平移,

void SettingsWindow::onTranslateXValueChanged(int value)
{
    // TranslateX [-2,2]
    qDebug() << "TranslateX Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateX(value*0.01f);

}

Y轴平移,

void SettingsWindow::onTranslateYValueChanged(int value)
{
    // TranslateY [-2,2]
    qDebug() << "TranslateY Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateY(value*0.01f);
}

三、参数记忆

配置面板设置了参数,只是临时的,并没有保存到配置文件,下次启动时,还是需要重新配置,为了解决这个问题,我们引入 QSettings 实现参数记忆。

1、记录当前人物

void SettingsWindow::onComboBoxRoleIndexChanged(int index){
    qDebug() << "onComboBoxRoleIndexChanged, Selected Index:" << index;
    QSettings settings("myapp.ini", QSettings::IniFormat);
    settings.setValue("Settings/Role", ui->comboBoxRole->currentText());
    settings.setValue("Settings/Index", index);
    LAppLive2DManager::GetInstance()->ChangeScene(index);
}

2、记录放缩比例 

void SettingsWindow::onScaleValueChanged(int value)
{
    // Scale [0,1]
    qDebug() << "Scale Value " << value * 0.01f;
    QSettings settings("myapp.ini", QSettings::IniFormat);
    settings.setValue("Settings/ScaleX", value);
    settings.setValue("Settings/ScaleY", value);
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->Scale(value*0.01f,value*0.01f);
}

3、记录X轴平移

void SettingsWindow::onTranslateXValueChanged(int value)
{
    // TranslateX [-2,2]
    qDebug() << "TranslateX Value " << value * 0.01f;
    QSettings settings("myapp.ini", QSettings::IniFormat);
    settings.setValue("Settings/TranslateX", value);
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateX(value*0.01f);
}

4、记录Y轴平移

void SettingsWindow::onTranslateYValueChanged(int value)
{
    // TranslateY [-2,2]
    qDebug() << "TranslateY Value " << value * 0.01f;
    QSettings settings("myapp.ini", QSettings::IniFormat);
    settings.setValue("Settings/TranslateY", value);
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateY(value*0.01f);
}

四、启动参数

在第三步,我们记录了模型参数,接下来实现在启动时根据参数来渲染模型。

1、实现原理

通过源代码 debug,不难发现渲染逻辑是通过 LAppLive2DManager 类的构造方法调用 ChangeScene 方法渲染模型,

2、代码实现

修改构造方法, 我们先从 myapp.ini 配置文件中获取参数,如果没有参数则采用默认值,

LAppLive2DManager::LAppLive2DManager()
    : _viewMatrix(NULL)
    , _sceneIndex(0)
{
    _viewMatrix = new CubismMatrix44();

    // ChangeScene(_sceneIndex);

    // 加载上一次的运行参数
    QSettings settings("myapp.ini", QSettings::IniFormat);
    // 模型参数 读取参数值: 0 是默认值,如果 "Index" 不存在则返回 0
    _sceneIndex = settings.value("Settings/Index", 0).toInt();
    // 放缩参数
    csmInt32 scalesX =  settings.value("Settings/ScaleX", 100).toInt();
    csmInt32 scalesY = settings.value("Settings/ScaleY", 100).toInt();
    // 平移参数X
    csmInt32 translateX = settings.value("Settings/TranslateX", 170).toInt();
    // 平移参数Y
    csmInt32 translateY = settings.value("Settings/TranslateY", -50).toInt();
    
    // 渲染模型
    CustomChangeScene(_sceneIndex,scalesX,scalesY,translateX,translateY);

}

 自定义实现 CustomChangeScene 方法,按指定的参数渲染模型,

void LAppLive2DManager::CustomChangeScene(Csm::csmInt32 index,Csm::csmInt32 scalesX, Csm::csmInt32 scalesY,Csm::csmInt32 translateX,Csm::csmInt32 translateY)
{
    _sceneIndex = index;
    if (DebugLogEnable)
    {
        LAppPal::PrintLog("[APP]model index: %d", _sceneIndex);
    }

    // ModelDir[]に保持したディレクトリ名から
    // model3.jsonのパスを決定する.
    // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
    std::string model = ModelDir[index];
    std::string modelPath = ResourcesPath + model + "/";
    std::string modelJsonName = ModelDir[index];
    modelJsonName += ".model3.json";

    ReleaseAllModel();
    _models.PushBack(new LAppModel());
    _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
    // 自定义参数
    _models[0]->GetModelMatrix()->Scale(scalesX*0.01f,scalesY*0.01f);
    _models[0]->GetModelMatrix()->TranslateX(translateX*0.01f);
    _models[0]->GetModelMatrix()->TranslateY(translateY*0.01f);

    /*
     * モデル半透明表示を行うサンプルを提示する。
     * ここでUSE_RENDER_TARGET、USE_MODEL_RENDER_TARGETが定義されている場合
     * 別のレンダリングターゲットにモデルを描画し、描画結果をテクスチャとして別のスプライトに張り付ける。
     */
    {
#if defined(USE_RENDER_TARGET)
        // LAppViewの持つターゲットに描画を行う場合、こちらを選択
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ViewFrameBuffer;
#elif defined(USE_MODEL_RENDER_TARGET)
        // 各LAppModelの持つターゲットに描画を行う場合、こちらを選択
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ModelFrameBuffer;
#else \
    // デフォルトのメインフレームバッファへレンダリングする(通常)
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_None;
#endif

#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
        // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
        _models.PushBack(new LAppModel());
        _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
        _models[1]->GetModelMatrix()->TranslateX(0.2f);
#endif

        LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget);

        // 別レンダリング先を選択した際の背景クリア色
        float clearColor[3] = { 1.0f, 1.0f, 1.0f };
        LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]);
    }
}

五、运行效果

六、更多细节

二、Live2d 简介与使用_live2d是什么-CSDN博客

三、Live2d 移植 QT_live2d源文件-CSDN博客

四、模型渲染与透明背景_opengl 透明背景-CSDN博客

五、鼠标事件与目标焦点_鼠标指向焦点-CSDN博客

六、模型显示位置与放缩-CSDN博客


http://www.kler.cn/a/501732.html

相关文章:

  • 分多个AndroidManifest.xml来控制项目编译
  • ImportError: attempted relative import with no known parent package 报错的解决!
  • R语言的语法糖
  • 回归预测 | MATLAB实RVM-Adaboost相关向量机集成学习多输入单输出回归预测
  • 量子计算:从薛定谔的猫到你的生活
  • Compose 的集成与导航
  • springmvc前端传参,后端接收
  • StarRocks Awards 2024 年度贡献人物
  • 《解锁鸿蒙系统AI能力,开启智能应用开发新时代》
  • 【GoLand】无法debug 无法运行
  • 【Orca】Orca - Graphlet 和 Orbit 计数算法
  • 《解锁计算机视觉智慧:编程实现图片场景文字描述的开源宝藏》
  • mysql-行溢出处理原理
  • 【HTML+CSS+JS+VUE】web前端教程-21-字体属性
  • 智能化文档开发(DI)
  • el-table 合并单元格
  • Redis解决热key问题
  • sql server cdc漏扫数据
  • C# 虚方法和抽象方法的区别,重写和重载的区别,参数修饰符(ref、out、in、params)--09
  • C语言程序环境和预处理详解
  • 基于element UI el-dropdown打造表格操作列的“更多⌵”上下文关联菜单
  • Transmon
  • linux网络 | http结尾、理解长连接短链接与cookie
  • 在 WSL 中使用 Jupyter Notebook 的 TensorBoard 启动问题与解决方法
  • GIN模型详解及代码复现
  • 【初体验】【学习】Web Component