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

Qt之自定义标题栏拓展(十)

Qt开发 系列文章 - user-defined-titlebars(十)


目录

前言

一、方式一

1.效果演示

2.创建标题栏类

3.可视化UI设计

4.定义相关函数

5.使用标题栏类

二、方式二

1.效果演示

2.创建标题栏类

3.定义相关函数

4.使用标题栏类

总结


前言

Qt自带的窗口标题栏通常遵循操作系统的默认样式和布局,以确保在不同平台上都能提供一致且符合用户期望的用户体验,因此Qt自带的窗口标题栏无法自定义。但我们在Qt设计软件时,经常需要改变窗口标题栏的样式,以满足不同场合用户需求。本文紧接着上一篇博文Qt之修改窗口标题、图标以及自定义标题栏(九)-CSDN博客的基础上,在介绍几种实现自定义标题栏的方法,并提供简单示例。


一、方式一

上一篇博文Qt之修改窗口标题、图标以及自定义标题栏(九)实现该方式是通过直接手鲁编写标题栏UI代码,下面提供的方式是在可视化界面UI上来设计标题栏,简洁方便直观,然后绑定/链接到主窗口界面上。

1.效果演示

2.创建标题栏类

跟上一个有区别的是,在原有的项目上,添加新的类文件,选择带ui设计类的模版,选择如下。

然后,定义类和ui的名称为MyTitleBar,MyTitleBar类的头文件代码如下(示例):

/** 只提供与上一篇不一样的代码地方 **/
QT_BEGIN_NAMESPACE
namespace Ui { class MyTitleBar; }
QT_END_NAMESPACE

class MyTitleBar : public QWidget
{
private slots:
    // 按钮触发的槽;
    void on_m_pButtonClose_clicked();
    void on_m_pButtonMax_clicked();
    void on_m_pButtonRestore_clicked();
    void on_m_pButtonMin_clicked();
private:
    Ui::MyTitleBar *ui;
};

3.可视化UI设计

上面我们定义标题栏类的头文件,下面来在可视化界面UI上来设计标题栏,双击打开.ui文件,在图像化设计界面设计如下标题栏。

  

上面设计完后,Qt会自动生成相应的UI代码和头文件,相关类为Ui_MyTitleBar。

4.定义相关函数

设计好MyTitleBar的UI文件后,下面来说明相关功能函数。

#include "ui_mytitlebar.h"
#include "mytitlebar.h"

MyTitleBar::MyTitleBar(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyTitleBar)
{
    // UI初始化
    ui->setupUi(this);
    // 初始化控件
    initControl();
    // 初始化标题栏色彩
    setBackgroundColor(m_colorR, m_colorG, m_colorB, m_isTransparent);
    // 加载本地样式 .css文件
    //loadStyleSheet("MyTitle");
    // 初始化标题栏色彩
    setBackgroundColor(230,232,250,0);

setStyleSheet("QToolButton#m_pButtonMenu,QPushButton#m_pButtonMin,QPushButton#m_pButtonMax,QPushButton#m_pButtonClose{\
    border-radius:3px;\
    color:#324C6C;\
    padding:3px;\
    margin:0px;\
    background:none;\
    border-style:none;\
    }");
                 setStyleSheet("QToolButton#m_pButtonMenu:hover,QPushButton#m_pButtonMin:hover,QPushButton#m_pButtonMax:hover{\
    color:#FFFFFF;\
    margin:1px 1px 2px 1px;\
    background-color:rgba(51,127,209,230);\
    }");
}
MyTitleBar::~MyTitleBar()
{
}
void MyTitleBar::initControl()
{
    m_colorR=0;
    m_colorG=153;
    m_colorB=153;
    m_isPressed=false;
    m_buttonType=MIN_MAX_BUTTON;
    m_windowBorderWidth=0;
    m_isTransparent=false;
    setFixedHeight(30);
    setWindowFlags(Qt::FramelessWindowHint);
    // 添加换肤菜单
    QStringList name;
    name << "银色" << "蓝色" << "浅蓝色" << "深蓝色";
    foreach (QString str, name) {
        QAction *action = new QAction(str, this);
        ui->m_pButtonMenu->addAction(action);
        connect(action, SIGNAL(triggered(bool)), this, SLOT(onButtonchangeStyle()));
    }
}
// 以下为按钮操作响应的槽
void MyTitleBar::onButtonchangeStyle()
{
    QAction *act = (QAction *)sender();
    QString name = act->text();
    //QString qssFile = "qss/blue.css";
    if (name == "银色") {
        //qssFile = "qss/silvery.css";
        setBackgroundColor(230,232,250,0);
    }
    else if (name == "蓝色"){
        //qssFile = "qss/blue.css";
        setBackgroundColor(50,76,108,0);
    }
    else if (name == "浅蓝色"){
        //qssFile = "qss/lightblue.css";
        setBackgroundColor(56,100,135,0);
    }
    else if (name == "深蓝色"){
        //qssFile = "qss/darkblue.css";
        setBackgroundColor(122,175,227,0);
    }
    //loadStyleSheet(qssFile);
    //emit signalchangeStyle(qssFile);
}
void MyTitleBar::on_m_pButtonClose_clicked()
{
    emit signalButtonCloseClicked();
}
void MyTitleBar::on_m_pButtonMax_clicked()
{
    ui->m_pButtonMax->setVisible(false);
    ui->m_pButtonRestore->setVisible(true);
    emit signalButtonMaxClicked();
}
void MyTitleBar::on_m_pButtonRestore_clicked()
{
    ui->m_pButtonRestore->setVisible(false);
    ui->m_pButtonMax->setVisible(true);
    emit signalButtonRestoreClicked();
}
void MyTitleBar::on_m_pButtonMin_clicked()
{
    emit signalButtonMinClicked();
}

