Qt實現TabWidget通過addTab函數添加的頁,頁內控件自適應窗口大小

前言:因為項目的要求,需要把幾個不同類型功能的界面集成在同一個窗口中,方便用戶不切換窗口,也能快捷的操作不同類型的功能。我首先想到的是通過選項卡方式,讓幾個類別的功能界面通過不同選項卡進行切換,這在windows系統中也是很常見的一種方式。為了將不同類功能進行模塊化,方便維護,通過自定義QWidget的子類,然后在主界面通過tabWidget.addTab()方法,將不同類功能添加到主界面。由于不同tab頁內控件大小不一,為了讓界面盡可能的美觀,希望新增的tab頁也能跟隨窗口的大小隨時改變尺寸。但是我使用通過遍歷tab頁內的控件,并在窗口改變事件(resizeEvent)中添加控件縮放操作,發現控件并沒有達到我想要的縮放效果。經過不斷嘗試,發現問題出現在:新增的tab頁中的布局控件無法輕易地獲取真實大小,而且也無法觸發tab頁resizeEvent事件。知道了問題所在,經過不懈努力,終于找到了解決方法,于是有了本文。

一、主界面類

? ? ? ? 主界面中包含一個TabWidget控件,并包含一個tab頁。TabWidget通過addTab()方法將其他類型的功能模塊加進來,既實現模塊化,又能將多個功能集成到一個窗口。

以下為主界面內的主要代碼

mainwindow.h

