QT学习笔记二

ch2_1 模仿腾讯会议登录界面布局

1、添加各类控件布局登录界面

在这里插入图片描述

在这里插入图片描述
要注意最好要限制每一个控件的尺寸,然后再做水平垂直和栅格布局,否则可能会产生奇怪的编译结果。如果在修改完ui中的布局和控件尺寸,但是构建和编译后并没有更改,查看是否勾选了“shadow build”xuan”选项,要取消勾选重新编译效果就会改变。

2、运行结果

在这里插入图片描述
和原本的腾讯会议登录界面相比,模仿的界面多出了窗口标题,同时鼠标单击任务栏中的软件任务不能再显示和隐藏之间切换。

3、隐藏标题并添加切换显示和不显示设置

只需要在构造函数增加一行代码

#include "tencentmeetinglogin.h"
#include "ui_tencentmeetinglogin.h"

TencentMeetingLogin::TencentMeetingLogin(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::TencentMeetingLogin)
{
    ui->setupUi(this);
    //隐藏窗口标题,显示和不显示
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);

}

TencentMeetingLogin::~TencentMeetingLogin()
{
    delete ui;
}

ch1-2 优化腾讯会议登录界面

任务:

去掉窗口边框;
添加控件样式;
窗口移动

1、添加控件图标

在这里插入图片描述

2、设置控件样式

#include "tencentmeetinglogin.h"
#include "ui_tencentmeetinglogin.h"

TencentMeetingLogin::TencentMeetingLogin(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::TencentMeetingLogin)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
    //为了凸显下面三个按钮的效果,可以设置全局样式为白色,这样会导致其他登陆方式这里的横线消失
    //this->setStyleSheet("backfround-color:white; border:none");

    ui->btnSet->setText("");    // 去除按钮上的文字
    // 添加按钮样式,背景图标、无边界线、鼠标悬浮颜色加深
    ui->btnSet->setStyleSheet("QPushButton{background-image:url(:/resource/set.png); border:none}"
                              "QPushButton::hover{background-color:rgb(200,200,200)}");

    ui->btnMin->setText("");
    ui->btnMin->setStyleSheet("QPushButton{background-image:url(:/resource/min.png); border:none}"
                              "QPushButton::hover{background-color:rgb(200,200,200)}");

    ui->btnClose->setText("");
    ui->btnClose->setStyleSheet("QPushButton{background-image:url(:/resource/close.png); border:none}"
                              "QPushButton::hover{background-color:rgb(200,200,200)}");

    // 去除标签上的文字
    ui->labelLogo->clear();
    //添加腾讯会议logo
    QPixmap* pix = new QPixmap(":/resource/tencent-meeting.png");
    ui->labelLogo->setPixmap(*pix);

    ui->btnWeChat->setText("");
    ui->btnWeChat->setStyleSheet("QPushButton{background-image:url(:/resource/weichatlogin.png); border:none} QPushButton::hover{background-color:rgb(10,100,100)}");

    ui->btnPhoneLogin->setIcon(QIcon(":/resource/phonelogin.png"));
    ui->btnPhoneLogin->setIconSize(QSize(40, 40));
    ui->btnPhoneLogin->setText("手机号");
    ui->btnPhoneLogin->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    ui->btnPhoneLogin->setStyleSheet("background-color:white;border:none");

    ui->btnEnpriseWX->setIcon(QIcon(":/resource/enpriseweichat.png"));
    ui->btnEnpriseWX->setIconSize(QSize(40, 40));
    ui->btnEnpriseWX->setText("企业微信");
    ui->btnEnpriseWX->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    ui->btnEnpriseWX->setStyleSheet("background-color:white;border:none");

    ui->btnSSO->setIcon(QIcon(":/resource/sso.png"));
    ui->btnSSO->setIconSize(QSize(40, 40));
    ui->btnSSO->setText("SSO");
    ui->btnSSO->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    ui->btnSSO->setStyleSheet("background-color:white;border:none");

    connect(ui->btnClose,&QPushButton::clicked,[=]{
        close();
    });

}

TencentMeetingLogin::~TencentMeetingLogin()
{
    delete ui;
}


在这里插入图片描述

还可以在控件上右击选择改变样式表,添加样式内容来改变样式
在这里插入图片描述

ch2_3 代码创建布局,水平布局详解

手写代码布局的好处:

  • 更好的控制布局
  • 更好的设置qss
  • 代码复用
//包含头文件
#include <QHBoxLayout>
//创建水平布局
QHBoxLayout* pHLay = new QHBoxLayout(父窗口指针,一般是this

Qt布局的相关方法

  • addWidget:在布局中添加一个控件
  • addLayout:在布局里添加布局
  • setMargin:(在6.3.1vs2022环境下报错没有这个函数)设置水平布局最外边界与相邻控件左上右下的间隙,这时左上右下的间隙相同,如果想设置成不同,可以使用setContentsMargins方法;
  • setspacing:设置相邻控件之间的间隙,默认值大概是7
  • addspacing:在setSpacing的基础上进行相加,例如addspacing(-7),相当于两个控件之间没有距离;addspacing(13)相当于setspacing(20);
  • addStretch():在水平布局时添加一个水平的伸缩空间(QSpacerltem),在竖直布局时,添加一个竖直的伸缩空间

手写代码布局一个水平布局案例

#include "ch2_3_hLayout.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QDebug>


ch2_3_hLayout::ch2_3_hLayout(QWidget *parent)
    : QWidget(parent)
{
    QLabel* pPath = new QLabel(this);
    pPath->setObjectName("pPath");
    pPath->setFixedSize(40, 32);
    pPath->setText("路径");

    QLineEdit* pEdit = new QLineEdit(this);
    pEdit->setObjectName("pEdit");
    //pEdit->setFixedSize(100, 32);
    pEdit->setMinimumWidth(50);

    QPushButton* pBtn = new QPushButton(this);
    pBtn->setObjectName("pBtn");
    //pBtn->setFixedSize(50, 32);
    pBtn->setText("打开");

    添加一个水平布局
    QHBoxLayout* pHlay = new QHBoxLayout(this);

    //
    pHlay->addStretch();    //在水平布局中这个函数用于添加水平弹簧,在垂直布局中添加垂直弹簧
    pHlay->addWidget(pPath);    //addWidget函数用于把控件添加到布局当中
    pHlay->setSpacing(20);    //在控件之间添加间隙,默认值为7
    //pHlay->addStretch();
    pHlay->addWidget(pEdit);
    //pHlay->addStretch();
    pHlay->addWidget(pBtn);
    pHlay->addStretch();
    pHlay->setContentsMargins(100, 100, 100, 100);  //设置水平布局最外边界和相邻控件左上右下的间隙

}

ch2_3_hLayout::~ch2_3_hLayout()
{}

结果:
在这里插入图片描述

ch2_4 垂直布局

(1)包含头文件
#include
(2)创建竖直布局
QVBoxLayout* pMainVLay=new QVBoxLayout(this);
其他设置与水平布局类似
以下是手写代码垂直布局实例:

#include "ch2_4_vLayout.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QDebug>


ch2_4_vLayout::ch2_4_vLayout(QWidget *parent)
    : QWidget(parent)
{
    //resize(400, 400); 设置窗口的大小
    //创建一个新按钮
    QPushButton* btn1 = new QPushButton(this);
    //给按钮命名
    btn1->setObjectName("btn1");
    //设置按钮大小
    btn1->setFixedSize(40, 32);
    //编辑按钮上的文字内容
    btn1->setText("按钮1");
 
    QPushButton* btn2 = new QPushButton(this);
    btn2->setObjectName("btn2");
    btn2->setFixedSize(40, 32);
    btn2->setText("按钮2");
 
    QPushButton* btn3 = new QPushButton(this);
    btn3->setObjectName("btn3");
    btn3->setFixedSize(40, 32);
    btn3->setText("按钮3");

    //创建一个垂直布局
    QVBoxLayout* pVLay = new QVBoxLayout(this);
    pVLay->addWidget(btn1);
    pVLay->setSpacing(30);
    pVLay->addWidget(btn2);
    pVLay->addSpacing(50);
    pVLay->addWidget(btn3);
    //pVLay->addSpacing(13);
    pVLay->setContentsMargins(50, 60, 70, 80);

}

ch2_4_vLayout::~ch2_4_vLayout()
{}

结果:
在这里插入图片描述

ch2_5 栅格布局

(1)包含头文件#include
(2)创建栅格布局
QGridLayout* pGridLayout = new QGridLayout(this);
示例:

#include "widget.h"
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QGridLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //去除窗口标题和缩放在任务栏
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
    //头像
    QLabel* pImageLabel = new QLabel(this);
    QPixmap pixmap(":/user_image.png");
    pImageLabel->setFixedSize(150, 150);
    pImageLabel->setPixmap(pixmap);
    pImageLabel->setScaledContents(true);

    //用户名
    QLineEdit* pUserNameLineEdit = new QLineEdit(this);
    pUserNameLineEdit->setFixedSize(300, 40);
    pUserNameLineEdit->setPlaceholderText("QQ号码/手机/邮箱");

    QLineEdit* pPasswordLineEdit = new QLineEdit(this);
    pPasswordLineEdit->setFixedSize(300, 40);
    pPasswordLineEdit->setPlaceholderText("密码");
    pPasswordLineEdit->setEchoMode(QLineEdit::Password);

    QPushButton* pForgotButton = new QPushButton(this);
    pForgotButton->setText("找回密码");
    pForgotButton->setFixedWidth(80);

    QCheckBox* pRememberCheckBox = new QCheckBox(this);
    pRememberCheckBox->setText("记住密码");

    QCheckBox* pAutoLoginCheckBox = new QCheckBox(this);
    pAutoLoginCheckBox->setText("自动登录");

    QPushButton* pLoginButton = new QPushButton(this);
    pLoginButton->setFixedHeight(40);
    pLoginButton->setText("登录");

    QPushButton* pRegisterButton = new QPushButton(this);
    pRegisterButton->setFixedHeight(40);
    pRegisterButton->setText("注册账号");

    QGridLayout* pGridLay = new QGridLayout(this);

    //栅格布局添加控件时,widget函数参数
    pGridLay->addWidget(pImageLabel, 0,0,3,1);
    pGridLay->addWidget(pUserNameLineEdit, 0,1,1,2);
    pGridLay->addWidget(pPasswordLineEdit, 1,1,1,2);
    pGridLay->addWidget(pForgotButton, 2,1,1,1);
    pGridLay->addWidget(pRememberCheckBox, 2,2,1,1, Qt::AlignHCenter | Qt::AlignVCenter);
    pGridLay->addWidget(pAutoLoginCheckBox, 2,2,1,1, Qt::AlignRight | Qt::AlignVCenter);
    pGridLay->addWidget(pLoginButton, 3,1,1,2);
    pGridLay->addWidget(pRegisterButton, 4,1,1,2);

    //pGridLay->setHorizontalSpacing(20);
    //pGridLay->setVerticalSpacing(20);

    pGridLay->setContentsMargins(20,20,20,20);
}