5.使用标题栏类

在用户的构造函数上面添加对标题栏类的使用,跟上一篇博文一样。

二、方式二

方式一实现自定义标题栏时,定义一个标题栏类,在生成标题栏时,会覆盖原有的MenuBar和ToolBar,方式二改进后,修改标题栏不覆盖,效果如下。

1.效果演示

2.创建标题栏类

跟上一篇博文一样,在原有的项目上,添加C++新的类文件,选择如下。

然后定义标题栏类,代码部分如下(示例):

#include <QDialog>
#include <QMutex>

class QLabel;
class QPushButton;
class QToolButton;
class QVBoxLayout;
class QHBoxLayout;
class QFrame;
class QSpacerItem;
class QLineEdit;
class QComboBox;
class QAbstractButton;
class QUIWidget : public QDialog
        #endif
{
    Q_OBJECT
    Q_ENUMS(Style)
    Q_PROPERTY(QString title READ getTitle WRITE setTitle)
    Q_PROPERTY(Qt::Alignment alignment READ getAlignment WRITE setAlignment)
public:
    explicit QUIWidget(QWidget *parent = 0);
    ~QUIWidget();
public Q_SLOTS:
    //设置主窗体
    void setMainWidget(QWidget *mainWidget);
    //设置部件图标
    void setIcon(QUIWidget::Widget widget, QChar str, quint32 size = 9);
    //设置部件图片
    void setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size = QSize(16, 16));
    //设置部件是否可见
    void setVisible(QUIWidget::Widget widget, bool visible = true);
    //设置只有关闭按钮
    void setOnlyCloseBtn();
    //设置标题栏高度
    void setTitleHeight(int height);
    //设置按钮统一宽度
    void setBtnWidth(int width);
    //设置标题及文本样式
    void setTitle(const QString &title);
    void setAlignment(Qt::Alignment alignment);
};

3.定义相关函数

1.初始化函数

在标题栏类构造函数上,初始化如下设置,代码如下。