#include <QPlainTextEdit>
#include <QTextBrowser>
#include <QResizeEvent>
#include "tab2widght.h"
class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();
private:/** 初始化添加的TabWidget的尺寸 */void initialAddedTabWidgetSize(int tabIndex);// 需要添加的Tab2Widget模塊Tab2Widget *tab2Widget = NULL;// 上次點擊的tab頁序號int preTabWidgetIndex = 0;// 控件根據窗口大小自動調整控件大小 @{
protected:void resizeEvent(QResizeEvent* event) override;
private:QMap<QWidget*, QRect> allWidgetMap;QMap<QLayout*, QRect> allLayoutMap;/** 窗口默認尺寸 */QSize windowOriginalSize;/** 查找所有子布局和子控件 */void findAllLayoutAndWidget(QObject *object);/** 檢查文本是否超出了容器寬或高,方便修改文本大小 */bool checkTextOverflow(QWidget *widget);
// 控件根據窗口大小自動調整控件大小 @}
private slots:/** 當tabwidget切換tab時 **/void onTabClicked(int index);
};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{// 實例化tab2模塊類if(tab2Widget == NULL) {tab2Widget = new Tab2Widget();}// tab2模塊添加到主界面的tabwidget中if (tab2Widget != NULL) {ui->tabWidget->addTab(tab2Widget, "Tab2");}// 注冊tabwidget的頁點擊事件connect(ui->tabWidget, &QTabWidget::tabBarClicked, this, &MainWindow::onTabClicked);// 延時為了獲取的控件初始大小是正確的QTimer::singleShot(200, this, [=] {findAllLayoutAndWidget(this);windowOriginalSize = this->size();});// 控件根據窗口大小自動調整控件大小 @}
}MainWindow::~MainWindow()
{if (tab2Widget != NULL) {tab2Widget->deleteLater();}
}/** 當tabview切換tab時 **/
void MainWindow::onTabClicked(int index) {// 根據tab的索引判斷是否需要授權if (index == ui->tabWidget->indexOf(tab2Widget)) {// 首次設置新添加的tab的尺寸,只有切換到對應tab,才能拿到真實的layout尺寸數據,關鍵代碼。initialAddedTabWidgetSize(index);}// 切換tabui->tabWidget->setCurrentIndex(index);preTabWidgetIndex = index;
}void MainWindow::initialAddedTabWidgetSize(int tabIndex)
{// 刷新切換后的tab的布局大小if (tabIndex < ui->tabWidget->count() && preTabWidgetIndex != tabIndex && ui->tabWidget->count() > 1) {// 調整通用參數選項卡頁的尺寸if (tabIndex == ui->tabWidget->indexOf(tab2Widget) && tab2Widget != NULL) {if (tab2Widget->allWidgetMap.size() == 0 && tab2Widget->allLayoutMap.size() == 0) {tab2Widget->findAllLayoutAndWidget(tab2Widget);}// 設置通過addTab()函數新增的選項卡頁內容的大小tab2Widget->setMinimumSize(ui->tabWidget->widget(0)->geometry().width(),ui->tabWidget->widget(0)->geometry().height());// tabwidget需要單獨調用內部控件的大小if (tab2Widget != NULL) {tab2Widget->resizeAllComponents(ui->tabWidget->widget(0)->geometry());}}}
}// 控件根據窗口大小自動調整控件大小 @{
void MainWindow::resizeEvent(QResizeEvent* event)
{if (event == NULL) {return;}double scaleX = (double)event->size().width() / windowOriginalSize.width();double scaleY = (double)event->size().height() / windowOriginalSize.height();for (auto iter = allLayoutMap.begin(); iter != allLayoutMap.end(); ++iter) {QLayout* layout = iter.key();QRect originalGeometry = iter.value();QRect newGeometry(originalGeometry.x() * scaleX,originalGeometry.y() * scaleY,originalGeometry.width() * scaleX,originalGeometry.height() * scaleY);if (layout) {layout->setGeometry(newGeometry);}}for (auto iter = allWidgetMap.begin(); iter != allWidgetMap.end(); ++iter) {QWidget* widget = iter.key();if (widget) {QRect originalGeometry = iter.value();QRect newGeometry(originalGeometry.x() * scaleX,originalGeometry.y() * scaleY,originalGeometry.width() * scaleX,originalGeometry.height() * scaleY);widget->setGeometry(newGeometry);// 防止在多屏(選擇擴展方式),移動到擴展屏時,tab頁文字疊在一起的問題QTabWidget* tab = dynamic_cast<QTabWidget*>(widget);if (tab != NULL) {tab->setElideMode(Qt::ElideNone);}}// 調整帶文本的控件的文本大小QPushButton* btn = dynamic_cast<QPushButton*>(widget);QLabel* label = dynamic_cast<QLabel*>(widget);QCheckBox* checkbox = dynamic_cast<QCheckBox*>(widget);QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget);QTextEdit* textEdit = dynamic_cast<QTextEdit*>(widget);QPlainTextEdit* plainTextEdit = dynamic_cast<QPlainTextEdit*>(widget);QTextBrowser* textBrowser = dynamic_cast<QTextBrowser*>(widget);// 條件為了防止在隨意調節界面大小時,界面上出現黑塊問題if (textBrowser == NULL && (btn != NULL || label != NULL || checkbox != NULL|| lineEdit != NULL || textEdit != NULL || plainTextEdit != NULL)) {int initialFontSize = widget->height() / 3;if (btn != NULL) {initialFontSize = widget->height() / 4;} else if (checkbox != NULL) {initialFontSize = widget->height() / 2;}// 使用Do...While語句是為了始終會設置字體大小一次,防止界面縮小后又放大后,字體還一直保持很小的問題do {QFont font = widget->font();int size = initialFontSize;bool needBreak = false;// 最小9if (size < 9) {size = 9;needBreak = true;}// 根據按鈕的寬度/高度調整字體大小,可以根據默認控件的高度和字體的大小比率進行適當調整font.setPointSize(size);widget->setFont(font);initialFontSize--;if (needBreak) {break;}} while(checkTextOverflow(widget));}}if (windowOriginalSize.width() != -1) {// 設置通過addTab()函數新增的選項卡頁內容的大小if (ui->tabWidget->count() > 1) {// 布局或控件拿到之后才能調整if (tab2Widget->allWidgetMap.size() > 0|| tab2Widget->allLayoutMap.size() > 0) {// tab2tab2Widget->setMinimumSize(ui->tabWidget->widget(0)->geometry().width(),ui->tabWidget->widget(0)->geometry().height());// tabwidget需要單獨調用內部控件的大小if (tab2Widget != NULL) {tab2Widget->resizeAllComponents(ui->tabWidget->widget(0)->geometry());}}}}
}void MainWindow::findAllLayoutAndWidget(QObject *object) {QLayout *layout = qobject_cast<QLayout*>(object);QWidget *widget = qobject_cast<QWidget*>(object);if (layout) {if (layout->objectName() != "" && !allLayoutMap.contains(layout)) {allLayoutMap.insert(layout, layout->geometry());}for (int i = 0; i < layout->count(); ++i) {findAllLayoutAndWidget(layout->itemAt(i)->widget());}// 嵌套的選項卡,自適應尺寸放到對應類中,不在此類中調整} else if (widget && widget != tab2Widget) {if (widget != this && widget->objectName() != "" && !allWidgetMap.contains(widget)) {allWidgetMap.insert(widget, widget->geometry());}for (int i = 0; i < widget->children().size(); ++i) {findAllLayoutAndWidget(widget->children().at(i));}}
}bool MainWindow::checkTextOverflow(QWidget *widget) {if (widget == NULL) {return false;}QPushButton* btn = dynamic_cast<QPushButton*>(widget);QLabel* label = dynamic_cast<QLabel*>(widget);QCheckBox* checkbox = dynamic_cast<QCheckBox*>(widget);QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget);QTextEdit* textEdit = dynamic_cast<QTextEdit*>(widget);QPlainTextEdit* plainTextEdit = dynamic_cast<QPlainTextEdit*>(widget);// TODO 可增加其他可調節文本的控件,以下的text文本也要相應賦值控件文本// 獲取按鈕的字體和文本QString text = "";if (btn != NULL) {text = btn->text();} else if (label != NULL) {text = label->text();} else if (checkbox != NULL) {text = checkbox->text();} else if (lineEdit != NULL) {text = lineEdit->text();} else if (textEdit != NULL) {text = textEdit->toPlainText();} else if (plainTextEdit != NULL) {text = plainTextEdit->toPlainText();}if (text.isEmpty()) {return false;}QFont font = widget->font();QFontMetrics fm(font);// 計算文本的寬度和高度int textWidth = fm.horizontalAdvance(text);int textHeight = fm.height();// 獲取按鈕的尺寸(不包括邊框)QSize buttonSize = widget->size();// 寬度多減去一些,為了防止有些時候按鈕字體和左右邊框切邊buttonSize.rwidth() -= 8 * widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); // 減去邊框寬度buttonSize.rheight() -= 2 * widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); // 減去邊框高度// 檢查是否溢出if (textWidth > buttonSize.width() || textHeight > buttonSize.height()) {return true;} else {return false;}
}// 控件根據窗口大小自動調整控件大小 @}

二、通過addTab()方法加入到主界面的類

相當于另一個模塊,只是界面嵌套到了主界面,既方便用戶操作,又能夠模塊化,方便維護。

tab2widget.h

class Tab2Widget : public QWidget
{Q_OBJECTpublic:explicit Tab2Widget(QWidget *parent = nullptr);~Tab2Widget();// 控件根據窗口大小自動調整控件大小 @{
public:void resizeAllComponents(QRect parentRect);QMap<QWidget*, QRect> allWidgetMap;QMap<QLayout*, QRect> allLayoutMap;/** 查找所有子布局和子控件 **/void findAllLayoutAndWidget(QObject *object);
private:/** 窗口默認尺寸 **/QSize windowOriginalSize = QSize(0,0);/** 檢查文本是否超出了容器寬或高,方便修改文本大小 **/bool checkTextOverflow(QWidget *widget);// 控件根據窗口大小自動調整控件大小 @}
};

tab2widget.cpp

#include "tab2widget.h"
#include "ui_tab2widget.h"Tab2Widget::Tab2Widget(QWidget *parent): QWidget(parent), ui(new Ui::Tab2Widget)
{// 控件根據窗口大小自動調整控件大小 @{// 延時為了獲取的控件初始大小是正確的QTimer::singleShot(200, this, [=] {windowOriginalSize = this->size();});// 控件根據窗口大小自動調整控件大小 @}
}Tab2Widget::~Tab2Widget() 
{
}// 控件根據窗口大小自動調整控件大小 @{
void Tab2Widget::resizeAllComponents(QRect parentRect)
{if (parentRect.width() == 0 || parentRect.height() == 0|| windowOriginalSize.width() == 0 || windowOriginalSize.height() == 0) {return;}double scaleX = (double)parentRect.width() / windowOriginalSize.width();double scaleY = (double)parentRect.height() / windowOriginalSize.height();for (auto iter = allLayoutMap.begin(); iter != allLayoutMap.end(); ++iter) {QLayout* layout = iter.key();QRect originalGeometry = iter.value();QRect newGeometry(originalGeometry.x() * scaleX,originalGeometry.y() * scaleY,originalGeometry.width() * scaleX,originalGeometry.height() * scaleY);if (layout) {layout->setGeometry(newGeometry);}}for (auto iter = allWidgetMap.begin(); iter != allWidgetMap.end(); ++iter) {QWidget* widget = iter.key();if (widget) {QRect originalGeometry = iter.value();QRect newGeometry(originalGeometry.x() * scaleX,originalGeometry.y() * scaleY,originalGeometry.width() * scaleX,originalGeometry.height() * scaleY);widget->setGeometry(newGeometry);}// 調整帶文本的控件的文本大小QPushButton* btn = dynamic_cast<QPushButton*>(widget);QLabel* label = dynamic_cast<QLabel*>(widget);QCheckBox* checkbox = dynamic_cast<QCheckBox*>(widget);QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget);QTextEdit* textEdit = dynamic_cast<QTextEdit*>(widget);QPlainTextEdit* plainTextEdit = dynamic_cast<QPlainTextEdit*>(widget);QTextBrowser* textBrowser = dynamic_cast<QTextBrowser*>(widget);// 條件為了防止在隨意調節界面大小時,界面上出現黑塊問題if (textBrowser == NULL && (btn != NULL || label != NULL || checkbox != NULL|| lineEdit != NULL || textEdit != NULL || plainTextEdit != NULL)) {int initialFontSize = widget->height() / 3;if (btn != NULL) {initialFontSize = widget->height() / 4;} else if (checkbox != NULL) {initialFontSize = widget->height() / 2;}// 使用Do...While語句是為了始終會設置字體大小一次,防止界面縮小后又放大后,字體還一直保持很小的問題do {QFont font = widget->font();int size = initialFontSize;bool needBreak = false;// 最小9if (size < 9) {size = 9;needBreak = true;}// 根據按鈕的寬度/高度調整字體大小,可以根據默認控件的高度和字體的大小比率進行適當調整font.setPointSize(size);widget->setFont(font);initialFontSize--;if (needBreak) {break;}} while(checkTextOverflow(widget));}}
}void Tab2Widget::findAllLayoutAndWidget(QObject *object) {QLayout *layout = qobject_cast<QLayout*>(object);QWidget *widget = qobject_cast<QWidget*>(object);if (layout) {if (layout->objectName() != "" && !allLayoutMap.contains(layout)) {allLayoutMap.insert(layout, layout->geometry());}for (int i = 0; i < layout->count(); ++i) {findAllLayoutAndWidget(layout->itemAt(i)->widget());}} else if (widget) {if (widget != this && widget->objectName() != "" && !allWidgetMap.contains(widget)) {allWidgetMap.insert(widget, widget->geometry());}for (int i = 0; i < widget->children().size(); ++i) {findAllLayoutAndWidget(widget->children().at(i));}}
}bool Tab2Widget::checkTextOverflow(QWidget *widget) {if (widget == NULL) {return false;}QPushButton* btn = dynamic_cast<QPushButton*>(widget);QLabel* label = dynamic_cast<QLabel*>(widget);QCheckBox* checkbox = dynamic_cast<QCheckBox*>(widget);QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(widget);QTextEdit* textEdit = dynamic_cast<QTextEdit*>(widget);QPlainTextEdit* plainTextEdit = dynamic_cast<QPlainTextEdit*>(widget);// TODO 可增加其他可調節文本的控件,以下的text文本也要相應賦值控件文本// 獲取按鈕的字體和文本QString text = "";if (btn != NULL) {text = btn->text();} else if (label != NULL) {text = label->text();} else if (checkbox != NULL) {text = checkbox->text();} else if (lineEdit != NULL) {text = lineEdit->text();} else if (textEdit != NULL) {text = textEdit->toPlainText();} else if (plainTextEdit != NULL) {text = plainTextEdit->toPlainText();}if (text.isEmpty()) {return false;}QFont font = widget->font();QFontMetrics fm(font);// 計算文本的寬度和高度int textWidth = fm.horizontalAdvance(text);int textHeight = fm.height();// 獲取按鈕的尺寸(不包括邊框)QSize buttonSize = widget->size();// 寬度多減去一些,為了防止有些時候按鈕字體和左右邊框切邊buttonSize.rwidth() -= 8 * widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); // 減去邊框寬度buttonSize.rheight() -= 2 * widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); // 減去邊框高度// 檢查是否溢出if (textWidth > buttonSize.width() || textHeight > buttonSize.height()) {return true;} else {return false;}
}// 控件根據窗口大小自動調整控件大小 @}

注意:要實現界面自適應尺寸,控件的sizePolicy最好設置成Preferred或者Expanding,少用Fixed,否則會出現在縮小窗口尺寸的時候,由于控件最小尺寸設定死了,容易出現文字切邊的問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93882.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93882.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93882.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

代碼隨想錄算法訓練營27天 | ??56. 合并區間、738.單調遞增的數字、968.監控二叉樹(提高)

題目鏈接&#xff1a;56. 合并區間、738.單調遞增的數字、968.監控二叉樹 文章鏈接&#xff1a;代碼隨想錄 貪心算法 1. 合并區間 &#xff08;待更新...&#xff09; class Solution { private:static bool cmp(const vector<int>& a, const vector<int>&…

從 H.264/H.265 到 H.266:RTSP播放器的跨代際演進

引言&#xff1a;H.266與實時視頻的交匯點 視頻編解碼的發展歷程&#xff0c;始終是 帶寬效率與視覺體驗的博弈。從 H.264 的普及&#xff0c;到 H.265/HEVC 的深化應用&#xff0c;每一次標準迭代&#xff0c;都在推動視頻向更高分辨率、更高幀率、更復雜場景的應用邁進。而 …

oc-mirror plugin v2 錯誤could not establish the destination for the release i

openshift 4.19使用的鏡像倉庫為harbor. 運行disk to registry時出現下面的錯誤&#xff1a; 2025/08/19 17:51:13 [ERROR] : [Executor] [release collector] could not establish the destination for the release image 備注&#xff1a; 我沒有賬戶&#xff0c;無法打開…

Android auncher3實現簡單的負一屏功能

Android launcher3實現簡單的負一屏功能 1.前言&#xff1a; 之前實現過Launcher3從湊提修改成單層&#xff0c;今天來講解一下如何實現一個簡單的負一屏功能&#xff0c;涉及的類如下&#xff0c;直接看代碼。 2.NegativeScreenAdapter&#xff1a; package com.example.ne…

跨網閘數據庫同步:在物理隔離中架起安全的數據橋梁

作者:DeepSeek-R1 | 日期:2025年8月17日 引言 在等保2.0和分級保護政策的要求下,高密級網絡(如政務內網、金融核心網)必須與低密級網絡(如互聯網)物理隔離。但業務又要求數據跨網流動(如市民在線提交申請、分支機構數據回傳)。如何解決這一矛盾?雙向網閘與單向光閘成…

【Android】一文詳解Android里的AOP編程

一文詳解Android里的AOP編程 1. 基于 AspectJ&#xff08;編譯期/打包期織入&#xff09; 思路&#xff1a;用 AspectJ 編譯器在 編譯階段 或 Gradle Transform 階段&#xff0c;把切面邏輯織入 class / bytecode。 特點&#xff1a; 能實現類似 Spring AOP 的注解切面&#…

AI+預測3D新模型百十個定位預測+膽碼預測+去和尾2025年8月21日第167彈

從今天開始&#xff0c;咱們還是暫時基于舊的模型進行預測&#xff0c;好了&#xff0c;廢話不多說&#xff0c;按照老辦法&#xff0c;重點8-9碼定位&#xff0c;配合三膽下1或下2&#xff0c;殺1-2個和尾&#xff0c;再殺4-5個和值&#xff0c;可以做到100-300注左右。(1)定位…

機器學習【十】neural network

系統梳理了機器學習與神經網絡的基礎知識&#xff0c;涵蓋理論、核心概念及代碼實踐。理論部分包括線性模型&#xff08;向量表示、廣義線性模型&#xff09;、分類與回歸的區別、梯度下降&#xff08;批量/隨機/小批量&#xff09;、激活函數&#xff08;Sigmoid、ReLU等&…

如何用算力魔方4060安裝PaddleOCR MCP 服務器

在當今數字化快速發展的時代&#xff0c;OCR&#xff08;光學字符識別&#xff09;技術已經成為從圖像中提取文本信息的重要工具。無論是在自動化辦公、智能文檔處理還是在內容創作領域&#xff0c;OCR 技術的應用都極大地提高了工作效率和準確性。本文將詳細介紹如何利用算力魔…

Azure的遷移專業服務是怎么提供的

好的&#xff0c;這是一個非常實際的問題。Azure的遷移專業服務&#xff08;Professional Services for Migration&#xff09;并非一個單一的“產品”&#xff0c;而是一個由微軟及其龐大的合作伙伴生態系統共同提供的、基于成熟方法論的綜合服務框架。其提供方式可以概括為&a…

Seaborn數據可視化實戰:Seaborn入門-環境搭建與基礎操作

Seaborn環境搭建與配置 學習目標 本課程將指導學員如何在不同的操作系統&#xff08;Windows, macOS, Linux&#xff09;上安裝Seaborn庫&#xff0c;以及如何配置Python環境&#xff0c;包括使用Jupyter Notebook和Spyder等集成開發環境&#xff08;IDE&#xff09;的基本操作…

Windows下RabbitMQ完整安裝指南

一、RabbitMQ 簡介 RabbitMQ 是一款基于 Erlang 語言開發的開源消息隊列中間件&#xff0c;實現了高級消息隊列協議&#xff08;AMQP&#xff09;。其最初起源于金融系統&#xff0c;專為分布式系統中的消息存儲與轉發設計&#xff0c;在可靠性、擴展性和高可用性方面表現卓越…

thingsboard 通過Entities hierarchy部件實現左邊菜單點擊,右邊的表格按左邊的分類型進行過濾篩選數據源

在 ThingsBoard 中&#xff0c;要讓“Entities hierarchy”部件&#xff08;左側樹形導航&#xff09;與右側的數據表格實現聯動——即點擊左側某個節點后&#xff0c;右側表格立刻按該節點對應的實體類型/層級進行過濾——需要把“數據源別名&#xff08;Alias&#xff09; 儀…

【Ansible】核心概念解析:架構、清單管理與配置入門

本專欄文章持續更新&#xff0c;新增內容使用藍色表示。對于系統管理員而言&#xff0c;手動管理每一臺服務器不僅維護難度極大&#xff0c;而且即使經驗豐富&#xff0c;也難免出現疏忽和錯誤。自動化技術能有效避免因手動管理系統和基礎架構而產生的各類問題。其優點包括&…

rs-fMRI_兩篇文章中分析方法的梳理(近乎翻譯)

文章一文章信息APOE ε4 influences within and between network functional connectivity in posterior cortical atrophy and logopenic progressive aphasia2024美國梅奧診所發表在Alzheimers Dement. 的文章。“APOE ε4等位基因對后皮質萎縮與進行性語言障礙型失語癥的網絡…

在互聯網大廠的Java面試:謝飛機的搞笑歷險記

在互聯網大廠的Java面試&#xff1a;謝飛機的搞笑歷險記 在一個陽光明媚的早上&#xff0c;我們的主角&#xff0c;程序員謝飛機&#xff0c;走進了一家著名的互聯網大廠&#xff0c;準備迎接他人生中最嚴峻的挑戰——Java面試。 第一輪&#xff1a;基礎技術面試 面試官&#x…

微軟AD國產化替換倒計時——不是選擇題,而是生存題

一直以來&#xff0c;微軟Active Directory&#xff08;AD&#xff09;作為企業身份管理和訪問控制的核心組件&#xff0c;承擔著用戶認證、權限分配、資源目錄管理等基礎職能。然而&#xff0c;隨著政策、合規與網絡安全壓力不斷加劇&#xff0c;AD面臨著前所未有的挑戰&#…

MyBatis-Plus MetaObjectHandler的幾個坑(主要是id字段)

1.背景 主要是要實現一個id字段的自增長&#xff0c;不依賴數據庫的能力&#xff08;已避免后續換庫的問題&#xff09;。姑且使用redis作為表的id分配器&#xff0c;因此使用MyBatis-Plus MetaObjectHandler對每個insert的id進行分配。 2.實施過程 以下是實現過程 1.實現MetaO…

Springboot 項目配置多數據源

Springboot 項目配置多數據源 基礎環境 java8、springboot2.2.13、mybatis、mysql5.x、oracle 項目配置 1.application.yml spring:datasource:mysql1:username: abcpassword: 123456url: jdbc:mysql://127.0.0.1:3306/panda?useUnicodetrue&characterEncodingUTF-8&z…

STM32_0001 KEILMDK V5.36 編譯一個STM32F103C8T6說core_cm3.h文件找不到以及編譯器版本不匹配的解決辦法

KEILMDK V5.36 編譯一個STM32F103C8T6說core_cm3.h文件找不到的解決辦法利用KEILMDK V5.36 編譯一個STM32F103C8T6說core_cm3.h文件找不到。主要錯誤信息如下D:/stm32studio/Armmdk/Packs/Keil/STM32F1xx_DFP/2.4.1/Device/Include\stm32f10x.h(486): error: core_cm3.h file n…