Widget::~Widget() {}

结果:
在这里插入图片描述

ch2_6 栅格布局中的一些调整

//就是上一节的代码中最后几行用于调整布局间距
    pGridLay->setHorizontalSpacing(20);
    pGridLay->setVerticalSpacing(20);

    pGridLay->setContentsMargins(20,20,20,20);

ch2_7 分裂器布局代码实现

什么是分裂器?实际应用中的案例如下:
在这里插入图片描述

1、使用designer布局

在这里插入图片描述

2、C++代码实现分裂器

水平分裂器
QSplitter* pHSplitter = new QSplitter(Qt::Horizontal, this);
竖直分裂器
QSplitter* pVSplitter = new QSplitter(at::Vertical, pHSplitter);
分裂器也是Qwidget的子类,因此分裂器也有addwidget方法,而布局也可以使用addwidget往布局里添加分裂器

#include "ch2_7_splitter_code.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QSplitter>

ch2_7_splitter_code::ch2_7_splitter_code(QWidget *parent)
    : QWidget(parent)
{
    this->setWindowTitle("Qt分裂器布局_c++代码");

    //整体用水平布局
    QHBoxLayout* pHLay = new QHBoxLayout(this);

    //整体水平分裂器
    QSplitter* pHSplitter = new QSplitter(this);
    QWidget* pLeftWdiget = new QWidget(this);
    pLeftWdiget->setStyleSheet("background-color:rgb(54,54,54)");
    pLeftWdiget->setMinimumWidth(200);

    //分裂器添加widget
    pHSplitter->addWidget(pLeftWdiget);

    //右侧的竖直分裂器
    //注意参数pHSplitter,表示父指针
    QSplitter* pVSplitter = new QSplitter(Qt::Vertical, pHSplitter);

    //在拖动到位后并谈起鼠标后再显示分隔条
    pHSplitter->setOpaqueResize(true);

    QWidget* pRightTopWidget = new QWidget(this);
    pRightTopWidget->setStyleSheet("background-color:rgb(154,1,1)");

    QTextBrowser* pRifghtBottom = new QTextBrowser(this);

    pVSplitter->addWidget(pRightTopWidget);
    pVSplitter->addWidget(pRifghtBottom);

    pHSplitter->addWidget(pVSplitter);

    //布局添加分裂器
    pHLay->addWidget(pHSplitter);

    //设置整体布局
    setLayout(pHLay);
}

ch2_7_splitter_code::~ch2_7_splitter_code()
{}

在这里插入图片描述

ch2_8 setLayout使用说明

将此小部件的布局管理器设置为布局。如果这个小部件上已经安装了一个布局管理器,那么Qwidget不会让您安装另一个。您必须首先删除现有的布局管理器(由layout()返回),然后才能用新的布局调用setLayout()。
一般可以不写setLayout

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QVBoxLayout>

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

    //不用加this
    QPushButton* btn1 = new QPushButton;
    btn1->setFixedSize(100, 100);
    btn1->setText("btn1");

    QPushButton* btn2 = new QPushButton;
    btn2->setFixedSize(100, 100);
    btn2->setText("btn2");

    QHBoxLayout* hLay = new QHBoxLayout(this);
    hLay->addWidget(btn1);
    hLay->addWidget(btn2);
    setLayout(hLay);

    QPushButton* btn3 = new QPushButton(this);
    btn3->setFixedSize(100, 100);
    btn3->setText("btn3");

    QPushButton* btn4 = new QPushButton;
    btn4->setFixedSize(100, 100);
    btn4->setText("btn4");

    QVBoxLayout* vLay = new QVBoxLayout(this);
    vLay->addWidget(btn3);
    vLay->addWidget(btn4);
    setLayout(vLay);
}

Widget::~Widget()
{
    delete ui;
}

上面的代码中setLayout()只会生效第一个,另外new后面是否加this,this表示父类指针,加上this则会在父窗口中显示,不加只显示setLayout以上的布局内容。

ch2_9 多重布局变化和布局删除

#include "ch2_9_rightMenu.h"
#include <QAction>
#include <QMessageBox>

ch2_9_rightMenu::ch2_9_rightMenu(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    //设置菜单策略
    this->setContextMenuPolicy(Qt::DefaultContextMenu);

    initMenu();

}

ch2_9_rightMenu::~ch2_9_rightMenu()
{}


void ch2_9_rightMenu::contextMenuEvent(QContextMenuEvent* event)//这是一个事件处理函数,该函数不需要显式的调用,用于处理右键点击(上下文菜单)事件。Qt 框架会在适当的时候自动调用它。
{
    m_pMenu->exec(QCursor::pos());
}

void ch2_9_rightMenu::initMenu()
{
    m_pMenu = new QMenu(this);
    QAction* pAc1 = new QAction("ac1");
    QAction* pAc2 = new QAction("ac2");
    QAction* pAc3 = new QAction("ac3");
    QAction* pAc4 = new QAction("ac4");
    QAction* pAc5 = new QAction("ac5");

    m_pMenu->addAction(pAc1);
    m_pMenu->addAction(pAc2);
    m_pMenu->addAction(pAc3);
    m_pMenu->addAction(pAc4);
    m_pMenu->addAction(pAc5);

    connect(pAc1, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac1");
        });

    connect(pAc2, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac2");
        });

    connect(pAc3, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac3");
        });

    connect(pAc4, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac4");
        });

    connect(pAc5, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac5");
        });

}

在这里插入图片描述
另一个示例:

#pragma execution_character_set("utf-8")

#include "SwitchWidget.h"
#include <QGridLayout>
#include <QContextMenuEvent>

