Manual-Labeling-Tool/Manual-Label-Tool-Widget/ManualLabelToolWidget.cpp

277 lines
8.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "ManualLabelToolWidget.h"
#include <qdockwidget.h>
#include <qgslayertreeview.h>
#include <qgslayertreemodel.h>
#include <qgslayertreemapcanvasbridge.h>
#include <qgslayertreeview.h>
#include <qgslayertreemapcanvasbridge.h>
#include <qlabel.h>
#include <qstatusbar.h>
#include <QMenuBar>
#include <QToolBar>
#include <qgsmapcanvas.h>
#include <qgsrasterlayer.h>
#include <qgsmaptoolpan.h>
#include <qgsunittypes.h>
#include <QString>
#include <qgis.h>
#include <QgsMapSettings.h>
#include <QFile>
#include <QFileDialog>
#include <QDialog>
#include <QString>
#include <qfileinfo.h>
#include <qdir.h>
#include <qgsmaplayer.h>
#include <qgsproject.h>
//QgsUnitTypes
// 定义访问参数
#define RASTERFILEFILTER u8"所有文件 (*.*);;TIF (*.tif);;TIFF (*.tiff);;bin (*.bin);;dat (*.dat);;"
ManualLabelToolWidget::ManualLabelToolWidget(QWidget *parent)
: QMainWindow(parent)
{
this->init_UI();
}
ManualLabelToolWidget::~ManualLabelToolWidget()
{
}
void ManualLabelToolWidget::init_UI()
{
this->setWindowTitle(tr(u8"AI标注软件"));
// 初始大小
{
this->resize(1920,1080);
}
//地图控制
{
// 1. inti map canvas
this->map_canvas = new QgsMapCanvas();
this->setCentralWidget((this->map_canvas));
// 2. map tool pan
this->map_tool_pan = new QgsMapToolPan(this->map_canvas);
this->map_canvas->setMapTool(this->map_tool_pan);
// 3. map layer manager
this->map_layerTreeView = new QgsLayerTreeView(this);
// 4. create map model
this->map_layerModel = new QgsLayerTreeModel(QgsProject::instance()->layerTreeRoot(), this);
this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeRename); // 允许重命名
this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeReorder); // 允许调整顺序
this->map_layerModel->setFlag(QgsLayerTreeModel::AllowNodeChangeVisibility); // 允许改变可见性
this->map_layerModel->setFlag(QgsLayerTreeModel::ShowLegendAsTree); // 以树状图显示图例
this->map_layerModel->setAutoCollapseLegendNodes(10); // 自动折叠过多图例项
this->map_layerTreeView->setModel(this->map_layerModel);
// create bridge between mapcontrol and layer
this->map_layer_Bridge = new QgsLayerTreeMapCanvasBridge(QgsProject::instance()->layerTreeRoot(), this->map_canvas, this);
// layer 布局
// 1. 创建一个QDockWidget停靠窗口来承载图层树视图
this->layerTreeDock = new QDockWidget(tr(u8"图层管理器"), this);
this->layerTreeDock->setWidget(this->map_layerTreeView);
// 2. 将已有的图层树视图(m_layerTreeView)设置为这个停靠窗口的中心部件
layerTreeDock->setWidget(this->map_layerTreeView);
// 3. (可选但推荐)设置停靠窗口允许停靠的区域
layerTreeDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
// 5. 将停靠窗口添加到主窗口的左侧区域
this->addDockWidget(Qt::LeftDockWidgetArea, this->layerTreeDock);
}
// 状态工具栏
{
appStatusBar = this->statusBar(); // 获取或创建状态栏
scaleLabel = new QLabel(tr(u8"比例尺:"));
CoordinaryTextLabel = new QLabel(tr(u8"坐标系:"));
PointXYLabel = new QLabel(tr(u8"坐标:"));
UnitLabel = new QLabel(tr(u8"单位:"));
appStatusBar->addPermanentWidget(PointXYLabel); //
appStatusBar->addPermanentWidget(scaleLabel); //
appStatusBar->addPermanentWidget(UnitLabel); //
appStatusBar->addPermanentWidget(CoordinaryTextLabel); //
// 连接比例尺变化信号
connect(map_canvas, SIGNAL(scaleChanged(double)) , this, SLOT(updateScaleLabel(double)));
connect(map_canvas, SIGNAL(xyCoordinates(const QgsPointXY&)), this, SLOT(updateCoordinateLabel(const QgsPointXY&)));
connect(map_canvas, SIGNAL(extentsChanged()), this, SLOT(onMapExtentsChanged()));
}
// 菜单栏
{
menubar = this->menuBar();
// 在菜单栏上添加"文件"和"编辑"菜单
fileMenu = menubar->addMenu(tr(u8"文件"));
// 向"文件"菜单中添加菜单项QAction
newAction = fileMenu->addAction(tr(u8"新建"));
fileMenu->addSeparator(); // 添加分割线[1,5](@ref)
openMenu = fileMenu->addMenu(tr(u8"打开"));
openRasterFolderAction = openMenu->addAction(tr(u8"打开影像文件夹"));
openRasterAction = openMenu->addAction(tr(u8"打开影像"));
openSLCRasterAction = openMenu->addAction(tr(u8"SLC影像"));
editMenu = menubar->addMenu(tr(u8"编辑"));
// 事件绑定
QObject::connect(this->openRasterAction, SIGNAL(triggered()), this, SLOT(openRasterLayerTriggered()));
}
// AI标注工具栏
{
AiLabelToolBar = new QToolBar(tr(u8"AI标注工具栏"), this);
this->addToolBar(Qt::LeftToolBarArea, AiLabelToolBar);
}
}
void ManualLabelToolWidget::open()
{
}
void ManualLabelToolWidget::openRasterLayerTriggered()
{
if (lastFileDialogPath.isEmpty()) {
lastFileDialogPath = ".";
}
// 打开影像
// 2. 选择多个文件
QString rasterPath = QFileDialog::getOpenFileName(
this,
tr(u8"请选择影像文件"),
lastFileDialogPath,
tr(RASTERFILEFILTER)
);
lastFileDialogPath = rasterPath;
// 读取数据
this->openRaster(rasterPath);
}
void ManualLabelToolWidget::openRaster(QString& filePath)
{
QString filename = QFileInfo(filePath).fileName();
QgsRasterLayer* rasterLayer = new QgsRasterLayer(filePath, filename);
if (!rasterLayer->isValid()) {
qDebug() << "Failed to load raster layer!";
// 错误处理
return;
}
QgsProject::instance()->addMapLayer(rasterLayer);
}
void ManualLabelToolWidget::updateCoordinateLabel(const QgsPointXY& point)
{
QString coordText = QString(tr(u8"坐标X:%1 Y:%2")).arg(QString::number(point.x(), 'f', 2)).arg(QString::number(point.y(), 'f', 2));
PointXYLabel->setText(coordText);
}
void ManualLabelToolWidget::onMapExtentsChanged()
{
QgsRectangle currentExtent = map_canvas->extent();
//// 现在你可以使用这个范围信息了,例如:
//// 1. 打印范围坐标
//qDebug() << "新范围 - Xmin:" << currentExtent.xMinimum()
// << "Ymin:" << currentExtent.yMinimum()
// << "Xmax:" << currentExtent.xMaximum()
// << "Ymax:" << currentExtent.yMaximum();
}
void ManualLabelToolWidget::onLayersChanged(QgsMapLayer* layer)
{
// WGS坐标系
QgsCoordinateReferenceSystem currentCrs = map_canvas->mapSettings().destinationCrs();
// 获取坐标系的描述信息和认证标识符,例如 "WGS 84 / EPSG:4326"
QString description = currentCrs.description();
QString authid = currentCrs.authid();
// 获取当前项目中所有图层
QList<QgsMapLayer*> layers = QgsProject::instance()->mapLayers().values();
int layerCount = layers.size();
// 判断当前是否仅有一层
if (layerCount == 0&&description == "") {
QgsMapLayer* theOnlyLayer = layers.first();
// 检查图层是否有效且拥有定义的坐标系
if (theOnlyLayer && theOnlyLayer->isValid() && theOnlyLayer->crs().isValid()) {
// 将地图画布的目标坐标系设置为与图层一致
map_canvas->mapSettings().setDestinationCrs(theOnlyLayer->crs());
// 可选:将地图范围缩放至该图层的全范围,提供更好的初始视图
map_canvas->setExtent(theOnlyLayer->extent());
// 刷新画布,使更改生效
map_canvas->refresh();
qDebug() << "图层数量为1已同步画布坐标系至" << theOnlyLayer->crs().description();
}
}
}
void ManualLabelToolWidget::updateScaleLabel(double scale)
{
// 将比例尺数值格式化为易读的字符串,例如 1:10000
QString scaleText = QString(tr(u8"比例尺1:%1")).arg(QString::number(scale, 'f', 0));
scaleLabel->setText(scaleText);
// 同时更新单位标签
Qgis::DistanceUnit unit = map_canvas->mapUnits();
QString unitString;
if (unit == Qgis::DistanceUnit::Meters) {
unitString = tr(u8"");
}
else if (unit == Qgis::DistanceUnit::Degrees) {
unitString = tr(u8"");
}
else if (unit == Qgis::DistanceUnit::Feet) {
unitString = tr(u8"英尺");
}
else {
unitString = tr(u8"未知");
}
UnitLabel->setText(QString(tr(u8"单位:%1")).arg(unitString));
// WGS坐标系
QgsCoordinateReferenceSystem currentCrs = map_canvas->mapSettings().destinationCrs();
// 获取坐标系的描述信息和认证标识符,例如 "WGS 84 / EPSG:4326"
QString description = currentCrs.description();
QString authid = currentCrs.authid();
if (description == "") {
// 假设 ui->label_crs 是用于显示坐标系信息的QLabel
CoordinaryTextLabel->setText(QString(tr(u8"坐标系:未知")));
}
else {
// 假设 ui->label_crs 是用于显示坐标系信息的QLabel
CoordinaryTextLabel->setText(QString(tr(u8"坐标系:%1 (%2)")).arg(description).arg(authid));
}
}