QUIWidget::QUIWidget(QWidget *parent) : QDialog(parent)
{
    //定义标题栏字体文本编码
    this->setTranslator(":/qm/qt_zh_CN.qm");
    this->setCode();
    this->initControl();
    this->initForm();
    //设置标题栏标题
#ifdef csd
    setTitle("**软件");
#else
    setTitle("csd演示版");
#endif
    //设置标题文本居中
    setAlignment(Qt::AlignCenter);
    //设置窗体可拖动大小
    setSizeGripEnabled(true);
    //设置换肤下拉菜单可见
    setVisible(QUIWidget::BtnMenu, true);
    //设置标题栏高度
    setTitleHeight(30);
    //设置按钮宽度
    setBtnWidth(30);
    //设置软件左上角图标--没有图标时显示图形字体
    setPixmap(QUIWidget::Lab_Ico, "ico/butterfly.ico", QSize(30,30));
    //默认样式风格blue
    setStyle(":/qss/blue.css");
    QFont font;
    font.setPointSize(12);
    this->setFont(font);
}
void QUIWidget::initControl()
{
    this->setObjectName(QString::fromUtf8("QUIWidget"));
    this->resize(900, 750);
    verticalLayout1 = new QVBoxLayout(this);
    verticalLayout1->setSpacing(0);
    verticalLayout1->setContentsMargins(11, 11, 11, 11);
    verticalLayout1->setObjectName(QString::fromUtf8("verticalLayout1"));
    verticalLayout1->setContentsMargins(1, 1, 1, 1);
    widgetMain = new QWidget(this);
    widgetMain->setObjectName(QString::fromUtf8("widgetMain"));
    widgetMain->setStyleSheet(QString::fromUtf8(""));
    verticalLayout2 = new QVBoxLayout(widgetMain);
    verticalLayout2->setSpacing(0);
    verticalLayout2->setContentsMargins(11, 11, 11, 11);
    verticalLayout2->setObjectName(QString::fromUtf8("verticalLayout2"));
    verticalLayout2->setContentsMargins(0, 0, 0, 0);
    widget_title = new QWidget(widgetMain);
    widget_title->setObjectName(QString::fromUtf8("widget_title"));
    QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(widget_title->sizePolicy().hasHeightForWidth());
    widget_title->setSizePolicy(sizePolicy);
    widget_title->setMinimumSize(QSize(0, 30));
    horizontalLayout4 = new QHBoxLayout(widget_title);
    horizontalLayout4->setSpacing(0);
    horizontalLayout4->setContentsMargins(11, 11, 11, 11);
    horizontalLayout4->setObjectName(QString::fromUtf8("horizontalLayout4"));
    horizontalLayout4->setContentsMargins(0, 0, 0, 0);
    lab_Ico = new QLabel(widget_title);
    lab_Ico->setObjectName(QString::fromUtf8("lab_Ico"));
    QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred);
    sizePolicy1.setHorizontalStretch(0);
    sizePolicy1.setVerticalStretch(0);
    sizePolicy1.setHeightForWidth(lab_Ico->sizePolicy().hasHeightForWidth());
    lab_Ico->setSizePolicy(sizePolicy1);
    lab_Ico->setMinimumSize(QSize(30, 0));
    lab_Ico->setAlignment(Qt::AlignCenter);

    horizontalLayout4->addWidget(lab_Ico);

    lab_Title = new QLabel(widget_title);
    lab_Title->setObjectName(QString::fromUtf8("lab_Title"));
    QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Preferred);
    sizePolicy2.setHorizontalStretch(0);
    sizePolicy2.setVerticalStretch(0);
    sizePolicy2.setHeightForWidth(lab_Title->sizePolicy().hasHeightForWidth());
    lab_Title->setSizePolicy(sizePolicy2);
    lab_Title->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);

    horizontalLayout4->addWidget(lab_Title);

    widget_menu = new QWidget(widget_title);
    widget_menu->setObjectName(QString::fromUtf8("widget_menu"));
    sizePolicy1.setHeightForWidth(widget_menu->sizePolicy().hasHeightForWidth());
    widget_menu->setSizePolicy(sizePolicy1);
    horizontalLayout = new QHBoxLayout(widget_menu);
    horizontalLayout->setSpacing(0);
    horizontalLayout->setContentsMargins(11, 11, 11, 11);
    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
    horizontalLayout->setContentsMargins(0, 0, 0, 0);
    btnMenu = new QToolButton(widget_menu);
    btnMenu->setObjectName(QString::fromUtf8("btnMenu"));
    QSizePolicy sizePolicy3(QSizePolicy::Fixed, QSizePolicy::Expanding);
    sizePolicy3.setHorizontalStretch(0);
    sizePolicy3.setVerticalStretch(0);
    sizePolicy3.setHeightForWidth(btnMenu->sizePolicy().hasHeightForWidth());
    btnMenu->setSizePolicy(sizePolicy3);
    btnMenu->setMinimumSize(QSize(30, 0));
    btnMenu->setMaximumSize(QSize(30, 16777215));
    btnMenu->setFocusPolicy(Qt::NoFocus);
    btnMenu->setPopupMode(QToolButton::InstantPopup);

    horizontalLayout->addWidget(btnMenu);

    btnMenu_Min = new QPushButton(widget_menu);
    btnMenu_Min->setObjectName(QString::fromUtf8("btnMenu_Min"));
    QSizePolicy sizePolicy4(QSizePolicy::Minimum, QSizePolicy::Expanding);
    sizePolicy4.setHorizontalStretch(0);
    sizePolicy4.setVerticalStretch(0);
    sizePolicy4.setHeightForWidth(btnMenu_Min->sizePolicy().hasHeightForWidth());
    btnMenu_Min->setSizePolicy(sizePolicy4);
    btnMenu_Min->setMinimumSize(QSize(30, 0));
    btnMenu_Min->setMaximumSize(QSize(30, 16777215));
    btnMenu_Min->setCursor(QCursor(Qt::ArrowCursor));
    btnMenu_Min->setFocusPolicy(Qt::NoFocus);

    horizontalLayout->addWidget(btnMenu_Min);

    btnMenu_Max = new QPushButton(widget_menu);
    btnMenu_Max->setObjectName(QString::fromUtf8("btnMenu_Max"));
    sizePolicy3.setHeightForWidth(btnMenu_Max->sizePolicy().hasHeightForWidth());
    btnMenu_Max->setSizePolicy(sizePolicy3);
    btnMenu_Max->setMinimumSize(QSize(30, 0));
    btnMenu_Max->setMaximumSize(QSize(30, 16777215));
    btnMenu_Max->setCursor(QCursor(Qt::ArrowCursor));
    btnMenu_Max->setFocusPolicy(Qt::NoFocus);

    horizontalLayout->addWidget(btnMenu_Max);

    btnMenu_Close = new QPushButton(widget_menu);
    btnMenu_Close->setObjectName(QString::fromUtf8("btnMenu_Close"));
    sizePolicy3.setHeightForWidth(btnMenu_Close->sizePolicy().hasHeightForWidth());
    btnMenu_Close->setSizePolicy(sizePolicy3);
    btnMenu_Close->setMinimumSize(QSize(30, 0));
    btnMenu_Close->setMaximumSize(QSize(30, 16777215));
    btnMenu_Close->setCursor(QCursor(Qt::ArrowCursor));
    btnMenu_Close->setFocusPolicy(Qt::NoFocus);

    horizontalLayout->addWidget(btnMenu_Close);
    horizontalLayout4->addWidget(widget_menu);
    verticalLayout2->addWidget(widget_title);

    widget = new QWidget(widgetMain);
    widget->setObjectName(QString::fromUtf8("widget"));
    verticalLayout3 = new QVBoxLayout(widget);
    verticalLayout3->setSpacing(0);
    verticalLayout3->setContentsMargins(11, 11, 11, 11);
    verticalLayout3->setObjectName(QString::fromUtf8("verticalLayout3"));
    verticalLayout3->setContentsMargins(0, 0, 0, 0);

    verticalLayout2->addWidget(widget);
    verticalLayout1->addWidget(widgetMain);

    connect(this->btnMenu_Min, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Min_clicked()));
    connect(this->btnMenu_Max, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Max_clicked()));
    connect(this->btnMenu_Close, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Close_clicked()));
}