SwitchWidget::SwitchWidget(QWidget *parent)
    : QWidget(parent)
{
	setWindowTitle("鍤欒笣钑�鍤欒笣钑�鍤欒珛槌磋暛鍤欒笣钑�鍤欒珝灏嶈暛");
    initWidget();
    this->resize(QSize(800, 500));
    this->setContextMenuPolicy(Qt::DefaultContextMenu);
}

void SwitchWidget::initWidget()
{
	initMenu();

	for (int i = 0; i < 9; i++)
	{
		QLabel* label = new QLabel;
		
		label->setStyleSheet(QString("QLabel{background-image:url(:/SwitchWidget/resources/%1.png); \
			border:1px solid gray; \
			background-position:center; \
			background-repeat:no-repeat; \
			}").arg(QString::number(i + 1)));
		
		m_videoLabelList.append(label);
	}

	switchLayout(VideoLayoutType::OneVideo);
}

void SwitchWidget::initMenu()
{
	m_switchMenu = new QMenu(this);
	m_switchMenu->addAction("鐝ㄥ殭韪濊暛鍤欒笣钑�");
	m_switchMenu->addAction("鍤欒�濈榾钑�鍤欒笣钑�");
	m_switchMenu->addAction("鍤欒笣钑�鍤欒笣钑�鍤欙拷");
	m_switchMenu->addAction("鍤欒笣钑�鍤欒笣钑�鍤欒笣钑�");
	m_switchMenu->addAction("鍤欒�愮榾钑�鍤欒笣钑�");

	QMap<QString, int> strTypeMap;
	strTypeMap["鐝ㄥ殭韪濊暛鍤欒笣钑�"] = VideoLayoutType::OneVideo;
	strTypeMap["鍤欒�濈榾钑�鍤欒笣钑�"] = VideoLayoutType::FourVideo;
	strTypeMap["鍤欒笣钑�鍤欒笣钑�鍤欙拷"] = VideoLayoutType::FiveVideo;
	strTypeMap["鍤欒笣钑�鍤欒笣钑�鍤欒笣钑�"] = VideoLayoutType::SixVideo;
	strTypeMap["鍤欒�愮榾钑�鍤欒笣钑�"] = VideoLayoutType::NineVideo;

	connect(m_switchMenu, &QMenu::triggered, this, [=](QAction* action) {
		QString strText = action->text();
		VideoLayoutType type = VideoLayoutType(strTypeMap[strText]);
		switchLayout(type);
		});
}

void SwitchWidget::contextMenuEvent(QContextMenuEvent* event)
{
	m_switchMenu->exec(QCursor::pos());
}

void SwitchWidget::switchLayout(VideoLayoutType type)
{
	QLayout* layout = this->layout();
	
	
	if (layout)
	{
		QLayoutItem* child;
		while ((child = layout->takeAt(0)) != 0)
		{
			if (child->widget())
			{
				child->widget()->setParent(NULL);
			}

			delete child;
		}

		delete layout;
	}

	switch (type)
	{
	case OneVideo:
	{
		QGridLayout* gLayout = new QGridLayout(this);
		gLayout->addWidget(m_videoLabelList[0]);
		gLayout->setMargin(0);
	}
	break;

	case FourVideo:
	{
		QGridLayout* gLayout = new QGridLayout(this);
		gLayout->setSpacing(0);
		gLayout->setMargin(0);

		for (int i = 0; i < 4; i++)
		{
			gLayout->addWidget(m_videoLabelList[i], i / 2, i % 2);
		}
	}
	break;

	case FiveVideo:
	{
		QVBoxLayout* pVLay = new QVBoxLayout(this);
		pVLay->setSpacing(0);

		QHBoxLayout* pHTopLay = new QHBoxLayout(this);
		pHTopLay->setSpacing(0);
		for (int i = 0; i < 3; i++)
		{
			pHTopLay->addWidget(m_videoLabelList[i]);
		}

		QHBoxLayout* pHBottomLay = new QHBoxLayout(this);
		pHBottomLay->setSpacing(0);
		for (int i = 3; i < 5; i++)
		{
			pHBottomLay->addWidget(m_videoLabelList[i]);
		}
	
		pVLay->addLayout(pHTopLay);
		pVLay->addLayout(pHBottomLay);
		
	}
	break;

	case SixVideo:
	{
		QGridLayout* gLayout = new QGridLayout(this);
		gLayout->addWidget(m_videoLabelList[0], 0, 0, 2, 2);
		gLayout->addWidget(m_videoLabelList[1], 0, 2);
		gLayout->addWidget(m_videoLabelList[2], 1, 2);
		gLayout->addWidget(m_videoLabelList[3], 2, 0);
		gLayout->addWidget(m_videoLabelList[4], 2, 1);
		gLayout->addWidget(m_videoLabelList[5], 2, 2);
		gLayout->setSpacing(0);
		gLayout->setMargin(0);
	}
	break;

	case NineVideo:
	{
		QGridLayout* gLayout = new QGridLayout(this);
		gLayout->setSpacing(0);
		gLayout->setMargin(0);

		for (int i = 0; i < 9; i++)
		{
			gLayout->addWidget(m_videoLabelList[i], i / 3, i % 3);
		}
	}
	break;

	default:
		break;
	}
}


ch2_10 手写代码实现腾讯会议登录界面

可以借鉴qt的designer布局自动生成的代码,然后这些代码复制过来做一些自己的修改。自动生成的代码为ui_tencentmeetinglogin.h,基于这个代码修改如下:

#include "ch2_10_logincode.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QToolButton>
#include <QCoreApplication>

