#include "FITKMdiArea.h" #include "FITKMdiSubWindow.h" #include #include #include #include namespace Comp { //互斥锁初始化 QMutex FITKMdiArea::_mutex; FITKMdiArea::FITKMdiArea(QWidget * parent) : QMdiArea(parent) { //设置在tab模式下bar中包含关闭按钮 this->setTabsClosable(true); //设置tab页bar为矩形 this->setTabShape(QTabWidget::TabShape::Rounded); } FITKMdiArea::~FITKMdiArea() { _widgetHash.clear(); } int FITKMdiArea::addSubWidget(QWidget* widgwt, QString title) { //互斥锁添加 QMutexLocker locker(&_mutex); FITKMdiSubWindow* subWin = new FITKMdiSubWindow; subWin->setWidget(widgwt); subWin->setParent(this); this->addSubWindow(subWin); _objectID++; //初始化界面的布局方式 setLayoutType(_layoutType); _widgetHash.insert(_objectID, subWin); //QMdiArea中添加widget后需要调用一下show,不然可能无法显示 subWin->setWindowTitle(title); subWin->show(); //返回ID return _objectID; } void FITKMdiArea::setLayoutType(FITKVportsLayoutType type) { _layoutType = type; switch (_layoutType){ //当前视口最大化 case Comp::FITKVportsLayoutType::CurrentMax:this->setViewMode(QMdiArea::ViewMode::SubWindowView); break; //层叠 case Comp::FITKVportsLayoutType::Cascade:this->setViewMode(QMdiArea::ViewMode::SubWindowView); break; //水平平铺 case Comp::FITKVportsLayoutType::TileHorizontally:this->setViewMode(QMdiArea::ViewMode::SubWindowView); break; //垂直平铺 case Comp::FITKVportsLayoutType::TileVertically:this->setViewMode(QMdiArea::ViewMode::SubWindowView); break; //Tab页 case Comp::FITKVportsLayoutType::Tab: this->setViewMode(QMdiArea::ViewMode::TabbedView); break; } //更新布局 updateLayout(); } void FITKMdiArea::setTabPos(FITKVportsTabPos pos) { //设置tab下toolbar的位置 if (_layoutType != Comp::FITKVportsLayoutType::Tab)return; _tabPos = pos; switch (_tabPos) { //顶部 case Comp::FITKVportsTabPos::Top:this->setTabPosition(QTabWidget::TabPosition::North); break; //底部 case Comp::FITKVportsTabPos::Bottom:this->setTabPosition(QTabWidget::TabPosition::South); break; //左侧 case Comp::FITKVportsTabPos::Left:this->setTabPosition(QTabWidget::TabPosition::West); break; //右侧 case Comp::FITKVportsTabPos::Right:this->setTabPosition(QTabWidget::TabPosition::East); break; } } QMdiSubWindow * FITKMdiArea::getSubWidget(int objectID) { return _widgetHash.value(objectID); } QWidget* FITKMdiArea::getWidget(int id) { QMdiSubWindow* subWidget = _widgetHash.value(id); if (subWidget == nullptr)return nullptr; return subWidget->widget(); } void FITKMdiArea::removeWidget(int id) { //互斥锁 QMutexLocker locker(&_mutex); QMdiSubWindow* widget = _widgetHash.value(id); if (widget == nullptr)return; this->removeSubWindow(widget); _widgetHash.remove(id); //更新布局 updateLayout(); } QWidget* FITKMdiArea::getWidget(QMdiSubWindow* subWidget) { if (subWidget == nullptr)return nullptr; QList subWidgets = _widgetHash.values(); if(!subWidgets.contains(subWidget))return nullptr; return subWidget->widget(); } QMdiSubWindow * FITKMdiArea::getSubWidget(QWidget* widget) { if (widget == nullptr)return nullptr; QList subWidgets = _widgetHash.values(); for (QMdiSubWindow* subWidget : subWidgets) { if (subWidget == nullptr)continue; if (subWidget->widget() == widget)return subWidget; } return nullptr; } QWidget* FITKMdiArea::getCurrentWidget() { FITKMdiSubWindow* subMainwin = dynamic_cast(this->currentSubWindow()); if (subMainwin == nullptr)return nullptr; return subMainwin->widget(); } QMdiSubWindow * FITKMdiArea::getCurrentSubWidget() { return this->currentSubWindow(); } void FITKMdiArea::removeCurrentWidget() { QMutexLocker locker(&_mutex); QMdiSubWindow* subMainwin = this->currentSubWindow(); if (subMainwin == nullptr)return; int id = _widgetHash.key(subMainwin); removeWidget(id); } void FITKMdiArea::updateLayout() { switch (_layoutType){ //当前视图最大化 case Comp::FITKVportsLayoutType::CurrentMax:currentMaxViewports(); break; //叠层布局 case Comp::FITKVportsLayoutType::Cascade:cascadeViewports(); break; //水平平铺 case Comp::FITKVportsLayoutType::TileHorizontally:tileHorizontallyViewports(); break; //垂直平铺 case Comp::FITKVportsLayoutType::TileVertically:tileVerticallyViewports(); break; } } void FITKMdiArea::setTabBarExpanding(bool ex /*= true */) { if (_layoutType != FITKVportsLayoutType::Tab) return; QTabBar* bar = this->findChild(); if (bar) bar->setExpanding(ex); } void FITKMdiArea::resizeEvent(QResizeEvent * event) { QMdiArea::resizeEvent(event); //大小发生变化时重新计算窗口位置 updateLayout(); } bool FITKMdiArea::eventFilter(QObject * object, QEvent * event) { QMdiArea::eventFilter(object, event); QList subWidgets = _widgetHash.values(); for (QMdiSubWindow* subWidget : subWidgets) { if (object == subWidget) { if (event->type() == QEvent::Close) { slotWidgetClose(subWidget); } } } return false; } void FITKMdiArea::slotWidgetClose(QMdiSubWindow* subWidget) { if (subWidget == nullptr)return; QList subWidgets = _widgetHash.values(); if (!subWidgets.contains(subWidget))return; _widgetHash.remove(_widgetHash.key(subWidget)); this->removeSubWindow(subWidget); } void FITKMdiArea::currentMaxViewports() { //最大化当前窗口 QMdiSubWindow* currentSubWin = this->currentSubWindow(); if (currentSubWin == nullptr)return; currentSubWin->showMaximized(); } void FITKMdiArea::cascadeViewports() { QPoint position(0, 0); // 分别设置每个视口大小为总尺寸的75% auto viewportWidth = width() * 0.75; auto viewportHeight = height() * 0.75; QList widgetList = this->subWindowList(QMdiArea::CreationOrder); for (QMdiSubWindow* widget : widgetList) { // 宽度超出最大值,则从左上角从新开始排列 if (position.x() + viewportWidth > width()) { position.setX(0); position.setY(0); } // 高度超出最大值,则从新开始一列 if (position.y() + viewportHeight > height()) { position.setY(0); } // 分别设置每个视口的位置、大小 widget->setWindowState(Qt::WindowState::WindowNoState); QRect rect(0, 0, viewportWidth, viewportHeight); widget->setGeometry(rect); widget->move(position); position.setX(position.x() + 30); position.setY(position.y() + 30); } } void FITKMdiArea::tileHorizontallyViewports() { //已创建的顺序获取列表 QList widgetList = this->subWindowList(QMdiArea::CreationOrder); // 最大可用长度和宽度 int availableWidth = width(); int availableHeight = height(); // 计算行数和列数 int count = widgetList.size(); int column = floor(sqrt((double)count)); if (column == 0) return; int row = ceil((double)count / (double)column); if (row == 0) return; // 计算每个视口的显示宽度和高度 int viewportWidth = availableWidth / column; int viewportHeight = availableHeight / row; // 当前行索引与列索引 int rowIndex = 0, columnIndex = 0; // 分别计算每个视口的长度,分别设置显示位置和大小 QPoint position(0, 0); int i = 0; for (auto widget : widgetList) { if (widget == nullptr) continue; // 计算索引为i的视口的行索引和列索引 rowIndex = floor(i / column); columnIndex = i % column; // 设置视口的显示状态 widget->setWindowState(Qt::WindowState::WindowNoState); // 设置视口大小 QRect rect(0, 0, viewportWidth, viewportHeight); widget->setGeometry(rect); // 计算视口的位置 position.setX(columnIndex * viewportWidth); position.setY(rowIndex * viewportHeight); // 移动到指定位置 widget->move(position); i++; } } void FITKMdiArea::tileVerticallyViewports() { QList widgetList = this->subWindowList(QMdiArea::CreationOrder); // 最大可用长度和宽度 int availableWidth = width(); int availableHeight = height(); // 计算行数和列数 auto count = widgetList.size(); int row = floor(sqrt((double)count)); if (row == 0) return; int column = ceil((double)count / (double)row); if (column == 0) return; // 计算每个视口的显示宽度和高度 int viewportWidth = availableWidth / column; int viewportHeight = availableHeight / row; // 当前行索引与列索引 int rowIndex = 0, columnIndex = 0; // 分别计算每个视口的长度,分别设置显示位置和大小 QPoint position(0, 0); int i = 0; for (QMdiSubWindow* widget : widgetList) { if (widget == nullptr) continue; // 计算索引为i的视口的行索引和列索引 rowIndex = floor(i / column); columnIndex = i % column; // 设置视口的显示状态 widget->setWindowState(Qt::WindowState::WindowNoState); // 设置视口大小 QRect rect(0, 0, viewportWidth, viewportHeight); widget->setGeometry(rect); // 计算视口的位置 position.setX(columnIndex * viewportWidth); position.setY(rowIndex * viewportHeight); // 移动到指定位置 widget->move(position); i++; } } }