【QGIS二次开发】地图编辑-08
系列目录:
【QGIS二次开发】地图显示与交互-01_qgis二次开发加载地图案例-CSDN博客
【QGIS二次开发】地图显示与交互-02_setlayerlabeling-CSDN博客
【QGIS二次开发】地图符号与色表-03-CSDN博客
【QGIS二次开发】地图编辑-04-CSDN博客
【QGIS二次开发】地图编辑-05-CSDN博客
【QGIS二次开发】地图编辑-06-CSDN博客
【QGIS二次开发】地图编辑-07-CSDN博客
4.17 格式刷
先将数据添加到界面上面,再点击需要作为母版的数据,再点击格式刷工具
图 74 格式刷按键
点击后,跳出的窗口会展示所有和母版矢量数据类型相同的数据,例如此处会出现所有面类型的数据,而不会出现其他类型的。勾选后点击“OK”,所有勾选的数据都会被刷上模板数据的样式。
图 75 格式刷选择图层
结果如下。
图 76 格式刷效果
相关代码分析:
DataViewer::on_actiongeshishua_triggered 函数用于响应用户触发的操作,比如菜单项点击。首先,它获取当前活动的图层,并显示一个 LayerSelectionDialog 对话框,以便用户选择要应用样式的目标图层。如果用户在对话框中选择了图层且当前图层存在,则函数获取当前图层的样式。接着,为每个选定的目标图层创建一个唯一的样式名称,并将当前图层的样式应用到这些目标图层上。
LayerSelectionDialog 类是一个继承自 QDialog 的自定义对话框类,用于显示和选择图层。构造函数接受一个当前图层(可选),并调用 setupUi 方法构建对话框界面。setupUi 方法设置对话框的标题,初始化列表部件(用于显示图层列表),并添加确定和取消按钮。如果提供了当前图层且它是矢量图层,代码会遍历项目中所有图层,并将与当前图层具有相同几何类型的矢量图层添加到列表中供用户选择。selectedLayers 方法返回用户在对话框中选中的图层列表。
代码部分如下:
class LayerSelectionDialog : public QDialog { Q_OBJECT public: LayerSelectionDialog(QWidget* parent = nullptr) : QDialog(parent) { setupUi(); } LayerSelectionDialog(QWidget* parent = nullptr, QgsMapLayer* L=nullptr) : QDialog(parent) { m_currentLayer = L; setupUi(); } QList<QgsMapLayer*> selectedLayers() const { QList<QgsMapLayer*> layers; for (int i = 0; i < m_listWidget->count(); ++i) { QListWidgetItem* item = m_listWidget->item(i); if (item->checkState() == Qt::Checked) { QgsMapLayer* layer = item->data(Qt::UserRole).value<QgsMapLayer*>(); layers.append(layer); } } return layers; } private: QgsMapLayer* m_currentLayer; QListWidget* m_listWidget; void setupUi() { setWindowTitle("选择图层"); m_listWidget = new QListWidget(this); // 检查当前图层是否为空 if (m_currentLayer && m_currentLayer->type() == QgsMapLayerType::VectorLayer) { QgsVectorLayer* veclayer = qobject_cast<QgsVectorLayer*>(m_currentLayer); if (veclayer) { // 确保转换成功 const auto layers = QgsProject::instance()->mapLayers().values(); for (QgsMapLayer* layer : layers) { if (layer->type() == QgsMapLayerType::VectorLayer) { QgsVectorLayer* eveveclayer = qobject_cast<QgsVectorLayer*>(layer); if (eveveclayer && eveveclayer->geometryType() == veclayer->geometryType()) { QListWidgetItem* item = new QListWidgetItem(eveveclayer->name(), m_listWidget); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Unchecked); item->setData(Qt::UserRole, QVariant::fromValue(eveveclayer)); } } } } } QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerSelectionDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerSelectionDialog::reject); QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(m_listWidget); layout->addWidget(buttonBox); resize(400, 300); // 设定对话框的初始大小 } }; void DataViewer::on_actiongeshishua_triggered()
{ // 显示图层选择对话框 currentLayer = m_layerTreeView->currentLayer(); LayerSelectionDialog dialog(this, currentLayer); if (dialog.exec() == QDialog::Accepted) { // 获取用户选择的目标图层列表 QList<QgsMapLayer*> targetLayers = dialog.selectedLayers(); if (!targetLayers.isEmpty() && currentLayer) { // 获取当前图层的样式名称和数据 QString currentStyleName = currentLayer->styleManager()->currentStyle(); QgsMapLayerStyle currentStyle = currentLayer->styleManager()->style(currentStyleName); // 生成唯一的样式名称 QString uniqueStyleName = "tempStyle_" + QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"); // 应用样式到每个选中的目标图层 for (QgsMapLayer* targetLayer : targetLayers) { targetLayer->styleManager()->addStyle(uniqueStyleName, currentStyle); targetLayer->styleManager()->setCurrentStyle(uniqueStyleName); } } }
}
4.18 线缓冲区
选中面弧段转后的结果作为演示数据,点击工具栏中的生成缓冲区工具,弹出输入缓冲区半径的对话框,单位根据图层的投影实时显示,用户输入半径后点击确定,操作过程如下图所示:
图 77 输入缓冲区半径
生成的缓冲区如下图所示:
图 78 生成缓冲区
生成缓冲区功能实现的主要代码如下,通过在按钮点击事件中获取用户在界面上输入的缓冲区长度,并通过迭代遍历选中的要素,在内存中创建一个新的矢量图层bufferLayer。对于每个选中的要素,获取其几何体并利用指定的缓冲区长度和圆弧段数进行缓冲区生成。然后,创建一个新的要素bufferFeature,将生成的缓冲区几何体设置为其几何体,并通过数据提供者将新要素添加到bufferLayer中。最后,将bufferLayer添加到当前QGIS项目中,并刷新地图视图以显示新添加的缓冲区图层。最后,窗口被关闭。
void QgsMapToolGenerateBuffer::on_pushButton_clicked() { QString bufferle = ui.lineEdit->text(); if (!bufferle.isEmpty()) { bufferlength = bufferle.toDouble(); QgsVectorLayer* bufferLayer = new QgsVectorLayer("Polygon?crs=epsg:4326", "Buffer", "memory"); bufferLayer->startEditing(); QgsFeatureIterator selectedFeatureIt = m_currentlayer->getSelectedFeatures(); QgsFeature selectedFeature; while (selectedFeatureIt.nextFeature(selectedFeature)) { // 获取要素的几何体 QgsGeometry geom = selectedFeature.geometry(); // 生成缓冲区,假设我们想要的缓冲区半径是bufferlength,圆弧段数是8 QgsGeometry buffer = geom.buffer(bufferlength, 8); // 创建一个新的要素 QgsFeature bufferFeature; bufferFeature.setGeometry(buffer); // 将新的要素添加到数据提供者 bufferLayer->dataProvider()->addFeature(bufferFeature); } //bufferLayer->commitChanges(); QgsProject::instance()->addMapLayer(bufferLayer); m_mapCanvas->refresh(); m_mapCanvas->refreshAllLayers(); } window->close();
}