ch2_10_logincode::ch2_10_logincode(QWidget *parent)
    : QDialog(parent)
{
    QVBoxLayout* verticalLayout_2;
    QHBoxLayout* horizontalLayout;
    QPushButton* btnSet;
    QLabel* label;
    QPushButton* btnMin;
    QPushButton* btnClose;
    QHBoxLayout* horizontalLayout_4;
    QSpacerItem* horizontalSpacer;
    QLabel* labelLogo;
    QSpacerItem* horizontalSpacer_2;
    QHBoxLayout* horizontalLayout_5;
    QSpacerItem* horizontalSpacer_3;
    QVBoxLayout* verticalLayout;
    QPushButton* btnWeChat;
    QPushButton* btnJoinMeeting;
    QSpacerItem* horizontalSpacer_4;
    QHBoxLayout* horizontalLayout_2;
    QFrame* line;
    QLabel* label_3;
    QFrame* line_2;
    QHBoxLayout* horizontalLayout_3;
    QToolButton* btnPhoneLogin;
    QToolButton* btnEnpriseWX;
    QToolButton* btnSSO;

    /*void setupUi(QDialog * this)
    {
        if (this->objectName().isEmpty())
            this->setObjectName(QString::fromUtf8("this"));
        this->resize(400, 600);*/
        //将TencentMeetingLogin替换成this
        this->setMinimumSize(QSize(400, 600));	
        this->setMaximumSize(QSize(400, 600));
        verticalLayout_2 = new QVBoxLayout(this);
        verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
        horizontalLayout = new QHBoxLayout();
        horizontalLayout->setSpacing(0);
        horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
        horizontalLayout->setSizeConstraint(QLayout::SizeConstraint::SetDefaultConstraint);
        horizontalLayout->setContentsMargins(-1, 0, -1, 61);
        btnSet = new QPushButton(this);
        btnSet->setObjectName(QString::fromUtf8("btnSet"));
        btnSet->setMinimumSize(QSize(0, 32));
        btnSet->setMaximumSize(QSize(32, 32));

        horizontalLayout->addWidget(btnSet);

        label = new QLabel(this);
        label->setObjectName(QString::fromUtf8("label"));
        label->setMinimumSize(QSize(284, 20));
        label->setMaximumSize(QSize(350, 20));
        label->setAlignment(Qt::AlignmentFlag::AlignCenter);

        horizontalLayout->addWidget(label);

        btnMin = new QPushButton(this);
        btnMin->setObjectName(QString::fromUtf8("btnMin"));
        btnMin->setMinimumSize(QSize(0, 32));
        btnMin->setMaximumSize(QSize(32, 32));

        horizontalLayout->addWidget(btnMin);

        btnClose = new QPushButton(this);
        btnClose->setObjectName(QString::fromUtf8("btnClose"));
        btnClose->setMinimumSize(QSize(0, 32));
        btnClose->setMaximumSize(QSize(32, 32));

        horizontalLayout->addWidget(btnClose);


        verticalLayout_2->addLayout(horizontalLayout);

        horizontalLayout_4 = new QHBoxLayout();
        horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
        horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        horizontalLayout_4->addItem(horizontalSpacer);

        labelLogo = new QLabel(this);
        labelLogo->setObjectName(QString::fromUtf8("labelLogo"));
        labelLogo->setMinimumSize(QSize(200, 200));
        labelLogo->setMaximumSize(QSize(200, 200));
        labelLogo->setAlignment(Qt::AlignmentFlag::AlignCenter);

        horizontalLayout_4->addWidget(labelLogo);

        horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        horizontalLayout_4->addItem(horizontalSpacer_2);


        verticalLayout_2->addLayout(horizontalLayout_4);

        horizontalLayout_5 = new QHBoxLayout();
        horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5"));
        horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        horizontalLayout_5->addItem(horizontalSpacer_3);

        verticalLayout = new QVBoxLayout();
        verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
        btnWeChat = new QPushButton(this);
        btnWeChat->setObjectName(QString::fromUtf8("btnWeChat"));
        btnWeChat->setMinimumSize(QSize(350, 40));
        btnWeChat->setMaximumSize(QSize(350, 40));

        verticalLayout->addWidget(btnWeChat);

        btnJoinMeeting = new QPushButton(this);
        btnJoinMeeting->setObjectName(QString::fromUtf8("btnJoinMeeting"));
        btnJoinMeeting->setMinimumSize(QSize(350, 40));
        btnJoinMeeting->setMaximumSize(QSize(350, 40));
        btnJoinMeeting->setStyleSheet(QString::fromUtf8("QPushButton\n"
            "{\n"
            "/* \345\211\215\346\231\257\350\211\262 */\n"
            "color:#0054E6;\n"
            "/* \350\203\214\346\231\257\350\211\262 */\n"
            "background-color:rgb(255,255,255);\n"
            "/*\350\276\271\346\241\206\351\243\216\346\240\274 */\n"
            "border-style:outset;\n"
            "/* \350\276\271\346\241\206\345\256\275\345\272\246 */\n"
            "border-width:0.5px;\n"
            "/*\350\276\271\346\241\206\351\242\234\350\211\262*/\n"
            "border-color:gray;\n"
            "/*\350\276\271\346\241\206\345\200\222\350\247\222 */\n"
            "border-radius:2px;\n"
            "}\n"
            "/*\351\274\240\346\240\207\346\202\254\346\265\256\346\227\266\347\232\204\346\225\210\346\236\234*/\n"
            "QPushButton:hover\n"
            "{\n"
            "/* \350\276\271\346\241\206\351\242\234\350\211\262 */\n"
            "border-color:blue\n"
            "}"));

        verticalLayout->addWidget(btnJoinMeeting);


        horizontalLayout_5->addLayout(verticalLayout);

        horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        horizontalLayout_5->addItem(horizontalSpacer_4);


        verticalLayout_2->addLayout(horizontalLayout_5);

        horizontalLayout_2 = new QHBoxLayout();
        horizontalLayout_2->setSpacing(6);
        horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
        horizontalLayout_2->setSizeConstraint(QLayout::SizeConstraint::SetFixedSize);
        line = new QFrame(this);
        line->setObjectName(QString::fromUtf8("line"));
        line->setFrameShape(QFrame::HLine);
        line->setFrameShadow(QFrame::Sunken);

        horizontalLayout_2->addWidget(line);

        label_3 = new QLabel(this);
        label_3->setObjectName(QString::fromUtf8("label_3"));
        label_3->setMinimumSize(QSize(150, 40));
        label_3->setMaximumSize(QSize(150, 40));
        label_3->setAlignment(Qt::AlignmentFlag::AlignCenter);

        horizontalLayout_2->addWidget(label_3);

        line_2 = new QFrame(this);
        line_2->setObjectName(QString::fromUtf8("line_2"));
        line_2->setFrameShape(QFrame::HLine);
        line_2->setFrameShadow(QFrame::Sunken);

        horizontalLayout_2->addWidget(line_2);


        verticalLayout_2->addLayout(horizontalLayout_2);

        horizontalLayout_3 = new QHBoxLayout();
        horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
        horizontalLayout_3->setSizeConstraint(QLayout::SizeConstraint::SetDefaultConstraint);
        btnPhoneLogin = new QToolButton(this);
        btnPhoneLogin->setObjectName(QString::fromUtf8("btnPhoneLogin"));
        btnPhoneLogin->setMinimumSize(QSize(68, 60));
        btnPhoneLogin->setMaximumSize(QSize(68, 60));

        horizontalLayout_3->addWidget(btnPhoneLogin);

        btnEnpriseWX = new QToolButton(this);
        btnEnpriseWX->setObjectName(QString::fromUtf8("btnEnpriseWX"));
        btnEnpriseWX->setMinimumSize(QSize(68, 60));
        btnEnpriseWX->setMaximumSize(QSize(68, 60));

        horizontalLayout_3->addWidget(btnEnpriseWX);

        btnSSO = new QToolButton(this);
        btnSSO->setObjectName(QString::fromUtf8("btnSSO"));
        btnSSO->setMinimumSize(QSize(68, 60));
        btnSSO->setMaximumSize(QSize(68, 60));

        horizontalLayout_3->addWidget(btnSSO);


        verticalLayout_2->addLayout(horizontalLayout_3);


//        retranslateUi(this);

        QMetaObject::connectSlotsByName(this);
//      } // setupUi

 /*   void retranslateUi(QDialog * this)
    {*/
        this->setWindowTitle(QCoreApplication::translate("this", "this", nullptr));
        btnSet->setText(QCoreApplication::translate("this", "PushButton", nullptr));
        label->setText(QCoreApplication::translate("this", "\350\247\206\351\242\221\344\274\232\350\256\256", nullptr));
        btnMin->setText(QCoreApplication::translate("this", "PushButton", nullptr));
        btnClose->setText(QCoreApplication::translate("this", "PushButton", nullptr));
        labelLogo->setText(QCoreApplication::translate("this", "helloworld", nullptr));
        btnWeChat->setText(QCoreApplication::translate("this", "\345\276\256\344\277\241\347\231\273\345\275\225", nullptr));
        btnJoinMeeting->setText(QCoreApplication::translate("this", "\345\212\240\345\205\245\344\274\232\350\256\256", nullptr));
        label_3->setText(QCoreApplication::translate("this", "\345\205\266\344\273\226\347\231\273\345\275\225\346\226\271\345\274\217", nullptr));
        btnPhoneLogin->setText(QCoreApplication::translate("this", "...", nullptr));
        btnEnpriseWX->setText(QCoreApplication::translate("this", "...", nullptr));
        btnSSO->setText(QCoreApplication::translate("this", "...", nullptr));
//    }

		       this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
       //为了凸显下面三个按钮的效果,可以设置全局样式为白色,这样会导致其他登陆方式这里的横线消失
       //this->setStyleSheet("backfround-color:white; border:none");

       btnSet->setText("");    // 去除按钮上的文字
       // 添加按钮样式,背景图标、无边界线、鼠标悬浮颜色加深
       btnSet->setStyleSheet("QPushButton{background-image:url(:/resources/set.png); border:none}"
           "QPushButton::hover{background-color:rgb(200,200,200)}");

       btnMin->setText("");
       btnMin->setStyleSheet("QPushButton{background-image:url(:/resources/min.png); border:none}"
           "QPushButton::hover{background-color:rgb(200,200,200)}");

       btnClose->setText("");
       btnClose->setStyleSheet("QPushButton{background-image:url(:/resources/close.png); border:none}"
           "QPushButton::hover{background-color:rgb(200,200,200)}");

       // 去除标签上的文字
       labelLogo->clear();
       //添加腾讯会议logo
       QPixmap* pix = new QPixmap(":/resources/tencent-meeting.png");
       labelLogo->setPixmap(*pix);

       btnWeChat->setText("");
       btnWeChat->setStyleSheet("QPushButton{background-image:url(:/resources/weichatlogin.png); border:none} QPushButton::hover{background-color:rgb(10,100,100)}");

/*       btnPhoneLogin->setIcon(QIcon(":/resources/phonelogin.png"));
       btnPhoneLogin->setIconSize(QSize(40, 40));
       btnPhoneLogin->setText(u8"手机号");
       btnPhoneLogin->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
       btnPhoneLogin->setStyleSheet("background-color:white;border:none");*/

       btnEnpriseWX->setIcon(QIcon(":/resources/enpriseweichat.png"));
       btnEnpriseWX->setIconSize(QSize(40, 40));
       btnEnpriseWX->setText("企业微信");
       btnEnpriseWX->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
       btnEnpriseWX->setStyleSheet("background-color:white;border:none");

       btnSSO->setIcon(QIcon(":/resources/sso.png"));
       btnSSO->setIconSize(QSize(40, 40));
       btnSSO->setText("SSO");
       btnSSO->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
       btnSSO->setStyleSheet("background-color:white;border:none");

       connect(btnClose, &QPushButton::clicked, [=] {
           close();
           });
}

