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

溧水做网站价格商务网站建设摘要

溧水做网站价格,商务网站建设摘要,凡客网络科技,用媒体做响应式网站可以吗WidgetBase 类旨在实现窗口的可调整大小功能#xff0c;使用户能够手动改变窗口的尺寸。该类通过以下机制实现窗口缩放效果#xff1a;当鼠标移动至窗口边缘时#xff0c;鼠标指针样式会动态改变以指示可调整大小的方向。用户在边缘区域按下鼠标左键后#xff0c;可以通过拖…WidgetBase 类旨在实现窗口的可调整大小功能使用户能够手动改变窗口的尺寸。该类通过以下机制实现窗口缩放效果当鼠标移动至窗口边缘时鼠标指针样式会动态改变以指示可调整大小的方向。用户在边缘区域按下鼠标左键后可以通过拖动鼠标实时调整窗口的大小从而实现对窗口尺寸的交互式控制。 WidgetBase.h #pragma once #include qwidget.h class WidgetBase :public QWidget {Q_OBJECT public:WidgetBase(QWidget* p nullptr);~WidgetBase();protected:bool nativeEvent(const QByteArray eventType, void* message, qintptr* result) override;private:int int_BorderWidth 5;};为了实现窗口可调整大小的效果我们通过重写 nativeEvent 函数来实现所需的功能。int_BorderWidth 表示窗口边缘的自定义宽度。当鼠标位于距离窗口边界 5 像素以内的区域时将其视为处于窗口边界。通过这种方式我们能够检测鼠标与窗口边缘的交互进而调整窗口的大小。 WidgetBase.cpp #include WidgetBase.h#ifdef Q_OS_WINDOWS #include windows.h #include windowsx.h #include qt_windows.h #endif // Q_OS_WINDOWSWidgetBase::WidgetBase(QWidget* p) :QWidget(p) {setWindowFlags(Qt::FramelessWindowHint); }WidgetBase::~WidgetBase() {}bool WidgetBase::nativeEvent(const QByteArray eventType, void* message, qintptr* result) {MSG* param static_castMSG*(message);switch (param-message) {case WM_NCHITTEST:QPoint qpoint_globalPos QCursor::pos();QPoint qpoint_lobalPos this-mapFromGlobal(qpoint_globalPos);int int_NX qpoint_lobalPos.x();int int_NY qpoint_lobalPos.y();if (childAt(int_NX, int_NY) ! nullptr) return QWidget::nativeEvent(eventType, message, result);if (int_NX 0 int_NX int_BorderWidth) *result HTLEFT;if (int_NY 0 int_NY int_BorderWidth) *result HTTOP;if (int_NXthis-width() int_NXthis-width() - int_BorderWidth) *result HTRIGHT;if (int_NYthis-height() int_NYthis-height() - int_BorderWidth) *result HTBOTTOM;if (int_NX 0 int_NX int_BorderWidth int_NY 0 int_NY int_BorderWidth)*result HTTOPLEFT;if (int_NX 0 int_NX int_BorderWidth int_NYthis-height() int_NYthis-height() - int_BorderWidth) *result HTBOTTOMLEFT;if (int_NY 0 int_NY int_BorderWidth int_NXthis-width() int_NXthis-width() - int_BorderWidth) *result HTTOPRIGHT;if (int_NYthis-height() int_NYthis-height() - int_BorderWidth int_NXthis-width() int_NXthis-width() - int_BorderWidth)*result HTBOTTOMRIGHT;return true;}return QWidget::nativeEvent(eventType, message, result); }1. MSG* param static_castMSG*(message); 使用 static_cast 对 message 进行类型转换将其转换为 MSG* 类型。这是一种安全的类型转换方式用于将通用的 void* 指针转换为特定的数据类型。在这里将 message 转换为 MSG* 类型以便访问 Windows 消息的相关信息。 2. switch (param-message) { 检查 param 中的 message 成员变量该变量表示当前接收到的 Windows 消息类型。通过 switch 语句进行分支处理根据不同的消息类型执行相应的操作。 3. case WM_NCHITTEST: WM_NCHITTEST 是一个 Windows 消息用于确定鼠标指针相对于窗口的位置。该消息的返回值指示鼠标所在窗口区域例如标题栏、边框、工作区等从而决定了鼠标指针的功能例如移动、调整大小等。在自定义窗口中该消息的处理是实现窗口边缘调整大小等交互行为的关键。 QPoint qpoint_globalPos QCursor::pos();QPoint qpoint_lobalPos this-mapFromGlobal(qpoint_globalPos);int int_NX qpoint_lobalPos.x();int int_NY qpoint_lobalPos.y();1. QPoint qpoint_globalPos QCursor::pos(); 该语句使用 QCursor::pos() 获取鼠标在屏幕上的全局坐标并将其存储在 qpoint_globalPos 变量中。QCursor::pos() 返回一个 QPoint 对象表示当前鼠标指针在整个屏幕坐标系中的位置。 2. QPoint qpoint_localPos this-mapFromGlobal(qpoint_globalPos); 使用 mapFromGlobal() 函数将鼠标的全局坐标转换为窗口的局部坐标。this-mapFromGlobal(qpoint_globalPos) 会将全局坐标 qpoint_globalPos 转换为相对于当前窗口this的坐标系并将结果存储在 qpoint_localPos 变量中。这一步使得鼠标的位置可以相对于窗口的边界进行检测。 3. int int_NX qpoint_localPos.x(); int int_NY qpoint_localPos.y(); 获取局部坐标中的横坐标x和纵坐标y并分别存储在 int_NX 和 int_NY 中。这两个值表示鼠标在窗口内部的位置方便后续判断鼠标是否处于窗口边缘以实现自定义的调整大小功能。 if (childAt(int_NX, int_NY) ! nullptr) return QWidget::nativeEvent(eventType, message, result);1. childAt(int_NX, int_NY): 该函数用于检测给定的局部坐标 (int_NX, int_NY) 是否位于窗口的某个子控件上。它返回一个指向位于此坐标处的子控件的指针。如果没有子控件位于该位置返回 nullptr。 2. if (childAt(int_NX, int_NY) ! nullptr): 这条语句检查鼠标是否位于窗口的子控件上。如果 childAt 返回的不是 nullptr表示鼠标在某个子控件上。 3. return QWidget::nativeEvent(eventType, message, result);: 如果鼠标位于子控件上调用基类 QWidget 的 nativeEvent 方法进行默认处理并立即返回。这表示当前的自定义 nativeEvent 函数不处理鼠标事件交由 QWidget 类的默认实现来处理。这样做的目的是让子控件自行处理鼠标事件例如点击按钮、输入框等。 if (int_NX 0 int_NX int_BorderWidth) *result HTLEFT;if (int_NY 0 int_NY int_BorderWidth) *result HTTOP;if (int_NXthis-width() int_NXthis-width() - int_BorderWidth) *result HTRIGHT;if (int_NYthis-height() int_NYthis-height() - int_BorderWidth) *result HTBOTTOM;if (int_NX 0 int_NX int_BorderWidth int_NY 0 int_NY int_BorderWidth)*result HTTOPLEFT;if (int_NX 0 int_NX int_BorderWidth int_NYthis-height() int_NYthis-height() - int_BorderWidth) *result HTBOTTOMLEFT;if (int_NY 0 int_NY int_BorderWidth int_NXthis-width() int_NXthis-width() - int_BorderWidth) *result HTTOPRIGHT;if (int_NYthis-height() int_NYthis-height() - int_BorderWidth int_NXthis-width() int_NXthis-width() - int_BorderWidth)*result HTBOTTOMRIGHT;return true;通过检测鼠标在窗口局部坐标中的位置确定其所处的窗口区域例如左侧边缘、右下角、顶部边缘等并根据不同的区域设置 *result 为相应的命中测试值如 HTLEFT、HTTOPRIGHT、HTBOTTOM 等。这些值用于指示窗口区域的性质从而实现对窗口调整大小、移动等操作的处理。 MainWidget.h #pragma once#include QtWidgets/QMainWindow #include ui_MainWidget.h #include WidgetBase.hclass MainWidget : public WidgetBase {Q_OBJECTpublic:MainWidget(QWidget *parent nullptr);~MainWidget();private slots:void on_close();private:Ui::MainWidgetClass ui; }; class MainWidget : public WidgetBase主窗口头文件继承WidgetBase. MainWidget.cpp #include MainWidget.h #include TapTitle.h #include QBoxLayout #include TabBrowser.hMainWidget::MainWidget(QWidget *parent): WidgetBase(parent) {resize(600, 400);TabBrowser* TabBrowser_pmain new TabBrowser(this);QVBoxLayout* layoutVP_main new QVBoxLayout(this);QWidget* widget_main new QWidget(this);layoutVP_main-addWidget(TabBrowser_pmain);layoutVP_main-addWidget(widget_main);setLayout(layoutVP_main);connect(TabBrowser_pmain, TabBrowser::sig_close, this, MainWidget::on_close);}MainWidget::~MainWidget() {}void MainWidget::on_close() {/*其他业务逻辑*/close(); } MainWidget 类的声明采用了单继承的方式继承自基类 WidgetBase。在主窗口的头文件中class MainWidget : public WidgetBase 表明 MainWidget 是 WidgetBase 的派生类具备 WidgetBase 中的所有属性和方法并可以在此基础上扩展功能。 在主窗口的实现文件.cpp 文件中通过构造函数初始化列表 MainWidget::MainWidget(QWidget *parent) : WidgetBase(parent) 调用基类 WidgetBase 的构造函数并将 parent 参数传递给基类以确保 WidgetBase 的初始化过程得以正确执行。这种继承机制使得 MainWidget 可以重用 WidgetBase 的功能并在此基础上实现自定义的窗口逻辑。 通过继承 WidgetBase 类MainWidget 自动继承了 WidgetBase 实现的窗口缩放功能。由于 WidgetBase 已重写了窗口缩放逻辑相关的事件处理如 nativeEvent因此 MainWidget 作为派生类能够直接复用这些功能而无需额外的实现。这种基于继承的机制允许 MainWidget 具备 WidgetBase 的自定义窗口交互特性包括对窗口边缘的调整大小等行为。 TapTitle.h #pragma once #include qwidget.h #include qpushbutton.h #include qboxlayout.hclass TapTitle :public QWidget {Q_OBJECT public:TapTitle(QWidget* p nullptr);~TapTitle(); protected:void paintEvent(QPaintEvent* event) override;void mousePressEvent(QMouseEvent* event) override;void mouseDoubleClickEvent(QMouseEvent* event) override;public:void setEmptyWidgetWidth(int w); signals:void sig_close();void sig_addtab();private slots:void on_Clicked();private:QPushButton* m_pAddBtn nullptr;QWidget* m_pEmptyWidget nullptr;QPushButton* m_pUserBtn nullptr;QPushButton* m_pMinBtn nullptr;QPushButton* m_pMaxBtn nullptr;QPushButton* m_pCloseBtn nullptr;}; TapTitle.cpp #include TapTitle.h #include QMouseEvent #include QDebug #include QPainter #include QStyleOption#ifdef Q_OS_WINDOWS #include qt_windows.h #pragma comment(lib,user32.lib) #endif // Q_OS_WINDOWSTapTitle::TapTitle(QWidget* p) :QWidget(p) {setStyleSheet(background-color:#E3E4E7);this-setFixedHeight(32 8);this-setContentsMargins(0, 0, 0, 0);m_pAddBtn new QPushButton(this);m_pEmptyWidget new QWidget(this);m_pUserBtn new QPushButton(this);m_pMinBtn new QPushButton(this);m_pMaxBtn new QPushButton(this);m_pCloseBtn new QPushButton(this);m_pAddBtn-setFixedSize(32, 32);m_pUserBtn-setFixedSize(32, 32);m_pMinBtn-setFixedSize(32, 32);m_pMaxBtn-setFixedSize(32, 32);m_pCloseBtn-setFixedSize(32, 32);//background-image border-image:url(:/MainWidget/resources/titlebar/title_icon.png);m_pAddBtn-setStyleSheet(background-image:url(:/MainWidget/resources/add.svg));m_pEmptyWidget-setStyleSheet(QWidget:hover { background: none; border: none; });m_pUserBtn-setStyleSheet(background-image:url(:/MainWidget/resources/user.png));m_pMinBtn-setStyleSheet(background-image:url(:/MainWidget/resources/min.svg));m_pMaxBtn-setStyleSheet(background-image:url(:/MainWidget/resources/max.svg));m_pCloseBtn-setStyleSheet(background-image:url(:/MainWidget/resources/close.svg));m_pAddBtn-setFlat(true);m_pUserBtn-setFlat(true);m_pMinBtn-setFlat(true);m_pMaxBtn-setFlat(true);m_pCloseBtn-setFlat(true);//m_pEmptyWidget-setAttribute(Qt::WA_Hover, false);this-setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);QHBoxLayout* pHLay new QHBoxLayout(this);pHLay-addWidget(m_pAddBtn);pHLay-addWidget(m_pEmptyWidget);pHLay-addStretch();pHLay-addWidget(m_pUserBtn);pHLay-addWidget(m_pMinBtn);pHLay-addWidget(m_pMaxBtn);pHLay-addWidget(m_pCloseBtn);setLayout(pHLay);connect(m_pAddBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pMinBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pMaxBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pCloseBtn, QPushButton::clicked, this, TapTitle::on_Clicked);}TapTitle::~TapTitle() {}void TapTitle::paintEvent(QPaintEvent* event) {QStyleOption opt;opt.initFrom(this);QPainter p(this);style()-drawPrimitive(QStyle::PE_Widget, opt, p, this);QWidget::paintEvent(event); }void TapTitle::mousePressEvent(QMouseEvent* event) {if (ReleaseCapture()) {if (this-window()-isTopLevel()) {SendMessage(HWND(this-window()-winId()), WM_SYSCOMMAND, SC_MOVE HTCAPTION, 0);}} }void TapTitle::mouseDoubleClickEvent(QMouseEvent* event) {emit m_pMaxBtn-clicked(); }void TapTitle::setEmptyWidgetWidth(int w) {m_pEmptyWidget-setMinimumWidth(w); }void TapTitle::on_Clicked() {QPushButton* pButton qobject_castQPushButton*(sender());QWidget* pWindow this-window();if (pWindow-isTopLevel()) {if (pButton m_pAddBtn) {emit sig_addtab();} else if (pButton m_pMinBtn) {pWindow-showMinimized();} else if (pButton m_pMaxBtn) {if (pWindow-isMaximized()) pWindow-showNormal();else pWindow-showMaximized();} else if (pButton m_pCloseBtn) {emit sig_close();}}} 标题栏拖拉窗口 TapTitle 类表示自定义窗口的标题栏由多个控件组成包括 m_pAddBtn、m_pEmptyWidget、m_pUserBtn、m_pMinBtn、m_pMaxBtn 和 m_pCloseBtn 等。这些控件共同构成了标题栏的交互部分如添加按钮、最小化、最大化、关闭等功能。 由于 TapTitle 是一个自定义标题栏为了实现窗口的拖动效果需要重写 mousePressEvent 以处理鼠标按下事件。通过调用 Windows API来实现窗口在标题栏区域的拖动。以下是各个关键步骤的专业描述 ReleaseCapture()调用此函数释放当前窗口对鼠标事件的捕获使得操作系统能够重新接管鼠标事件的处理。这是实现窗口拖动的第一步确保后续的拖动操作能够由系统默认的窗口移动机制处理。 if (this-window()-isTopLevel())检查当前窗口是否为顶级窗口。只有顶级窗口即没有父窗口的窗口才具备移动的能力因此这一步是执行窗口拖动操作的前提条件。此判断用于确保仅在合适的窗口层级上执行拖动。 SendMessage(HWND(this-window()-winId()), WM_SYSCOMMAND, SC_MOVE HTCAPTION, 0);通过 SendMessage 函数向操作系统发送系统命令 (WM_SYSCOMMAND) 消息指示系统开始处理窗口的移动操作。SC_MOVE HTCAPTION 参数告诉操作系统此次移动是通过拖动标题栏来实现的。HWND(this-window()-winId()) 获取当前窗口的句柄确保消息发送到正确的窗口实例。这一操作触发了系统的窗口拖动机制使用户可以通过鼠标拖动标题栏来移动整个窗口。 控件的信号与槽函数连接 connect(m_pAddBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pMinBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pMaxBtn, QPushButton::clicked, this, TapTitle::on_Clicked);connect(m_pCloseBtn, QPushButton::clicked, this, TapTitle::on_Clicked);void TapTitle::on_Clicked() {QPushButton* pButton qobject_castQPushButton*(sender());QWidget* pWindow this-window();if (pWindow-isTopLevel()) {if (pButton m_pAddBtn) {emit sig_addtab();} else if (pButton m_pMinBtn) {pWindow-showMinimized();} else if (pButton m_pMaxBtn) {if (pWindow-isMaximized()) pWindow-showNormal();else pWindow-showMaximized();} else if (pButton m_pCloseBtn) {emit sig_close();}}}connect(m_pAddBtn, QPushButton::clicked, this, TapTitle::on_Clicked); 该语句使用 Qt 的信号-槽机制将 m_pAddBtn 对象的 clicked 信号与当前窗口的槽函数 TapTitle::on_Clicked 进行连接。这样当用户点击 m_pAddBtn 按钮时Qt 框架会自动调用 on_Clicked 槽函数。由于其他按钮m_pMinBtn、m_pMaxBtn、m_pCloseBtn也连接到相同的槽函数所以在槽函数内部通过逻辑判断具体是哪个按钮触发了信号并执行相应的操作。 QPushButton* pButton qobject_castQPushButton*(sender()); 该语句使用 qobject_cast 将信号发送者 (sender()) 安全地转换为 QPushButton* 类型。sender() 返回发出信号的对象的指针但它是一个通用的 QObject*。qobject_cast 提供了一种类型安全的方式将 QObject* 转换为特定的 QPushButton* 类型。如果 sender() 实际上不是一个 QPushButton则 qobject_cast 将返回 nullptr确保程序不会因为类型不匹配而发生错误。 QWidget* pWindow this-window(); 通过调用 this-window() 获取当前组件所属的顶层窗口对象的指针。这个方法用于返回包含当前部件的窗口这样可以在顶层窗口上执行窗口控制操作例如最小化、最大化和关闭等操作。 if (pWindow-isTopLevel()) 该语句检查当前窗口是否为顶级窗口。顶级窗口是没有父窗口的窗口是应用程序的主要界面窗口。只有顶级窗口才能执行特定的窗口管理操作如最小化、最大化和关闭。此检查确保后续的窗口控制操作只在适用的上下文中执行避免在子窗口或嵌套窗口中执行不合理的操作。 按钮点击事件的处理逻辑 if (pButton m_pAddBtn): 判断触发信号的按钮是否为 m_pAddBtn添加标签页按钮。如果是发射自定义信号 sig_addtab()。该信号是一个自定义的 Qt 信号外部对象可以通过连接到该信号的槽函数来响应标签页添加的操作。 else if (pButton m_pMinBtn): 判断触发信号的按钮是否为 m_pMinBtn最小化按钮。如果是则调用 pWindow-showMinimized() 方法将顶层窗口最小化。showMinimized() 是 QWidget 类的成员函数用于改变窗口的状态使其最小化到任务栏中从而不占用桌面空间。 else if (pButton m_pMaxBtn): 判断触发信号的按钮是否为 m_pMaxBtn最大化按钮。如果是进一步检查窗口的当前状态 如果窗口已经处于最大化状态调用 pWindow-showNormal() 恢复窗口到普通尺寸。如果窗口未处于最大化状态调用 pWindow-showMaximized() 将窗口最大化。此逻辑实现了窗口在普通状态和最大化状态之间的切换。 else if (pButton m_pCloseBtn): 判断触发信号的按钮是否为 m_pCloseBtn关闭按钮。如果是发射自定义信号 sig_close()通知外部对象执行窗口关闭操作。通过使用自定义信号可以灵活地让外部槽函数响应关闭事件进行如保存数据、清理资源等操作。 双击标题栏 void TapTitle::mouseDoubleClickEvent(QMouseEvent* event): 这是 TapTitle 类中重写的 mouseDoubleClickEvent 函数用于处理鼠标在窗口标题栏上的双击事件。QMouseEvent* event 是鼠标事件对象包含了双击的位置信息和其他属性。通过重写此事件处理函数TapTitle 类可以自定义双击标题栏时的行为。 emit m_pMaxBtn-clicked();: 该语句模拟了 m_pMaxBtn 的点击信号。emit 是 Qt 中用于发送信号的关键字在这里直接触发了 m_pMaxBtn 的 clicked() 信号。这样就实现了鼠标双击标题栏与点击最大化按钮的等效效果。通常情况下双击标题栏会触发窗口在最大化和还原状态之间切换此实现通过模拟按钮点击来完成这一交互。 自定义函数实现设置空白widget宽度 void TapTitle::setEmptyWidgetWidth(int w): 这是 TapTitle 类的成员函数用于设置标题栏中 m_pEmptyWidget 的宽度。该函数接受一个整数参数 w表示所需的宽度值。 m_pEmptyWidget-setMinimumWidth(w);: 调用了 m_pEmptyWidget 的 setMinimumWidth 函数将其最小宽度设置为传入的参数 w。setMinimumWidth 是 QWidget 类的成员函数它指定了控件的最小宽度确保控件不会被压缩到比这个宽度更小的尺寸。此操作允许动态调整标题栏中占位控件的大小以适应不同的布局需求。 TabBrowser.h #pragma once #include QTabWidget #include TapTitle.h #include QMenuclass TabBrowser :public QTabWidget {Q_OBJECT public:TabBrowser(QWidget* p nullptr);~TabBrowser();enum TAB_FLAG {NEW,CLOSE,NORMAL,SPECIAL};signals:void sig_close();void sig_addtab();private slots:void on_newTab();void on_closeTab(int index);protected:void resizeEvent(QResizeEvent* e) override; private:void initTabWidget();void setTabBarFlag(TAB_FLAG flag);void creatTabMenu();void onMenuShow(const QPoint pos);private:TapTitle* m_pTabTitle nullptr;QMenu* m_pTabMenu nullptr; }; TabBrowser.cpp #include TabBrowser.h #include QTabBar #include QFrame #include QMenu #include QActionQString commonQss R(QTabBar::tab {font: 75 12pt Arial;text-align: left;width: 184px;height: 32px; /* 添加像素单位 */background: #FFFFFF;border: 2px solid #FFFFFF;border-bottom-color: #FFFFFF;border-top-left-radius: 4px;border-top-right-radius: 4px;padding: 2px;margin-top: 0px;margin-right: 1px;margin-left: 1px;margin-bottom: 0px;}QTabBar::tab:selected {color: #333333; /* 文字颜色 */background-color: #FFFFFF;}QTabBar::tab:!selected {color: #B2B2B2;border-color: #FFFFFF;} );QString qss0 commonQss R(QTabBar::scroller {width: 0px;} );QString qss1 commonQss R(QTabBar::scroller {width: 36px;} );TabBrowser::TabBrowser(QWidget* p):QTabWidget(p) {initTabWidget();this-addTab(new QWidget, 稻壳);this-setUsesScrollButtons(true);this-setTabsClosable(true);this-setMovable(true);setTabBarFlag(NORMAL);this-setStyleSheet(qss0);connect(this, QTabWidget::tabCloseRequested, this, TabBrowser::on_closeTab); }TabBrowser::~TabBrowser() {}void TabBrowser::on_newTab() {int Ncount count();QString title QString::number(Ncount);title Page title;this-insertTab(Ncount,new QWidget,title);if (!tabsClosable()) {setTabsClosable(true);}setTabBarFlag(NEW);}void TabBrowser::on_closeTab(int index) {widget(index)-deleteLater();setTabBarFlag(CLOSE);//当只剩下1个tab时if (count() 1) {setTabsClosable(false);setTabBarFlag(SPECIAL);} }void TabBrowser::resizeEvent(QResizeEvent* e) {setTabBarFlag(NORMAL);QTabWidget::resizeEvent(e);}void TabBrowser::initTabWidget() {this-setContextMenuPolicy(Qt::CustomContextMenu);m_pTabTitle new TapTitle(this);creatTabMenu();connect(this, QTabWidget::customContextMenuRequested, this, TabBrowser::onMenuShow);this-setCornerWidget(m_pTabTitle, Qt::TopRightCorner);connect(m_pTabTitle, TapTitle::sig_close, this, TabBrowser::sig_close);connect(m_pTabTitle, TapTitle::sig_addtab, this, TabBrowser::on_newTab); }void TabBrowser::setTabBarFlag(TAB_FLAG flag) {int w this-width();int tableWidth 0;int tabs this-count();if (flag NULL || flag NORMAL) {for (int i 0; i tabs; i) {tableWidth tabBar()-tabRect(i).width();}} else {for (int i 0; i tabs - 1; i) {tableWidth tabBar()-tabRect(i).width();}}if (w tableWidth) {m_pTabTitle-setEmptyWidgetWidth(w - tableWidth - 32 * 5 - 15);this-setStyleSheet(qss0);} else {m_pTabTitle-setEmptyWidgetWidth(100);this-setStyleSheet(qss1);} }void TabBrowser::creatTabMenu() {m_pTabMenu new QMenu(this);QAction* pAcSave new QAction(QIcon(:/MainWidget/resources/save.png), u8保存, m_pTabMenu);QAction* pAcSaveAS new QAction(QIcon(),u8另存为,m_pTabMenu);QAction* pAcShareDoc new QAction(QIcon(:/MainWidget/resources/share.png), u8分享文档, m_pTabMenu);QAction* pAcSendToDevice new QAction(QIcon(),u8发送到设备);QAction* pAcNewName new QAction(QIcon(),u8重命名,m_pTabMenu);QAction* pAcSaveToWPSCloud new QAction(QIcon(),u8保存到WPS文档,m_pTabMenu);QAction* pAcCloseAll new QAction(QIcon(),u8关闭所有文件,m_pTabMenu);m_pTabMenu-addAction( pAcSave);m_pTabMenu-addAction(pAcSaveAS);m_pTabMenu-addSeparator();m_pTabMenu-addAction(pAcShareDoc);m_pTabMenu-addAction(pAcSendToDevice);m_pTabMenu-addSeparator();m_pTabMenu-addAction(pAcNewName);m_pTabMenu-addAction(pAcSaveToWPSCloud);m_pTabMenu-addAction(pAcCloseAll);}void TabBrowser::onMenuShow(const QPoint pos) {int index this-tabBar()-tabAt(pos);if (index ! -1) {m_pTabMenu-exec(QCursor::pos());} } TabBrowser 类继承自 QTabWidget用于创建一个具有自定义标题栏和交互功能的选项卡控件。在 TabBrowser 的构造函数 TabBrowser::TabBrowser(QWidget* p) 中调用了 QTabWidget 的构造函数并将父窗口指针 p 传递给基类实现对选项卡控件的初始化。TabBrowser 类默认添加一个 QTabWidget 实例同时引入了其他自定义组件组合成一个新的选项卡控件。 TapTitle* m_pTabTitle nullptr;: m_pTabTitle 是一个指向 TapTitle 对象的指针用于表示自定义的标题栏。TapTitle 是一个自定义类继承自 QWidget用于替代默认的 QTabWidget 标题栏实现更加丰富的交互功能例如添加标签、关闭标签、拖动窗口等。通过在 TabBrowser 中组合 TapTitle实现对选项卡标题栏的高度自定义。 QMenu* m_pTabMenu nullptr;: m_pTabMenu 是一个指向 QMenu 对象的指针用于表示选项卡控件的上下文菜单。通过在 TabBrowser 中组合 QMenu实现右键菜单的自定义为用户提供选项卡的额外操作如添加、关闭、重命名等。 initTabWidget() void TabBrowser::initTabWidget() {this-setContextMenuPolicy(Qt::CustomContextMenu);m_pTabTitle new TapTitle(this);creatTabMenu();connect(this, QTabWidget::customContextMenuRequested, this, TabBrowser::onMenuShow);this-setCornerWidget(m_pTabTitle, Qt::TopRightCorner);connect(m_pTabTitle, TapTitle::sig_close, this, TabBrowser::sig_close);connect(m_pTabTitle, TapTitle::sig_addtab, this, TabBrowser::on_newTab); }this-setContextMenuPolicy(Qt::CustomContextMenu); 设置选项卡控件的上下文菜单策略为 Qt::CustomContextMenu允许自定义右键菜单的行为。此策略指示控件在接收到右键单击事件时不显示默认的上下文菜单而是发射 customContextMenuRequested 信号以便开发者自行实现自定义菜单。 m_pTabTitle new TapTitle(this); 创建一个 TapTitle 对象作为自定义标题栏并将 TabBrowserthis设为其父对象。自定义标题栏将用于取代默认的选项卡栏实现更丰富的交互功能。 creatTabMenu(); 调用 creatTabMenu 方法用于创建选项卡的上下文菜单。此方法通常用于定义右键菜单的各项内容和行为为选项卡的交互提供更多的操作选项。 connect(this, QTabWidget::customContextMenuRequested, this, TabBrowser::onMenuShow); 使用 Qt 的信号-槽机制将 QTabWidget 的 customContextMenuRequested 信号与 TabBrowser 的槽函数 onMenuShow 关联。customContextMenuRequested 信号在用户右键单击选项卡时触发调用 onMenuShow 槽函数以显示自定义的上下文菜单。这种机制实现了选项卡的自定义右键菜单功能。 this-setCornerWidget(m_pTabTitle, Qt::TopRightCorner); 使用 setCornerWidget 方法将自定义的 TapTitle 设置为 QTabWidget 的右上角小部件Qt::TopRightCorner。这为选项卡控件提供了一个可自定义的标题栏区域可以在该区域添加按钮、文本或其他控件以增强选项卡的功能和外观。 connect(m_pTabTitle, TapTitle::sig_close, this, TabBrowser::sig_close); 将自定义标题栏m_pTabTitle的 sig_close 信号与 TabBrowser 的 sig_close 信号进行连接。这一操作允许标题栏触发关闭操作并将此操作传递给 TabBrowser从而实现自定义标题栏与选项卡控件之间的交互。 connect(m_pTabTitle, TapTitle::sig_addtab, this, TabBrowser::on_newTab); 将 TapTitle 的 sig_addtab 信号与 TabBrowser 的 on_newTab 槽函数关联。当自定义标题栏中添加标签页的信号触发时on_newTab 槽函数被调用实现了通过标题栏添加新选项卡的功能。 setTabBarFlag() void TabBrowser::setTabBarFlag(TAB_FLAG flag) {int w this-width();int tableWidth 0;int tabs this-count();if (flag NULL || flag NORMAL) {for (int i 0; i tabs; i) {tableWidth tabBar()-tabRect(i).width();}} else {for (int i 0; i tabs - 1; i) {tableWidth tabBar()-tabRect(i).width();}}if (w tableWidth) {m_pTabTitle-setEmptyWidgetWidth(w - tableWidth - 32 * 5 - 15);this-setStyleSheet(qss0);} else {m_pTabTitle-setEmptyWidgetWidth(100);this-setStyleSheet(qss1);} }int w this-width(); 获取当前 TabBrowser 窗口的宽度用于后续计算选项卡和标题栏的宽度布局。 int tableWidth 0; 初始化 tableWidth用于累加所有选项卡的宽度以便在后续步骤中比较窗口宽度和选项卡总宽度。 int tabs this-count(); 获取选项卡的数量count() 返回当前 QTabWidget 中的选项卡数目用于遍历选项卡并计算它们的总宽度。 if (flag NULL || flag NORMAL) { ... } else { ... } 根据 flag 参数决定如何计算选项卡的总宽度。flag 是一个枚举类型 TAB_FLAG用于指示当前标题栏的状态。此处判断是否为 NULL 或 NORMAL以确定选项卡的宽度计算方式。 for (int i 0; i tabs; i) { ... } 当 flag 为 NULL 或 NORMAL 时遍历所有选项卡调用 tabBar()-tabRect(i).width() 获取每个选项卡的宽度并累加到 tableWidth 中。 for (int i 0; i tabs - 1; i) { ... } 如果 flag 不为 NULL 或 NORMAL则遍历所有选项卡但忽略最后一个。这样可以调整选项卡布局以满足某些特殊情况下的需求。 if (w tableWidth) { ... } else { ... } 比较窗口宽度 w 与选项卡总宽度 tableWidth根据结果调整标题栏中空白区域的宽度并设置相应的样式表。 m_pTabTitle-setEmptyWidgetWidth(w - tableWidth - 32 * 5 - 15); 如果窗口宽度大于选项卡总宽度计算空白区域的宽度并调用 m_pTabTitle-setEmptyWidgetWidth() 方法进行设置。这里的计算包括减去一些固定值32 * 5 15用于留出其他控件如按钮的空间。 this-setStyleSheet(qss0); 应用 qss0 样式表以调整选项卡的外观。这通常用于调整选项卡栏的样式如颜色、边距等。 m_pTabTitle-setEmptyWidgetWidth(100); 如果窗口宽度不够则将空白区域的宽度设置为固定值 100以防止选项卡栏中出现布局问题。 this-setStyleSheet(qss1); 应用 qss1 样式表以调整选项卡的外观。与前面的 qss0 不同这个样式表定义了滑动条的宽度。 resizeEvent(QResizeEvent* e) void TabBrowser::resizeEvent(QResizeEvent* e) {setTabBarFlag(NORMAL);QTabWidget::resizeEvent(e);}void TabBrowser::resizeEvent(QResizeEvent* e): 这是 TabBrowser 类中重写的 resizeEvent 方法用于响应窗口调整大小的事件。QResizeEvent* e 是调整大小事件对象包含有关窗口尺寸变化的信息。通过重写该方法TabBrowser 可以在每次窗口大小发生变化时执行自定义的处理逻辑。 setTabBarFlag(NORMAL);: 调用 setTabBarFlag 方法并传递参数 NORMAL。在此上下文中NORMAL 是枚举类型 TAB_FLAG 的一个值用于指示选项卡栏的布局状态。此调用用于根据当前窗口的新尺寸重新调整选项卡栏的布局和样式包括计算空白区域的宽度以及设置合适的样式表。当窗口大小发生变化时setTabBarFlag 的调用确保选项卡栏根据新的窗口尺寸进行自适应调整从而保持界面的美观和功能性。 QTabWidget::resizeEvent(e);: 调用基类 QTabWidget 的 resizeEvent 方法执行其默认的调整大小操作。这样确保 QTabWidget 及其子类中与调整大小相关的所有内部处理逻辑都得以正确执行。在重写事件处理函数时调用基类的默认实现是常见的做法确保继承链中其他类的处理逻辑不会被遗漏。 on_closeTab(int index) void TabBrowser::on_closeTab(int index) {widget(index)-deleteLater();setTabBarFlag(CLOSE);//当只剩下1个tab时if (count() 1) {setTabsClosable(false);setTabBarFlag(SPECIAL);} }widget(index)-deleteLater();: 获取指定索引的选项卡中的小部件并调用其 deleteLater() 方法延迟销毁该小部件。deleteLater() 是一种安全的对象销毁方式它将对象的销毁操作延迟到事件循环的下一次迭代避免立即销毁可能导致的潜在问题例如访问已销毁的对象。此操作实现了选项卡及其内容的安全释放。 setTabBarFlag(CLOSE);: 调用 setTabBarFlag 方法将选项卡栏状态设置为 CLOSE。这通常用于调整选项卡栏的布局和样式以反映选项卡关闭后的状态。例如调整空白区域的宽度和重新应用样式表以保持界面的视觉一致性。 if (count() 1) { ... }: 检查选项卡的数量count() 方法返回当前选项卡的总数。该逻辑用于判断当前选项卡关闭后是否只剩下最后一个选项卡。此判断是为了防止用户关闭所有选项卡使界面出现异常状态。 setTabsClosable(false);: 当只剩下一个选项卡时调用 setTabsClosable(false) 禁用选项卡的关闭按钮。这是为了防止用户关闭最后一个选项卡确保界面始终保留至少一个可用选项卡。该方法是 QTabWidget 的成员函数用于设置选项卡是否显示关闭按钮。 setTabBarFlag(SPECIAL);: 调用 setTabBarFlag 方法将选项卡栏状态设置为 SPECIAL以适应只有一个选项卡的特殊情况。此操作可能包括调整选项卡栏的外观、样式以及其他交互行为以反映特殊状态。 on_newTab() void TabBrowser::on_newTab() {int Ncount count();QString title QString::number(Ncount);title Page title;this-insertTab(Ncount,new QWidget,title);if (!tabsClosable()) {setTabsClosable(true);}setTabBarFlag(NEW);}int Ncount count();: 调用 count() 方法获取当前选项卡的总数量并将其存储在 Ncount 中。count() 是 QTabWidget 的成员函数返回当前选项卡的数量。此值用于确定新选项卡的插入位置和命名。 QString title QString::number(Ncount);: 使用 QString::number 将 Ncount 转换为字符串形式以便生成新选项卡的标题。QString 是 Qt 提供的字符串类用于文本处理。将数字转换为字符串便于创建具有动态编号的选项卡标题。 title Page title;: 将字符串 Page 与 title 拼接生成新选项卡的完整标题例如 “Page1”、“Page2” 等。此操作为新添加的选项卡提供了唯一且有意义的标识。 this-insertTab(Ncount, new QWidget, title);: 调用 insertTab 方法在指定位置插入一个新的选项卡。insertTab 是 QTabWidget 的成员函数接受三个参数插入位置Ncount、新选项卡的内容new QWidget和选项卡标题title。此操作在选项卡栏中添加一个新的空白选项卡并将其放置在当前选项卡总数的位置使新选项卡始终添加在末尾。 if (!tabsClosable()) { setTabsClosable(true); }: 调用 tabsClosable() 检查选项卡是否可关闭。如果不可关闭则调用 setTabsClosable(true) 将其设置为可关闭。setTabsClosable 是 QTabWidget 的成员函数用于显示或隐藏选项卡上的关闭按钮。此逻辑确保在新选项卡被添加后用户可以关闭选项卡。 setTabBarFlag(NEW);: 调用自定义方法 setTabBarFlag将选项卡栏状态设置为 NEW。此操作用于调整选项卡栏的布局和样式以适应新的选项卡。通过 setTabBarFlag可以根据选项卡数量和状态的变化来动态调整选项卡栏的外观和行为。 TabBrowser(QWidget* p):QTabWidget§ TabBrowser::TabBrowser(QWidget* p):QTabWidget(p) {initTabWidget();this-addTab(new QWidget, 稻壳);this-setUsesScrollButtons(true);this-setTabsClosable(true);this-setMovable(true);setTabBarFlag(NORMAL);this-setStyleSheet(qss0);connect(this, QTabWidget::tabCloseRequested, this, TabBrowser::on_closeTab); }initTabWidget();: 调用自定义的 initTabWidget 方法初始化选项卡控件的属性、标题栏和上下文菜单等功能。此步骤将 TabBrowser 的界面和交互逻辑进行自定义配置使其满足应用需求。 this-addTab(new QWidget, 稻壳);: 使用 addTab 方法在选项卡栏中添加一个新选项卡包含一个空的 QWidget标题为 稻壳。addTab 是 QTabWidget 的成员函数用于向选项卡控件中添加新的页面。此步骤确保 TabBrowser 在初始化时具有至少一个选项卡。 this-setUsesScrollButtons(true);: 启用选项卡栏的滚动按钮。当选项卡数量超过显示区域时滚动按钮可以用于查看所有选项卡。setUsesScrollButtons 是 QTabWidget 的成员函数该设置增强了选项卡栏的可用性确保在选项卡数量较多时仍能提供良好的导航体验。 this-setTabsClosable(true);: 设置选项卡可关闭在每个选项卡上显示关闭按钮。setTabsClosable 是 QTabWidget 的成员函数允许用户通过点击关闭按钮来移除选项卡。这为选项卡的管理提供了更灵活的操作方式。 this-setMovable(true);: 使选项卡可拖动以调整其在选项卡栏中的顺序。setMovable 是 QTabWidget 的成员函数启用该属性后用户可以通过拖拽选项卡在不同位置之间移动提供了更灵活的界面布局。 setTabBarFlag(NORMAL);: 调用自定义的 setTabBarFlag 方法将选项卡栏的状态设置为 NORMAL。该方法通常用于调整选项卡栏的布局和空白区域并应用适当的样式以符合选项卡栏的初始状态。 this-setStyleSheet(qss0);: 应用样式表 qss0用于自定义选项卡栏的外观。通过调用 setStyleSheet可以调整选项卡栏的视觉样式例如颜色、字体、边距等使其符合应用的界面设计。 connect(this, QTabWidget::tabCloseRequested, this, TabBrowser::on_closeTab);: 使用 Qt 的信号-槽机制将 QTabWidget 的 tabCloseRequested 信号连接到 TabBrowser 的槽函数 on_closeTab。当用户点击选项卡上的关闭按钮时tabCloseRequested 信号会被触发并传递要关闭的选项卡的索引给 on_closeTab从而执行选项卡关闭的逻辑。 creatTabMenu() void TabBrowser::creatTabMenu() {m_pTabMenu new QMenu(this);QAction* pAcSave new QAction(QIcon(:/MainWidget/resources/save.png), u8保存, m_pTabMenu);QAction* pAcSaveAS new QAction(QIcon(),u8另存为,m_pTabMenu);QAction* pAcShareDoc new QAction(QIcon(:/MainWidget/resources/share.png), u8分享文档, m_pTabMenu);QAction* pAcSendToDevice new QAction(QIcon(),u8发送到设备);QAction* pAcNewName new QAction(QIcon(),u8重命名,m_pTabMenu);QAction* pAcSaveToWPSCloud new QAction(QIcon(),u8保存到WPS文档,m_pTabMenu);QAction* pAcCloseAll new QAction(QIcon(),u8关闭所有文件,m_pTabMenu);m_pTabMenu-addAction( pAcSave);m_pTabMenu-addAction(pAcSaveAS);m_pTabMenu-addSeparator();m_pTabMenu-addAction(pAcShareDoc);m_pTabMenu-addAction(pAcSendToDevice);m_pTabMenu-addSeparator();m_pTabMenu-addAction(pAcNewName);m_pTabMenu-addAction(pAcSaveToWPSCloud);m_pTabMenu-addAction(pAcCloseAll);}m_pTabMenu-addSeparator();: 调用 QMenu 的成员函数 addSeparator()在菜单中插入一个分隔符QSeparator。分隔符在菜单中起到分组和视觉分割的作用提高菜单的可读性和用户体验。通过这种方式可以将菜单选项按照功能或类别进行逻辑划分使用户更容易找到所需的操作。 QAction* pAcSave new QAction(QIcon(:/MainWidget/resources/save.png), u8保存, m_pTabMenu);: 创建一个 QAction 对象 pAcSave表示菜单中的一个可交互选项。保存选项通过以下参数进行初始化 QIcon(:/MainWidget/resources/save.png): 从资源文件中加载图标并为菜单项指定一个图标提供视觉提示增强用户界面体验。QIcon 构造函数使用资源路径 :/MainWidget/resources/save.png 来定位并加载图标确保图标在不同的运行环境中正确显示。 u8保存: 指定菜单选项的文本。u8 前缀表示这是一个 UTF-8 编码的字符串确保中文字符在不同的系统和语言环境中正确显示。 m_pTabMenu: 设置菜单项的父对象指定 QAction 归属的菜单 (m_pTabMenu) 管理其生命周期。这样在 m_pTabMenu 被销毁时pAcSave 也会被自动销毁确保资源的正确管理。 onMenuShow(const QPoint pos) void TabBrowser::onMenuShow(const QPoint pos) {int index this-tabBar()-tabAt(pos);if (index ! -1) {m_pTabMenu-exec(QCursor::pos());} } void TabBrowser::onMenuShow(const QPoint pos): 该函数是一个槽函数用于响应上下文菜单请求例如右键单击事件。pos 参数表示鼠标事件相对于 QTabWidget 的局部坐标通过该坐标可以确定鼠标指针位于哪个选项卡上。 int index this-tabBar()-tabAt(pos);: 调用 tabBar()-tabAt(pos) 获取鼠标点击位置所在的选项卡索引。tabAt 是 QTabBar 类的成员函数接受局部坐标 pos 作为参数返回位于该坐标上的选项卡的索引。如果 pos 不在任何选项卡上则返回 -1。这一步用于判断鼠标点击是否发生在某个选项卡上从而决定是否显示上下文菜单。 if (index ! -1): 判断鼠标点击是否位于某个有效的选项卡上。如果 index 不等于 -1则表示鼠标点击的位置属于一个选项卡此时可以继续执行显示菜单的操作。 m_pTabMenu-exec(QCursor::pos());: 调用 QMenu 的成员函数 exec() 在指定位置显示上下文菜单。QCursor::pos() 获取当前鼠标的全局屏幕坐标确保菜单在鼠标指针的位置弹出。exec() 是一个阻塞式的菜单显示方法菜单在执行期间会阻止其他事件处理直到用户在菜单中选择一项或点击其他区域以关闭菜单。这一步实现了自定义右键菜单的显示使用户能够对选项卡执行特定操作例如保存、关闭等。 样式表 QString commonQss R(QTabBar::tab {font: 75 12pt Arial;text-align: left;width: 184px;height: 32px; /* 添加像素单位 */background: #FFFFFF;border: 2px solid #FFFFFF;border-bottom-color: #FFFFFF;border-top-left-radius: 4px;border-top-right-radius: 4px;padding: 2px;margin-top: 0px;margin-right: 1px;margin-left: 1px;margin-bottom: 0px;}QTabBar::tab:selected {color: #333333; /* 文字颜色 */background-color: #FFFFFF;}QTabBar::tab:!selected {color: #B2B2B2;border-color: #FFFFFF;} );QString qss0 commonQss R(QTabBar::scroller {width: 0px;} );QString qss1 commonQss R(QTabBar::scroller {width: 36px;} ); qss0 样式表: 通过设置 QTabBar::scroller { width: 0px; }将滑动条滚动按钮的宽度设为 0 像素。这样即使启用了 QTabBar 的滚动功能滑动条也不会在界面上显示。该设置实际上隐藏了滚动条适用于选项卡数量较少可以完全在选项卡栏中显示的场景避免界面出现多余的滚动控件。 qss1 样式表: 通过设置 QTabBar::scroller { width: 36px; }将滑动条的宽度设为 36 像素。这样在选项卡数量较多超出可视区域时滑动条可以显示出来允许用户通过滚动按钮查看所有选项卡。这种设置确保了选项卡栏在内容过多的情况下仍然具有良好的可用性和导航性。 结尾 最后感谢您阅读我的文章希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点请随时在评论区留言。 同时不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中我将继续探讨这个话题的不同方面为您呈现更多深度和见解。 谢谢您的支持期待与您在下一篇文章中再次相遇
http://www.hkea.cn/news/14554154/