void QUIWidget::initForm()
{
    //设置图形字体
    setIcon(QUIWidget::Lab_Ico, QChar(0xf099), 11); //设置左上角图标-图形字体
    setIcon(QUIWidget::BtnMenu, 0xf0d7);
    setIcon(QUIWidget::BtnMenu_Min, 0xf068);
    setIcon(QUIWidget::BtnMenu_Max, 0xf067);
    setIcon(QUIWidget::BtnMenu_Close, 0xf00d);

    //设置标题及对齐方式
    setTitle("QUI Demo");
    setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    setVisible(QUIWidget::BtnMenu, false);

    mainWidget = 0;
    max = false;
    location = this->geometry();
    this->setProperty("form", true);
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);//第一个参数是设置无边框。第二个参数是允许任务栏按钮右键菜单,第三个参数是允许最小化最大化与还原
    this->setWindowFlags(Qt::FramelessWindowHint);//任务栏单击图标后最小化后图标会消失,无法解决,因此不让最小化

    //绑定事件过滤器监听鼠标移动
    this->installEventFilter(this);
    this->widget_title->installEventFilter(this);

    //添加换肤菜单
    QStringList name;
    name << "银色" << "蓝色" << "浅蓝色" << "深蓝色" << "灰色" << "浅灰色" << "深灰色" << "黑色"
         << "浅黑色" << "深黑色" << "PS黑色" << "黑色扁平" << "白色扁平" << "浅紫色" << "橙色";
    foreach (QString str, name) {
        QAction *action = new QAction(str, this);
        this->btnMenu->addAction(action);
        connect(action, SIGNAL(triggered(bool)), this, SLOT(changeStyle()));
    }
}