ch2_10_logincode::~ch2_10_logincode()
{}

运行的结果基本和ch2_1一致。

ch2_11 QTabWidget各种常见用法详解一

添加自定义tab

int insertTab(int index, QWidget *page, const QString &label)
int insertTab(int index, QWidget *page, const Qlcon &icon, const QString &label)

示例

#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QTabWidget>
#include <QDebug>
#include <QTabBar>
#include "form.h"

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

    //添加一个水平布局
    QHBoxLayout* lay = new QHBoxLayout(this);

    //添加一个标签widget
    QTabWidget* pTabWidget = new QTabWidget(this);
    //设置标签页可以被关闭
    pTabWidget->setTabsClosable(true);
    pTabWidget->setMovable(true);
    pTabWidget->setTabShape(QTabWidget::Triangular);
    pTabWidget->setTabPosition(QTabWidget::South);

    //新建widget对象
    QWidget *w1 = new QWidget;
    w1->setStyleSheet("background-color:rgb(54,54,54)");
    QWidget *w2 = new QWidget;
    w2->setStyleSheet("background-color:rgb(154,54,54)");
    QWidget *w3 = new QWidget;
    w3->setStyleSheet("background-color:rgb(54,154,54)");

    //把w1,w2,w3三个窗口添加到Tabwidget中
    pTabWidget->insertTab(0, w1, "tab1");
    pTabWidget->insertTab(1, w2, "tab2");
    pTabWidget->insertTab(2, w3, "tab3");

    //创建一个新的窗口类
    Form* f = new Form;
    pTabWidget->insertTab(3, f, "第四页");

    //给标签添加提示信息,当鼠标放在标签上时显示
    pTabWidget->setTabToolTip(2, "the tab id is 2");

    //把pTabWidget添加到水平布局对象中
    lay->addWidget(pTabWidget);

    //测试几个QTabWidget的信号
    /*
Q_SIGNALS:
    void currentChanged(int index);
    void tabCloseRequested(int index);
    void tabBarClicked(int index);
    void tabBarDoubleClicked(int index);
    */
    connect(pTabWidget, &QTabWidget::currentChanged, [=](int index){
            qDebug()<< "index = "<< index;
    });

    connect(pTabWidget, &QTabWidget::tabBarDoubleClicked, [=](int index){
        qDebug() << "tabBarDoubleClicked index = " << index;
    });

    connect(pTabWidget, &QTabWidget::tabBarClicked, [=](int index){
        qDebug() << "tabBarClicked index = " << index;
    });

    connect(pTabWidget, &QTabWidget::tabCloseRequested, [=](int index){
        qDebug() << "tabCloseRequested index = " << index;
        pTabWidget->removeTab(index);  // 关闭tab
    });

}

Widget::~Widget()
{
    delete ui;
}

编译结果:
在这里插入图片描述

ch2_12 QTabWidget各种常见用法详解二

1、首先创建一个QWidget应用

2、添加Tab Widget控件

在Tab Widget控件上右击选择**“插入页”**,可以增加该控件的标签页面。然后在不同的页面可以选择一些控件添加进去。如下图:
在这里插入图片描述

3、在任意页面右击选择“改变样式表”对页面和控件进行样式修改

在这里插入图片描述

ch2_13 QListWidget用法一

QListWidget有两种显示模式如下
在这里插入图片描述

任务1:模仿一个选项窗口(列表模式)

在这里插入图片描述

1、添加控件

在这里插入图片描述

2、调整布局

在这里插入图片描述

3、添加图标资源文件

在这里插入图片描述
右击,选择添加现有文件,选择图标。

4、实例化QListWidgetItem,把图标选项添加到QListWidget中

在这里插入图片描述

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

    //创建item
    QListWidgetItem* pItem1 = new QListWidgetItem(QIcon(":/resources/kits.png"), "kits");
    QListWidgetItem* pItem2 = new QListWidgetItem(QIcon(":/resources/env.png"), "环境");
    QListWidgetItem* pItem3 = new QListWidgetItem(QIcon(":/resources/editor.png"), "文本编辑");
    QListWidgetItem* pItem4 = new QListWidgetItem(QIcon(":/resources/vim.png"), "FakeVim");
    QListWidgetItem* pItem5 = new QListWidgetItem(QIcon(":/resources/help.png"), "帮助");

    ui->listWidget->addItem(pItem1);
    ui->listWidget->addItem(pItem2);
    ui->listWidget->addItem(pItem3);
    ui->listWidget->addItem(pItem4);
    ui->listWidget->addItem(pItem5);
}

在这里插入图片描述

5、增加一个新的类并把它添加到ListWidget中

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在useritem.ui中布局UserItem界面
在这里插入图片描述
在useritem.cpp中设置useritem布局的大小
在这里插入图片描述
把UserItem的头文件添加到Widget.cpp中,在Widget.cpp中添加自定义类UserItem,并放置在ListWidget中
在这里插入图片描述
在这里插入图片描述
调整widget.ui 的控件大小,适合useritem

编译结果是:
在这里插入图片描述

ch2_14 QListWidget用法二——左键菜单、item删除

项目管理小技巧
创建一个空项目,把里面的东西都删了,只保留.sln,然后把其他项目添加到空的解决方案里
QT6.3.1转VS方法
在这里插入图片描述
** List Item如何添加右键菜单**

//设置菜单策略,必须设置,不然无法显示菜单
ui.listWidget0->setContextMenuPolicy(Qt::CustomContextMenu);
//连接信号槽
connect(ui.listWidget0,&QListWidget::customContextMenuRequested, this&Widget::on PopupRightMenu);

QListWidget如何删除item

  • 方式1:知道item的名字,根据名字删除,这种可用于用户掉线,信息丢失等,动态删除;
  • 方式2:右键点击删除,或者选中删除

任务:在QListWidget下创建item,右击菜单,删除item

示例:

#pragma once

#include <QtWidgets/QWidget>
#include "ui_ch2_14_QListWidget.h"
#include <QMenu>

class ch2_14_QListWidget : public QWidget
{
    Q_OBJECT

public:
    ch2_14_QListWidget(QWidget *parent = nullptr);
    ~ch2_14_QListWidget();

private slots:
    void on_PopupRightMenu(const QPoint& pos);

private:
    void initRightMenu();

private:
    Ui::ch2_14_QListWidgetClass ui;

    QMenu* m_pRightMenu = nullptr;
};

#include "ch2_14_QListWidget.h"
#include <QListWidgetItem>
#include <QMessageBox>

ch2_14_QListWidget::ch2_14_QListWidget(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    resize(600, 800);

    QListWidgetItem* pItem1 = new QListWidgetItem(QIcon(":/ch2_14_QListWidget/resources/kits.png"), "Kits");
    QListWidgetItem* pItem2 = new QListWidgetItem(QIcon(":/ch2_14_QListWidget/resources/env.png"), u8"环境");
    QListWidgetItem* pItem3 = new QListWidgetItem(QIcon(":/ch2_14_QListWidget/resources/editor.png"), u8"编辑器");
    QListWidgetItem* pItem4 = new QListWidgetItem(QIcon(":/ch2_14_QListWidget/resources/vim.png"), "FakeVim");
    QListWidgetItem* pItem5 = new QListWidgetItem(QIcon(":/ch2_14_QListWidget/resources/help.png"), u8"帮助");

    ui.listWidget->addItem(pItem1);
    ui.listWidget->addItem(pItem2);
    ui.listWidget->addItem(pItem3);
    ui.listWidget->addItem(pItem4);
    ui.listWidget->addItem(pItem5);

    initRightMenu();

    //设置菜单策略,必须设置,不然无法显示菜单
    ui.listWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    //连接信号槽
    connect(ui.listWidget, &QListWidget::customContextMenuRequested,
        this, &ch2_14_QListWidget::on_PopupRightMenu);

}