相关文章:

  • 网站建设及目标网站维护和更新
  • 沧州市东光建设局 网站广告公司 名称
  • 建站公司佛山网站开发专业就业前景分析
  • 秦皇岛网站开发报价湖南省建六公司官网
  • 常州做网站包括哪些上海网站搭建公司哪家好
  • php 网站开发架构住建网官网
  • 沧州做网站费用上海搜索引擎优化
  • 哈尔滨网站建设那家好360建筑网现在叫什么
  • 个人网站开发与设计摘要自己想建设一个网站
  • 网站地图的作用seo海外
  • 中国工程建设交易信息网站wap页面模板
  • 怎么做网站原型上海新媒体运营公司排名
  • 大连的网站制作公司太原百度关键词优化
  • 织梦网站源码医疗器械研发
  • 做网站 接单职业生涯规划大赛怎么准备
  • 温州开发网站公司wordpress分类链接打不开
  • 网站做5级分销合法吗wordpress零基础建站教程
  • seo 网站换程序wordpress做个人博客
  • 黑龙江华龙建设集团网站网站的关键词搜索怎么做
  • 设计产品网站推荐外贸行业建站
  • 用html是做班级简介网站个人简历网页制作教程
  • 南阳河南网站建设价格推广方式英语
  • 东莞桂城网站建设wordpress站点标题和副标题
  • 百度网站查反链餐饮公司网站模板下载
  • 创新的广州做网站网站开发注意事项
  • 网站虚拟主持创意产品设计图
  • 网站开发为什么采取ssh框架青岛网景互联网站建设公司
  • 188网站开发免费论坛创建
  • asp.net免费网站郑州建设企业网站找哪个公司
  • 产品类网站模板广州网站制作商