2.功能函数

具体设置部件图标、设置部件图片、设置部件是否可见、设置标题栏高度、设置按钮统一宽度、设置标题及文本样式等等设置,代码如下。

void QUIWidget::setIcon(QUIWidget::Widget widget, QChar str, quint32 size)
{
    if (widget == QUIWidget::Lab_Ico) {
        IconHelper::Instance()->setIcon(this->lab_Ico, str, size);
    } else if (widget == QUIWidget::BtnMenu) {
        IconHelper::Instance()->setIcon(this->btnMenu, str, size);
    } else if (widget == QUIWidget::BtnMenu_Min) {
        IconHelper::Instance()->setIcon(this->btnMenu_Min, str, size);
    } else if (widget == QUIWidget::BtnMenu_Max) {
        IconHelper::Instance()->setIcon(this->btnMenu_Max, str, size);
    } else if (widget == QUIWidget::BtnMenu_Close) {
        IconHelper::Instance()->setIcon(this->btnMenu_Close, str, size);
    }
}

void QUIWidget::setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size)
{
    QPixmap pix = QPixmap(file);
    //按照宽高比自动缩放
    pix = pix.scaled(size, Qt::KeepAspectRatio);
    if (widget == QUIWidget::Lab_Ico) {
        this->lab_Ico->setPixmap(pix);
    } else if (widget == QUIWidget::BtnMenu) {
        this->btnMenu->setIcon(QIcon(file));
    } else if (widget == QUIWidget::BtnMenu_Min) {
        this->btnMenu_Min->setIcon(QIcon(file));
    } else if (widget == QUIWidget::BtnMenu_Max) {
        this->btnMenu_Max->setIcon(QIcon(file));
    } else if (widget == QUIWidget::BtnMenu_Close) {
        this->btnMenu_Close->setIcon(QIcon(file));
    }
}

void QUIWidget::setVisible(QUIWidget::Widget widget, bool visible)
{
    if (widget == QUIWidget::Lab_Ico) {
        this->lab_Ico->setVisible(visible);
    } else if (widget == QUIWidget::BtnMenu) {
        this->btnMenu->setVisible(visible);
    } else if (widget == QUIWidget::BtnMenu_Min) {
        this->btnMenu_Min->setVisible(visible);
    } else if (widget == QUIWidget::BtnMenu_Max) {
        this->btnMenu_Max->setVisible(visible);
    } else if (widget == QUIWidget::BtnMenu_Close) {
        this->btnMenu_Close->setVisible(visible);
    }
}

void QUIWidget::setOnlyCloseBtn()
{
    this->btnMenu->setVisible(false);
    this->btnMenu_Min->setVisible(false);
    this->btnMenu_Max->setVisible(false);
}

void QUIWidget::setTitleHeight(int height)
{
    this->widget_title->setFixedHeight(height);
}

void QUIWidget::setBtnWidth(int width)
{
    this->lab_Ico->setFixedWidth(width);
    this->btnMenu->setFixedWidth(width);
    this->btnMenu_Min->setFixedWidth(width);
    this->btnMenu_Max->setFixedWidth(width);
    this->btnMenu_Close->setFixedWidth(width);
}