ch2_14_QListWidget::~ch2_14_QListWidget()
{}

void ch2_14_QListWidget::on_PopupRightMenu(const QPoint& pos)
{
    /*使用listwidget中的itemAt方法,返回一个ListWidgetItem对象,
    判断是否点击到了对象,如果是才弹出右击菜单*/
    QListWidgetItem* pItem = ui.listWidget->itemAt(pos);
    if (!pItem)
    {
        return;
    }

    m_pRightMenu->exec(QCursor::pos());
}

void ch2_14_QListWidget::initRightMenu()
{
    m_pRightMenu = new QMenu(this);

    QAction* pAc1 = new QAction("动作1", this);
    QAction* pAc2 = new QAction("动作2", this);
    QAction* pAc3 = new QAction("动作3", this);
    QAction* pAc4 = new QAction("删除", this);

    m_pRightMenu->addAction(pAc1);
    m_pRightMenu->addAction(pAc2);
    m_pRightMenu->addAction(pAc3);
    m_pRightMenu->addAction(pAc4);

    // 右击菜单中,选项1链接一个消息提示
    connect(pAc1, &QAction::triggered, [=] {
        QMessageBox::information(this, "title", "ac1");
        });

    connect(pAc4, &QAction::triggered, [=] {

        // 动态删除
        /*QList<QListWidgetItem*> list;
        list = ui.listWidget->findItems("Kits", Qt::MatchCaseSensitive);

        QListWidgetItem* sel = list[0];
        int r = ui.listWidget->row(sel);

        QListWidgetItem* item = ui.listWidget->takeItem(r);
        ui.listWidget->removeItemWidget(item);

        delete item;*/

        QListWidgetItem* item = ui.listWidget->currentItem();
        ui.listWidget->removeItemWidget(item);
        delete item;
        });
}

编译结果:
在这里插入图片描述

ch2_15 QListWidget用法三——图标模式+右侧滑动条样式

示例:

#include "ch2_15_QListWidget.h"
#include <QVBoxLayout>
#include <QListWidget>

ch2_15_QListWidget::ch2_15_QListWidget(QWidget *parent)
    : QWidget(parent)
{
    resize(600, 500);

    QVBoxLayout* pMainVLayout = new QVBoxLayout(this);

    QListWidget* pListWidget = new QListWidget(this);
    pListWidget->setViewMode(QListView::IconMode);
    pListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    pListWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    int vScrollBarWidth = 30;

    QString qssLW = QString("QScrollBar{width:%1px;background:rgba(255, 255, 255,100%);margin:0px, 0px, 0px, 0px;}\
              QScrollBar::handle:vertical{width:8px;background:rgba(162, 163, 165, 100%);border-radius:4px;min-height:60;}\
              QScrollBar::handle:vertical:hover{width:8px;background:rgba(115,118,118, 100%);border-radius:4px;min-height:60;}\
              QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:rgba(255, 255, 255, 100%);border-radius:4px;}\
              QScrollBar::top-arrow:vertical,QScrollBar::bottom-arrow:vertical{border: none;background: none;color: none;}\
              QScrollBar::add-line:vertical{border:none;background:none;}\
              QScrollBar::sub-line:vertical{border:none;background:none;}\
              QListWidget{background-color:rgb(255,255,255);border:none;} \
              QListWidget::item{  \
              /*background:blue;*/  \
              margin-left:20px;  \
              margin-right:20px; \
              margin-top:10px; \
              } \
    ").arg(QString::number(vScrollBarWidth));



    pListWidget->setStyleSheet(qssLW);

    //180包括margin-left的值
    //如果QListWidget::item没有写margin-right:20px,增加竖直滑动条和最后一列的间隙为margin-left的一半即可,这样看着美观
    //如果QListWidget::item写了margin-right:20px, vScrollBarWidth + 1即可
    pListWidget->setFixedWidth(180 * 3 + vScrollBarWidth + 1);

    for (int i = 0; i < 15; i++)
    {
        QIcon icon(":/ch2_15_QListWidget/env.png");

        QString name = QString(u8"用户%1").arg(QString::number(i));

        QListWidgetItem* pItem = new QListWidgetItem(icon, name);
        pItem->setSizeHint(QSize(180, 100));
        pListWidget->addItem(pItem);
    }

    pMainVLayout->addWidget(pListWidget);
}

ch2_15_QListWidget::~ch2_15_QListWidget()
{}

编译结果:
在这里插入图片描述

ch2_16_17_18 模仿迅雷可以上下滑动的设置界面

任务1:搭建一个迅雷设置页面的主要结构

在这里插入图片描述
示例代码如下:

#pragma once

#include <QtWidgets/QWidget>
#include <QListWidget>
#include <QScrollArea>
#include <QStringList>


class ch2_16_ScrollAreaDemo : public QWidget
{
    Q_OBJECT

public:
    ch2_16_ScrollAreaDemo(QWidget *parent = nullptr);
    ~ch2_16_ScrollAreaDemo();

private:

    //界面所要用到的所有控件,按照从上到下的顺序声明
    QListWidget* m_pListWidget = nullptr;
    QScrollArea* m_pScrollArea = nullptr;


    QStringList m_textList;

    
};

注意查看代码中的注释,一些注意点写在了注释里

#include "ch2_16_ScrollAreaDemo.h"
#include <QHBoxLayout>
#include <string>

using namespace std;


ch2_16_ScrollAreaDemo::ch2_16_ScrollAreaDemo(QWidget *parent)
    : QWidget(parent)
{
    setFixedSize(150 + 1000 + 30 , 900);
	this->setStyleSheet("background:rgb(26, 26, 26)");
	this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);	//隐藏窗口标题和任务栏控制最大最小化
//左边的ListWidget窗口
    m_pListWidget = new QListWidget(this);
    m_pListWidget->setFixedWidth(150);
	m_pListWidget->setFrameShape(QFrame::NoFrame);

    m_textList << "基本设置" << "云盘设置" << "下载设置" << "接管设置" << "任务管理" << "提醒" << "悬浮窗" << "高级设置";
    m_pListWidget->addItems(m_textList);

	string lw_qss = R"(QListWidget			
			{
				/*border:1px solid gray;   使用R字符串优点是避免了一般字符串换行时重复增加反斜杠*/
				background:rgb(26, 26, 26);   
				color:rgb(200, 200, 200);     
				font-size:15px;
				border-radius:1px;
			}

			QListWidget::item
			{
				height:40px;
				padding-left:10px; /*控制文本与left左边的距离*/
			}
		
			QListWidget::item:!active
			{
				background:rgb(26, 26, 26);
				margin:5px 20px 1px 20px;  /*上右下左,控制item与ListWidget的距离,这里好像有问题 */
			}

			QListWidget::item:hover
			{
				background:rgb(56, 56, 56);
				/*padding-left:30px;*/
			}

			QListWidget::item:selected
			{
				border-radius:15px;
				background:lightblue;
			}

		
			QListWidget::item:selected:!active
			{
				background:rgb(51,51,51);
				color:#3F85FF;
			})";

	m_pListWidget->setStyleSheet(QString::fromStdString(lw_qss));

//右边的设置窗口,用QScrollArea控件来实现
    m_pScrollArea = new QScrollArea(this);
    m_pScrollArea->setFixedWidth(1000 + 30);
//添加一个水平布局,把上面创建的两个控件添加进去,setSpacing设置两个控件的间隙
    QHBoxLayout* hlay = new QHBoxLayout(this);
    hlay->addWidget(m_pListWidget);
    hlay->setSpacing(0);
    hlay->addWidget(m_pScrollArea); 

}

ch2_16_ScrollAreaDemo::~ch2_16_ScrollAreaDemo()
{}

编译结果:
在这里插入图片描述

任务2:完善右边QScrollArea控件中的内容

右边的一个个单元设置可以认为是一个个widget窗口,分析第一个基本设置窗口的布局方法如下
在这里插入图片描述
添加一个Qwidget类,用于基本设置
ch2_16_ScrollAreaDemo.h

#pragma once

#include <QtWidgets/QWidget>
#include <QListWidget>
#include <QScrollArea>
#include <QStringList>
#include "CBaseSetWidget.h"
#include <vector>
#include "GaojiSetWidget.h"

using namespace std;

class ch2_16_ScrollAreaDemo : public QWidget
{
    Q_OBJECT

public:
    ch2_16_ScrollAreaDemo(QWidget *parent = nullptr);
    ~ch2_16_ScrollAreaDemo();

private slots:
    void slotItemChlicked(QListWidgetItem* Item);
    void slotValueChanged(int value);

private:

    //界面所要用到的所有控件,按照从上到下的顺序声明
    QListWidget* m_pListWidget = nullptr;
    QScrollArea* m_pScrollArea = nullptr;


    QStringList m_textList;
/*基本设置是创建了一个类来实现的,m_pYunpanSetWidget到m_pXuanfuWidget通过创建一个widget并在其中加入图片做的*/
    CBaseSetWidget* m_pBaseSetWidget;
    QWidget* m_pYunpanSetWidget;
    QWidget* m_pDownloadWidget;
    QWidget* m_pJieguanWidget;
    QWidget* m_pRenwuWidget;
    QWidget* m_pTixingWidget;
    QWidget* m_pXuanfuWidget;
    GaojiSetWidget* m_pGaojiWidget;	//高级设置是用两个图片拼接起来的

    vector<QWidget*> m_vecWidget;	//申明一个容器类用于排列m_pScrollArea中要添加的widget

    bool signFlag = false;
};

ch2_16_ScrollAreaDemo.cpp

#include "ch2_16_ScrollAreaDemo.h"
#include <QHBoxLayout>
#include <string>
#include <QScrollBar>

using namespace std;


ch2_16_ScrollAreaDemo::ch2_16_ScrollAreaDemo(QWidget *parent)
    : QWidget(parent)
{
    setFixedSize(150 + 1000 + 30 + 15 , 900);	//主界面的大小
	this->setStyleSheet("background:rgb(26, 26, 26)");	//主界面的颜色
	this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);	//隐藏窗口标题和任务栏控制最大最小化

    m_pListWidget = new QListWidget(this);	//创建一个QListWidget对象,this是他的父对象,这里就是ch2_16_ScrollAreaDemo
    m_pListWidget->setFixedWidth(150);
	m_pListWidget->setFrameShape(QFrame::NoFrame);	//去除ListWidget的白色边框
	m_pListWidget->setFocusPolicy(Qt::NoFocus);		//去除聚焦策略,避免ListWidget中的Item偏移

    m_textList << "基本设置" << "云盘设置" << "下载设置" << "接管设置" << "任务管理" << "提醒" << "悬浮窗" << "高级设置";
    m_pListWidget->addItems(m_textList);		//一次性添加多个Item
	//QListWidget样式表
	string lw_qss = R"(QListWidget			
			{
				/*border:1px solid gray;   使用R字符串优点是避免了一般字符串换行时重复增加反斜杠*/
				background:rgb(26, 26, 26);   
				color:rgb(200, 200, 200);     
				font-size:15px;
				border-radius:1px;
			}

			QListWidget::item
			{
				height:40px;
				padding-left:10px; /*控制文本与left左边的距离*/
			}
		
			QListWidget::item:!active
			{
				background:rgb(26, 26, 26);
				margin:5px 20px 1px 20px;  /*上右下左,控制item与ListWidget的距离,这里好像有问题 */
			}

			QListWidget::item:hover
			{
				background:rgb(56, 56, 56);
				padding-left:30px;  /*鼠标悬浮效果*/
			}

			QListWidget::item:selected
			{
				border-radius:15px;
				background:lightblue;
			}

		
			QListWidget::item:selected:!active
			{
				background:rgb(51,51,51);
				color:#3F85FF;
			})";

	m_pListWidget->setStyleSheet(QString::fromStdString(lw_qss));

    m_pScrollArea = new QScrollArea(this);
    m_pScrollArea->setFixedWidth(1000 + 30);
	m_pScrollArea->setFrameShape(QFrame::NoFrame); //取消右边QScrollArea白色边框
	m_pScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //取消水平滑动条
	//m_pScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);	//垂直滑动条在需要时显示

	string verticalbar_qss = R"(
		QScrollBar{width:15px;background:rgb(26, 26, 26);margin:0px, 0px, 0px, 0px;}
		QScrollBar::handle:vertical{width:8px;background:rgba(162, 163, 165, 100%);border-radius:4px;min-height:40;}
              QScrollBar::handle:vertical:hover{width:8px;background:rgba(115,118,118, 100%);border-radius:4px;min-height:40;}
              QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:rgb(26, 26, 26);border-radius:4px;}
              QScrollBar::top-arrow:vertical,QScrollBar::bottom-arrow:vertical{border: none;background: none;color: none;}
              QScrollBar::add-line:vertical{border:none;background:none;}
              QScrollBar::sub-line:vertical{border:none;background:none;}
		)";

	m_pScrollArea->verticalScrollBar()->setStyleSheet(QString::fromStdString(verticalbar_qss));

	m_pBaseSetWidget = new CBaseSetWidget;
	m_vecWidget.push_back(m_pBaseSetWidget);

	m_pYunpanSetWidget = new QWidget;
	m_pYunpanSetWidget->setStyleSheet("background-image:url(:/ch2_16_ScrollAreaDemo/resources/YunPanSet.png);background-repeat:no-repeat;background-color:rgb(51,51,51)");
	m_pYunpanSetWidget->setFixedSize(1000, 478);
	m_vecWidget.push_back(m_pYunpanSetWidget);

	m_pDownloadWidget = new QWidget;
	m_pDownloadWidget->setStyleSheet("background-image:url(:/ch2_16_ScrollAreaDemo/resources/XiaZai.png);background-repeat: no-repeat;background-color:rgb(51, 51, 51)");
	m_pDownloadWidget->setFixedSize(1000, 337);
	m_vecWidget.push_back(m_pDownloadWidget);

	m_pJieguanWidget = new QWidget;
	m_pJieguanWidget->setStyleSheet("background-image:url(:/ch2_16_ScrollAreaDemo/resources/JieGuanSet.png);background-repeat: no-repeat;background-color:rgb(51, 51, 51)");
	m_pJieguanWidget->setFixedSize(1000, 340);
	m_vecWidget.push_back(m_pJieguanWidget);

	m_pRenwuWidget = new QWidget;
	m_pRenwuWidget->setStyleSheet("background-image:url(:/ch2_16_ScrollAreaDemo/resources/RenwuGuanli.png);background-repeat: no-repeat;background-color:rgb(51, 51, 51)");
	m_pRenwuWidget->setFixedSize(1000, 413);
	m_vecWidget.push_back(m_pRenwuWidget);

	m_pTixingWidget = new QWidget;
	m_pTixingWidget->setStyleSheet("background-image:url(:/ch2_16_ScrollAreaDemo/resources/TiXing.png);background-repeat: no-repeat;background-color:rgb(51, 51, 51)");
	m_pTixingWidget->setFixedSize(1000, 728);
	m_vecWidget.push_back(m_pTixingWidget);

	m_pXuanfuWidget = new QWidget;
	m_pXuanfuWidget->setStyleSheet("background-image:url(:/ScrollAreaDemo/resources/XuanFuChuang.png);background-repeat: no-repeat;background-color:rgb(51, 51, 51)");
	m_pXuanfuWidget->setFixedSize(1000, 206);
	m_vecWidget.push_back(m_pXuanfuWidget);

	m_pGaojiWidget = new GaojiSetWidget;
	m_vecWidget.push_back(m_pGaojiWidget);

	QWidget* widget = new QWidget;
	QVBoxLayout* pVLay = new QVBoxLayout(widget);

	for (auto w : m_vecWidget)
	{	//给每一个m_vecWidget的元素之间增加间隙
		pVLay->addWidget(w);
		pVLay->addSpacing(15);
	}

	pVLay->setContentsMargins(0, 5, 0, 5);

	m_pScrollArea->setWidget(widget);


    QHBoxLayout* hlay = new QHBoxLayout(this);
    hlay->addWidget(m_pListWidget);
    hlay->setSpacing(0);
    hlay->addWidget(m_pScrollArea);

	connect(m_pListWidget, &QListWidget::itemClicked, this, &ch2_16_ScrollAreaDemo::slotItemChlicked);

	connect(m_pScrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, &ch2_16_ScrollAreaDemo::slotValueChanged);
    

}