void QUIWidget::setTitle(const QString &title)
{
    if (this->title != title) {
        this->title = title;
        this->lab_Title->setText(title);
        this->setWindowTitle(this->lab_Title->text());
    }
}

void QUIWidget::setAlignment(Qt::Alignment alignment)
{
    if (this->alignment != alignment) {
        this->alignment = alignment;
        this->lab_Title->setAlignment(alignment);
    }
}

void QUIWidget::on_btnMenu_Min_clicked()
{
    this->showMinimized();
}

void QUIWidget::on_btnMenu_Max_clicked()
{
    if (max) {
        this->setGeometry(location);
    } else {
        location = this->geometry();
        this->setGeometry(qApp->desktop()->availableGeometry());
    }
    max = !max;
}

void QUIWidget::on_btnMenu_Close_clicked()
{
    close();
}

3.窗口关联

打开主函数文件,在Main函数上将主窗口(用户)链接到标题栏窗口上,关联起来,代码如下。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //定义用户窗口
    MainWindow *w = new MainWindow;
    //定义标题栏
    QUIWidget qui;
    //将主窗体链接/关联到标题栏窗口上
    qui.setMainWidget(w);
    qui.show();
    return a.exec();
}
void QUIWidget::setMainWidget(QWidget *mainWidget)
{
    //一个QUI窗体对象只能设置一个主窗体
    if (this->mainWidget == 0) {
        //将子窗体添加到布局
        this->widget->layout()->addWidget(mainWidget);
        //自动设置大小
        resize(mainWidget->width(), mainWidget->height() + this->widget_title->height());
        this->mainWidget = mainWidget;
        this->mainWidget->installEventFilter(this);
    }
}

4.使用标题栏类

因为在Main函数上,已经将主窗体链接/关联到标题栏窗口上,因此在用户层无需关注/设置标题栏相关参数。这里和方式一不一样的是,方式是将标题栏类作为主窗口的私有变量使用,而方式二只是将两个窗口界面关联起来而已。

至此方式二讲解完毕,该种方式有个缺点是需要手鲁UI设计代码。更快捷的是,通过可视化界面UI来设计标题栏,然后绑定/链接到主窗口界面上,跟方式一一样。


总结

博文中相应的工程代码Qt-Case.zip 利用Qt开发软件进行编的例程,为博文提供案例-CSDN文库。


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

相关文章:

  • 中台成熟度模型有什么用
  • 浅谈云计算07 | 云安全机制
  • SpeingMVC框架(三)
  • 集合帖:区间问题
  • DNS解析域名简记
  • Web开发(二)CSS3基础与进阶
  • Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection
  • spring使用rabbitmq当rabbitmq集群节点挂掉 spring rabbitmq怎么保证高可用,rabbitmq网络怎么重新连接
  • 使用Python打造高效的PDF文件管理应用(合并以及分割)
  • Spring Boot 集成 Elasticsearch怎样在不启动es的情况下正常启动服务
  • 【21天学习AI底层概念】day5 机器学习的三大类型不能解决哪些问题?
  • 秒杀抢购场景下实战JVM级别锁与分布式锁
  • 四、网络层:数据平面,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
  • WPF 使用LibVLCSharp.WPF实现视频播放、停止、暂停功能
  • 【排序算法】——插入排序
  • .Net Core注册一个定制任务执行类服务
  • 首屏加载慢问题
  • 备战秋招:2024游戏开发入行与跳槽面试详解
  • 智能移动交通执法方案:易泊车牌识别相机助力精准执法与数据驱动管理
  • HCIA-Access V2.5_3_3_2_VLAN路由配置与实现
  • 机器学习之偏差
  • Shadcn UI 实战:打造可维护的企业级组件库
  • 简单配置,全面保护:HZERO审计服务让安全触手可及
  • 2412d,d的8月会议
  • Unity超优质动态天气插件(含一年四季各种天气变化,可用于单机局域网VR)
  • 【ETCD】【源码阅读】深入解析 EtcdServer.applyConfChange 方法