//左侧Item点击的槽函数,点击标签在右侧显示对应设置
void ch2_16_ScrollAreaDemo::slotItemChlicked(QListWidgetItem* item)
{
	signFlag = true;
	QString itemText = item->text();
	QPoint widgetPos;

	int size = m_textList.size();
	for (int i = 0; i < size; i++)
	{
		if (itemText == m_textList[i])
		{
			widgetPos = m_vecWidget[i]->pos();
		}
	}

	m_pScrollArea->verticalScrollBar()->setValue(widgetPos.y());
}
//右边设置页面跟随滚动条变化
void ch2_16_ScrollAreaDemo::slotValueChanged(int value)
{
	if (!signFlag)
	{
		int itemSize = m_vecWidget.size();
		for (int i = 0; i < itemSize; i++)
		{
			if (!m_vecWidget[i]->visibleRegion().isEmpty())
			{
				m_pListWidget->item(i)->setSelected(true);
				return;
			}
			else
			{
				m_pListWidget->item(i)->setSelected(false);
			}
		}
	}

	signFlag = false;
}

ch2_16_ScrollAreaDemo::~ch2_16_ScrollAreaDemo()
{}

基础设置,CBaseSetWidget.h

#include <QWidget>

#pragma once
class CBaseSetWidget:public QWidget
{
public:

	CBaseSetWidget(QWidget* parent = nullptr);
	~CBaseSetWidget();

};

CBaseSetWidget.cpp,根据基础设置布局手动代码布局

#include "CBaseSetWidget.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QRadioButton>
#include <QCheckBox>

CBaseSetWidget::CBaseSetWidget(QWidget* parent)
	:QWidget(parent)
{
	setWindowFlags(Qt::FramelessWindowHint);
	setAttribute(Qt::WA_StyledBackground);
	this->setStyleSheet("background-color:rgb(51, 51, 51);color:rgb(200,200,200);");

	QLabel* pBaseSetLabel = new QLabel(this);
	pBaseSetLabel->setText("基本设置");

	QCheckBox* pCheckKaijiqidong = new QCheckBox(this);
	pCheckKaijiqidong->setText("开机启动");

	QCheckBox* pCheckMiandarao = new QCheckBox(this);
	pCheckMiandarao->setFixedWidth(140);
	pCheckMiandarao->setText("开启免打扰模式");

	QLabel* p1 = new QLabel(this);
	p1->setText("?");

	QCheckBox* pCheckBosskey = new QCheckBox(this);
	pCheckBosskey->setFixedWidth(105);
	pCheckBosskey->setText("开启老板键");

	QLineEdit* pLineEdit = new QLineEdit(this);
	pLineEdit->setFixedWidth(100);
	pLineEdit->setStyleSheet("bordor-style:solid;bordor-width:1px;bordor-color:rgb(79,79,79);");

	QLabel* p2 = new QLabel(this);
	p2->setText("?");

	QCheckBox* pCheckNewShowMainUI = new QCheckBox(this);
	pCheckNewShowMainUI->setText("新建时显示主界面");

	QLabel* pXiazaimoshi = new QLabel(this);
	pXiazaimoshi->setText("下载模式");

	QRadioButton* pQuansuxiazai = new QRadioButton(this);
	pQuansuxiazai->setText("全速下载");

	QRadioButton* pXiansuxiazai = new QRadioButton(this);
	pXiansuxiazai->setText("限速下载");
	pXiansuxiazai->setFixedWidth(90);

	QPushButton* pBtnModify = new QPushButton(this);
	pBtnModify->setText("修改设置");
	pBtnModify->setStyleSheet("background-color:#1A1A1A;color:#5F5F5F");

	QLabel* label_cfginfo = new QLabel(this);
	label_cfginfo->setText("限制时间段: 00:00-23:59 最大下载速度:不限速");

	QVBoxLayout* pMainVlay = new QVBoxLayout(this);
	pMainVlay->addWidget(pBaseSetLabel);
	pMainVlay->addSpacing(20);

	QHBoxLayout* pHlay1 = new QHBoxLayout(this);
	pHlay1->addSpacing(35);

	QVBoxLayout* pVlay1 = new QVBoxLayout(this);
	pVlay1->addWidget(pCheckKaijiqidong);
	pVlay1->addSpacing(20);

	QHBoxLayout* pHlay2 = new QHBoxLayout(this);
	pHlay2->addWidget(pCheckMiandarao);
	pHlay2->addWidget(p1);

	//把免打扰的水平布局添加到pVlay1中
	pVlay1->addLayout(pHlay2);
	pVlay1->addSpacing(20);

	QHBoxLayout* pHlay3 = new QHBoxLayout(this);
	pHlay3->addWidget(pCheckBosskey);
	pHlay3->addWidget(pLineEdit);
	pHlay3->addWidget(p1);

	pVlay1->addLayout(pHlay3);
	pVlay1->addSpacing(20);

	pVlay1->addWidget(pCheckNewShowMainUI);
	pVlay1->addSpacing(20);
	//下载模式
	pVlay1->addWidget(pXiazaimoshi);
	pVlay1->addSpacing(20);

	QHBoxLayout* pHlay4 = new QHBoxLayout(this);
	pHlay4->addSpacing(30);

	QVBoxLayout* pVlay2 = new QVBoxLayout(this);
	
	QHBoxLayout* pHlay5 = new QHBoxLayout(this);
	pHlay5->addWidget(pQuansuxiazai);
	pHlay5->addWidget(p2);
	pVlay2->addLayout(pHlay5);
	pVlay2->addSpacing(20);

	QHBoxLayout* pHlay6 = new QHBoxLayout(this);
	pHlay6->addWidget(pXiansuxiazai);
	pHlay6->addWidget(pBtnModify);
	pHlay6->addWidget(label_cfginfo);

	pHlay6->addStretch();	//增加一个弹簧
	pVlay2->addLayout(pHlay6);

	pHlay4->addLayout(pVlay2);
	pVlay1->addLayout(pHlay4);
	pHlay1->addLayout(pVlay1);
	
	pMainVlay->addLayout(pHlay1);
	pMainVlay->setContentsMargins(20, 20, 20, 20);


}

CBaseSetWidget::~CBaseSetWidget()
{
}

因为高级设置页面比较长,所以采取两种图片拼接的方式来显示,GaojiSetWidget.h

#pragma once

#include <QWidget>

class GaojiSetWidget:public QWidget
{
	Q_OBJECT

public:
	GaojiSetWidget(QWidget* parent = Q_NULLPTR);
	~GaojiSetWidget();

private:

};

GaojiSetWidget.cpp

#include "GaojiSetWidget.h"

#include <QVBoxLayout>
#include <QLabel>

GaojiSetWidget::GaojiSetWidget(QWidget* parent)
	: QWidget(parent)
{
	QLabel* pLabel1 = new QLabel(this);
	pLabel1->setFixedSize(1000, 541);
	QPixmap* pixmap = new QPixmap(":/ch2_16_ScrollAreaDemo/resources/GaojiSet_1.png");
	pixmap->scaled(pLabel1->size(), Qt::KeepAspectRatio);
	pLabel1->setScaledContents(true);
	pLabel1->setPixmap(*pixmap);

	QLabel* pLabel2 = new QLabel(this);
	pLabel2->setFixedSize(1000, 685);
	pixmap = new QPixmap(":/ch2_16_ScrollAreaDemo/resources/GaojiSet_2.png");
	pixmap->scaled(pLabel2->size(), Qt::KeepAspectRatio);
	pLabel2->setScaledContents(true);
	pLabel2->setPixmap(*pixmap);

	QVBoxLayout* pVLay = new QVBoxLayout(this);
	pVLay->addWidget(pLabel1);
	pVLay->setSpacing(0);
	pVLay->addWidget(pLabel2);
	pVLay->setContentsMargins(0, 0, 0, 0);
}

GaojiSetWidget::~GaojiSetWidget()
{
}

编译结果:
在这里插入图片描述
还需要改进的地方: 基本设置中的问号离其他控件间距不正确;右边的界面在扩展显示器上图片显示不全;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值