当前位置:   article > 正文

实战PyQt5:169-数据可视化之三维表面图交互演示_pyqt5显示三维

pyqt5显示三维

表面图是数据可视化的另一种常见显示形式,本文演示如何使用交互方式控制三维表面图显示。

 

一、示例程序的基本功能

本文演示如何使用Q3Dsurface来创建一个简单的3D表面图,并使用一些控件来交互调节,以使3D达到合适的质量效果。这个实例程序演示了一下一些功能:

  • 如何设置QSurfaceDataProxy并为其设置合适的数据;
  • 如何使用QHeightMapSurfaceDataProxy显示一个3D高度图;
  • 3D图形的三种不同的选择模式;
  • 3D图形选定部分的轴范围的用法;
  • 更改主题;
  • 如何设置自定义曲面的渐变效果。

二、示例程序分析

演示程序包括两部分,我们将曲面的交互功能部分封装在类DemoWidget中, 首先调用QWidget::createWindowContainer()创建窗口容器。然后创建水平和垂直布局管理,将图形和垂直布局添加到一个水平布局中,垂直布局中用于添加交互部件。水平布局设置为DemoWidget的布局。

创建另一个类SurfaceGraph来处理数据添加以及与图形的其他交互。

现在简要分析SurfaceGraph类的功能:

设置代理(Proxy)和数据

首先,我们创建一个QSurfaceDataProxy实例,并将其附加到一个新创建的QSurface3DSeries上:

  1. self.sqrtSinProxy = QSurfaceDataProxy()
  2. self.sqrtSinSeries = QSurface3DSeries(self.sqrtSinProxy)

然后我们用简单的平方根和正弦波数据填充代理。这是通过创建一个新实例并向其中添加元素。

  1. def fillSqrtSinProxy(self):
  2. stepX = (sampleMax - sampleMin) / float(sampleCountX - 1)
  3. stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1)
  4. dataArray = []
  5. index = 0
  6. for i in range(sampleCountZ):
  7. z = min(sampleMax, i * stepZ + sampleMin)
  8. x_arr = []
  9. for j in range(sampleCountX):
  10. x = min(sampleMax, j * stepX + sampleMin)
  11. R = math.sqrt(z * z + x * x) + 0.01
  12. y = (math.sin(R) / R + 0.24) * 1.61
  13. x_arr.append(QSurfaceDataItem(QVector3D(x, y, z)))
  14. dataArray.append(x_arr)
  15. self.sqrtSinProxy.resetArray(dataArray)

高度映射是通过实例化一个QHeightMapSurfaceDataProxy和一个包含高度数据的QImage来创建的。QHeightMapSurfaceDataProxy::setValueRanges()方法用于定义映射的值范围。在我们的例子中,地图的假想位置为34.0°N - 40.0°N和18.0°E - 24.0°E。这些值用于显示和定位地图到轴线。

  1. heightMapImage = QImage(':/maps/mountain')
  2. self.heightMapProxy = QHeightMapSurfaceDataProxy(heightMapImage)
  3. self.heightMapSeries = QSurface3DSeries(self.heightMapProxy)
  4. self.heightMapSeries.setItemLabelFormat('(@xLabel, @zLabel): @yLabel')
  5. self.heightMapProxy.setValueRanges(34.0, 40.0, 18.0, 24.0)

为了演示不同的Proxy,这个示例有两个单选按钮,用户可以使用它们在Serial之间切换。当用户选择”Sqrt & Sin”单选按钮时,所选Serial将使用以下代码激活。

  1. self.sqrtSinSeries.setDrawMode(QSurface3DSeries.DrawSurfaceAndWireframe)
  2. self.sqrtSinSeries.setFlatShadingEnabled(True)
  3. self.graph.axisX().setLabelFormat('%.2f')
  4. self.graph.axisZ().setLabelFormat('%.2f')
  5. self.graph.axisX().setRange(sampleMin, sampleMax)
  6. self.graph.axisY().setRange(0.0, 2.0)
  7. self.graph.axisZ().setRange(sampleMin, sampleMax)
  8. self.graph.axisX().setLabelAutoRotation(30)
  9. self.graph.axisY().setLabelAutoRotation(90)
  10. self.graph.axisZ().setLabelAutoRotation(30)
  11. self.graph.removeSeries(self.heightMapSeries)
  12. self.graph.addSeries(self.sqrtSinSeries)

当用户选择”高度地图”单选按钮时,所选Serial将使用以下代码激活。

  1. self.heightMapSeries.setDrawMode(QSurface3DSeries.DrawSurface)
  2. self.heightMapSeries.setFlatShadingEnabled(False)
  3. self.graph.axisX().setLabelFormat('%.1f N')
  4. self.graph.axisZ().setLabelFormat('%.1f E')
  5. self.graph.axisX().setRange(34.0, 40.0)
  6. self.graph.axisY().setAutoAdjustRange(True)
  7. self.graph.axisZ().setRange(18.0, 24.0)
  8. self.graph.axisX().setTitle('纬度')
  9. self.graph.axisY().setTitle('高度')
  10. self.graph.axisZ().setTitle('经度')
  11. self.graph.removeSeries(self.sqrtSinSeries)
  12. self.graph.addSeries(self.heightMapSeries)

选择模式

Q3Dsurface支持三种不同的选择模式。示例中使用单选按钮演示了这些功能,用户可以使用单选按钮激活合适的选择模式。

  1. def toggleModeNone(self):
  2. self.graph.setSelectionMode(QAbstract3DGraph.SelectionNone)
  3. def toggleModeItem(self):
  4. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItem)
  5. def toggleModeSliceRow(self):
  6. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItemAndRow | QAbstract3DGraph.SelectionSlice)
  7. def toggleModeSliceColumn(self):
  8. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItemAndColumn | QAbstract3DGraph.SelectionSlice)

图形的坐标轴范围

示例有四个滑块控件,用于调整X和Z轴的最小值和最大值。

  1. #为Sqrt&Sin 重新设置滑动条范围
  2. self.rangeMinX = sampleMin
  3. self.rangeMinZ = sampleMin
  4. self.stepX = (sampleMax - sampleMin) / float(sampleCountX - 1)
  5. self.stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1)
  6. self.axisMinSliderX.setMaximum(sampleCountX - 2)
  7. self.axisMinSliderX.setValue(0)
  8. self.axisMaxSliderX.setMaximum(sampleCountX - 1)
  9. self.axisMaxSliderX.setValue(sampleCountX - 1)
  10. self.axisMinSliderZ.setMaximum(sampleCountZ - 2)
  11. self.axisMinSliderZ.setValue(0)
  12. self.axisMaxSliderZ.setMaximum(sampleCountZ - 1)
  13. self.axisMaxSliderZ.setValue(sampleCountZ - 1)

主题

Q3DSurface支持所有Qt数据可视化的主题。本示例有一个用于选择主题的下拉菜单。下面的方法连接到菜单以激活所选主题。将主题类型更改为另一个预定义主题,该主题将所有主题属性覆盖为预定义值

  1. def changeTheme(self, theme):
  2. self.graph.activeTheme().setType(theme)

自定义表面渐变

示例程序演示了使用两个按钮的自定义表面渐变。渐变可以用QLinearGradient定义,其中所需的颜色被设置为位置。下面的代码展示了如何创建示例渐变并将其设置为系列。注意,还需要将颜色样式更改为Q3DTheme::ColorStyleRangeGradient来实际使用渐变。

  1. gr = QLinearGradient()
  2. gr.setColorAt(0.0, Qt.black)
  3. gr.setColorAt(0.33, Qt.blue)
  4. gr.setColorAt(0.67, Qt.red)
  5. gr.setColorAt(1.0, Qt.yellow)
  6. self.graph.seriesList()[0].setBaseGradient(gr)
  7. self.graph.seriesList()[0].setColorStyle(Q3DTheme.ColorStyleRangeGradient)

surfacegraph.py完整代码:

  1. import math
  2. from PyQt5.QtCore import Qt, QObject
  3. from PyQt5.QtGui import QVector3D, QImage, QLinearGradient
  4. from PyQt5.QtDataVisualization import (Q3DSurface, QSurface3DSeries, QSurfaceDataProxy, QSurfaceDataItem,
  5. QAbstract3DSeries, QValue3DAxis, QAbstract3DGraph, Q3DCamera,
  6. Q3DTheme, QHeightMapSurfaceDataProxy)
  7. sampleCountX = 50
  8. sampleCountZ = 50
  9. heightMapGridStepX = 6
  10. heightMapGridStepZ = 6
  11. sampleMin = -8.0
  12. sampleMax = 8.0
  13. class SurfaceGraph(QObject):
  14. def __init__(self, surface):
  15. super(SurfaceGraph, self).__init__()
  16. self.graph = surface
  17. self.graph.setAxisX(QValue3DAxis())
  18. self.graph.setAxisY(QValue3DAxis())
  19. self.graph.setAxisZ(QValue3DAxis())
  20. self.sqrtSinProxy = QSurfaceDataProxy()
  21. self.sqrtSinSeries = QSurface3DSeries(self.sqrtSinProxy)
  22. self.fillSqrtSinProxy()
  23. heightMapImage = QImage(':/maps/mountain')
  24. self.heightMapProxy = QHeightMapSurfaceDataProxy(heightMapImage)
  25. self.heightMapSeries = QSurface3DSeries(self.heightMapProxy)
  26. self.heightMapSeries.setItemLabelFormat('(@xLabel, @zLabel): @yLabel')
  27. self.heightMapProxy.setValueRanges(34.0, 40.0, 18.0, 24.0)
  28. self.heightMapWidth = heightMapImage.width()
  29. self.heightMapHeight = heightMapImage.height()
  30. def toggleModeNone(self):
  31. self.graph.setSelectionMode(QAbstract3DGraph.SelectionNone)
  32. def toggleModeItem(self):
  33. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItem)
  34. def toggleModeSliceRow(self):
  35. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItemAndRow | QAbstract3DGraph.SelectionSlice)
  36. def toggleModeSliceColumn(self):
  37. self.graph.setSelectionMode(QAbstract3DGraph.SelectionItemAndColumn | QAbstract3DGraph.SelectionSlice)
  38. def setAxisMinSliderX(self, slider):
  39. self.axisMinSliderX = slider
  40. def setAxisMaxSliderX(self, slider):
  41. self.axisMaxSliderX = slider
  42. def setAxisMinSliderZ(self, slider):
  43. self.axisMinSliderZ = slider
  44. def setAxisMaxSliderZ(self, slider):
  45. self.axisMaxSliderZ = slider
  46. def fillSqrtSinProxy(self):
  47. stepX = (sampleMax - sampleMin) / float(sampleCountX - 1)
  48. stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1)
  49. dataArray = []
  50. index = 0
  51. for i in range(sampleCountZ):
  52. z = min(sampleMax, i * stepZ + sampleMin)
  53. x_arr = []
  54. for j in range(sampleCountX):
  55. x = min(sampleMax, j * stepX + sampleMin)
  56. R = math.sqrt(z * z + x * x) + 0.01
  57. y = (math.sin(R) / R + 0.24) * 1.61
  58. x_arr.append(QSurfaceDataItem(QVector3D(x, y, z)))
  59. dataArray.append(x_arr)
  60. self.sqrtSinProxy.resetArray(dataArray)
  61. def enableSqrtSinModel(self, enable):
  62. if not enable:
  63. return
  64. self.sqrtSinSeries.setDrawMode(QSurface3DSeries.DrawSurfaceAndWireframe)
  65. self.sqrtSinSeries.setFlatShadingEnabled(True)
  66. self.graph.axisX().setLabelFormat('%.2f')
  67. self.graph.axisZ().setLabelFormat('%.2f')
  68. self.graph.axisX().setRange(sampleMin, sampleMax)
  69. self.graph.axisY().setRange(0.0, 2.0)
  70. self.graph.axisZ().setRange(sampleMin, sampleMax)
  71. self.graph.axisX().setLabelAutoRotation(30)
  72. self.graph.axisY().setLabelAutoRotation(90)
  73. self.graph.axisZ().setLabelAutoRotation(30)
  74. self.graph.removeSeries(self.heightMapSeries)
  75. self.graph.addSeries(self.sqrtSinSeries)
  76. #为Sqrt&Sin 重新设置滑动条范围
  77. self.rangeMinX = sampleMin
  78. self.rangeMinZ = sampleMin
  79. self.stepX = (sampleMax - sampleMin) / float(sampleCountX - 1)
  80. self.stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1)
  81. self.axisMinSliderX.setMaximum(sampleCountX - 2)
  82. self.axisMinSliderX.setValue(0)
  83. self.axisMaxSliderX.setMaximum(sampleCountX - 1)
  84. self.axisMaxSliderX.setValue(sampleCountX - 1)
  85. self.axisMinSliderZ.setMaximum(sampleCountZ - 2)
  86. self.axisMinSliderZ.setValue(0)
  87. self.axisMaxSliderZ.setMaximum(sampleCountZ - 1)
  88. self.axisMaxSliderZ.setValue(sampleCountZ - 1)
  89. def enableHeightMapModel(self, enable):
  90. if not enable:
  91. return
  92. self.heightMapSeries.setDrawMode(QSurface3DSeries.DrawSurface)
  93. self.heightMapSeries.setFlatShadingEnabled(False)
  94. self.graph.axisX().setLabelFormat('%.1f N')
  95. self.graph.axisZ().setLabelFormat('%.1f E')
  96. self.graph.axisX().setRange(34.0, 40.0)
  97. self.graph.axisY().setAutoAdjustRange(True)
  98. self.graph.axisZ().setRange(18.0, 24.0)
  99. self.graph.axisX().setTitle('纬度')
  100. self.graph.axisY().setTitle('高度')
  101. self.graph.axisZ().setTitle('经度')
  102. self.graph.removeSeries(self.sqrtSinSeries)
  103. self.graph.addSeries(self.heightMapSeries)
  104. #重新设置滚动条的范围
  105. mapGridCountX = self.heightMapWidth / heightMapGridStepX
  106. mapGridCountZ = self.heightMapHeight / heightMapGridStepZ
  107. self.rangeMinX = 34.0
  108. self.rangeMinZ = 18.0
  109. self.stepX = 6.0 / float(mapGridCountX - 1)
  110. self.stepZ = 6.0 / float(mapGridCountZ - 1)
  111. self.axisMinSliderX.setMaximum(mapGridCountX - 2)
  112. self.axisMinSliderX.setValue(0)
  113. self.axisMaxSliderX.setMaximum(mapGridCountX - 1)
  114. self.axisMaxSliderX.setValue(mapGridCountX - 1)
  115. self.axisMinSliderZ.setMaximum(mapGridCountZ - 2)
  116. self.axisMinSliderZ.setValue(0)
  117. self.axisMaxSliderZ.setMaximum(mapGridCountZ - 1)
  118. self.axisMaxSliderZ.setValue(mapGridCountZ - 1)
  119. def adjustXMin(self, minVal):
  120. minX = self.stepX * minVal + self.rangeMinX
  121. maxVal = self.axisMaxSliderX.value()
  122. if minVal >= maxVal:
  123. maxVal = minVal + 1
  124. self.axisMaxSliderX.setValue(maxVal)
  125. maxX = self.stepX * maxVal + self.rangeMinX
  126. self.setAxisXRange(minX, maxX)
  127. def adjustXMax(self, maxVal):
  128. maxX = self.stepX * maxVal + self.rangeMinX
  129. minVal = self.axisMinSliderX.value()
  130. if maxVal <= minVal:
  131. minVal = maxVal - 1
  132. self.axisMinSliderX.setValue(minVal)
  133. minX = self.stepX * minVal + self.rangeMinX
  134. self.setAxisXRange(minX, maxX)
  135. def adjustZMin(self, minVal):
  136. minZ = self.stepZ * minVal + self.rangeMinZ
  137. maxVal = self.axisMaxSliderZ.value()
  138. if minVal >= maxVal:
  139. maxVal = minVal + 1
  140. self.axisMaxSliderZ.setValue(maxVal)
  141. maxZ = self.stepZ * maxVal + self.rangeMinZ
  142. self.setAxisZRange(minZ, maxZ)
  143. def adjustZMax(self, maxVal):
  144. maxZ = self.stepZ * maxVal + self.rangeMinZ
  145. minVal = self.axisMinSliderZ.value()
  146. if maxVal <= minVal:
  147. minVal = maxVal - 1
  148. self.axisMinSliderZ.setValue(minVal)
  149. minZ = self.stepZ * minVal + self.rangeMinZ
  150. self.setAxisZRange(minZ, maxZ)
  151. def setAxisXRange(self, minVal, maxVal):
  152. self.graph.axisX().setRange(minVal, maxVal)
  153. def setAxisZRange(self, minVal, maxVal):
  154. self.graph.axisZ().setRange(minVal, maxVal)
  155. def changeTheme(self, theme):
  156. self.graph.activeTheme().setType(theme)
  157. def setBlackToYellowGradient(self):
  158. gr = QLinearGradient()
  159. gr.setColorAt(0.0, Qt.black)
  160. gr.setColorAt(0.33, Qt.blue)
  161. gr.setColorAt(0.67, Qt.red)
  162. gr.setColorAt(1.0, Qt.yellow)
  163. self.graph.seriesList()[0].setBaseGradient(gr)
  164. self.graph.seriesList()[0].setColorStyle(Q3DTheme.ColorStyleRangeGradient)
  165. def setGreenToRedGradient(self):
  166. gr = QLinearGradient()
  167. gr.setColorAt(0.0, Qt.darkGreen)
  168. gr.setColorAt(0.5, Qt.yellow)
  169. gr.setColorAt(0.8, Qt.red)
  170. gr.setColorAt(1.0, Qt.darkRed)
  171. self.graph.seriesList()[0].setBaseGradient(gr)
  172. self.graph.seriesList()[0].setColorStyle(Q3DTheme.ColorStyleRangeGradient)

surfacedemo.py 完整代码:

  1. import sys
  2. from PyQt5 import QtCore, QtGui, QtWidgets
  3. from PyQt5.QtCore import Qt, QSize
  4. from PyQt5.QtGui import QLinearGradient, QPixmap, QPainter, QBrush, QIcon
  5. from PyQt5.QtWidgets import (QApplication, QWidget, QMessageBox, QSizePolicy,
  6. QHBoxLayout, QVBoxLayout, QComboBox, QPushButton,
  7. QCheckBox, QSlider, QGroupBox, QLabel, QRadioButton)
  8. from PyQt5.QtDataVisualization import (Q3DSurface, QAbstract3DSeries, QAbstract3DGraph)
  9. from surfacegraph import SurfaceGraph
  10. import surface_rc
  11. class DemoWidget(QWidget):
  12. def __init__(self, parent=None):
  13. super(DemoWidget, self).__init__(parent)
  14. # 设置窗口标题
  15. self.setWindowTitle('实战 Qt for Python: 三维表面图演示')
  16. # 设置窗口大小
  17. self.resize(640, 480)
  18. self.initUi()
  19. def initUi(self):
  20. widgetgraph = Q3DSurface()
  21. container = QWidget.createWindowContainer(widgetgraph)
  22. if not widgetgraph.hasContext():
  23. msgBox = QMessageBox()
  24. msgBox.setText('不能初始化OpenGL上下文')
  25. msgBox.exec()
  26. return;
  27. screenSize = widgetgraph.screen().size()
  28. container.setMinimumSize(QSize(int(screenSize.width() / 2.0), int(screenSize.height() / 1.5)))
  29. container.setMaximumSize(screenSize)
  30. container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  31. container.setFocusPolicy(Qt.StrongFocus)
  32. hLayout = QHBoxLayout()
  33. vLayout = QVBoxLayout()
  34. hLayout.addWidget(container, 1) #左边绘图部分
  35. hLayout.addLayout(vLayout) #右边控制部分
  36. vLayout.setAlignment(Qt.AlignTop)
  37. modelGroupBox = QGroupBox('模型')
  38. sqrtSinModelRB = QRadioButton(self)
  39. sqrtSinModelRB.setText('Sqrt && Sin')
  40. sqrtSinModelRB.setChecked(False)
  41. heightMapModelRB = QRadioButton(self)
  42. heightMapModelRB.setText('高度地图')
  43. heightMapModelRB.setChecked(False)
  44. modelVBox = QVBoxLayout()
  45. modelVBox.addWidget(sqrtSinModelRB)
  46. modelVBox.addWidget(heightMapModelRB)
  47. modelGroupBox.setLayout(modelVBox)
  48. selectionGroupBox = QGroupBox('选择模式')
  49. modeNoneRB = QRadioButton(self)
  50. modeNoneRB.setText('无选择')
  51. modeNoneRB.setChecked(False)
  52. modeItemRB = QRadioButton(self)
  53. modeItemRB.setText('条目')
  54. modeItemRB.setChecked(False)
  55. modeSliceRowRB = QRadioButton(self)
  56. modeSliceRowRB.setText('Row Slice')
  57. modeSliceRowRB.setChecked(False)
  58. modeSliceColumnRB = QRadioButton(self)
  59. modeSliceColumnRB.setText('Column Slice')
  60. modeSliceColumnRB.setChecked(False)
  61. selectionVBox = QVBoxLayout()
  62. selectionVBox.addWidget(modeNoneRB)
  63. selectionVBox.addWidget(modeItemRB)
  64. selectionVBox.addWidget(modeSliceRowRB)
  65. selectionVBox.addWidget(modeSliceColumnRB)
  66. selectionGroupBox.setLayout(selectionVBox)
  67. axisMinSliderX = QSlider(Qt.Horizontal, self)
  68. axisMinSliderX.setMinimum(0)
  69. axisMinSliderX.setTickInterval(1)
  70. axisMinSliderX.setEnabled(True)
  71. axisMaxSliderX = QSlider(Qt.Horizontal, self)
  72. axisMaxSliderX.setMinimum(1)
  73. axisMaxSliderX.setTickInterval(1)
  74. axisMaxSliderX.setEnabled(True)
  75. axisMinSliderZ = QSlider(Qt.Horizontal, self)
  76. axisMinSliderZ.setMinimum(0)
  77. axisMinSliderZ.setTickInterval(1)
  78. axisMinSliderZ.setEnabled(True)
  79. axisMaxSliderZ = QSlider(Qt.Horizontal, self)
  80. axisMaxSliderZ.setMinimum(1)
  81. axisMaxSliderZ.setTickInterval(1)
  82. axisMaxSliderZ.setEnabled(True)
  83. #图表主题控制
  84. themeList = QComboBox(self)
  85. themeList.addItem('Qt')
  86. themeList.addItem('Primary Colors')
  87. themeList.addItem('Digia')
  88. themeList.addItem('Stone Moss')
  89. themeList.addItem('Army Blue')
  90. themeList.addItem('Retro')
  91. themeList.addItem('Ebony')
  92. themeList.addItem('Isabelle')
  93. themeList.setCurrentIndex(6)
  94. colorGroupBox = QGroupBox('自定义梯度')
  95. grBtoY = QLinearGradient(0, 0, 1, 100)
  96. grBtoY.setColorAt(1.0, Qt.black)
  97. grBtoY.setColorAt(0.67, Qt.blue)
  98. grBtoY.setColorAt(0.33, Qt.red)
  99. grBtoY.setColorAt(0.0, Qt.yellow)
  100. pm = QPixmap(24, 100)
  101. pmp = QPainter(pm)
  102. pmp.setBrush(QBrush(grBtoY))
  103. pmp.setPen(Qt.NoPen)
  104. pmp.drawRect(0, 0, 24, 100)
  105. gradientBtoYPB = QPushButton(self)
  106. gradientBtoYPB.setIcon(QIcon(pm))
  107. gradientBtoYPB.setIconSize(QSize(24, 100))
  108. grGtoR = QLinearGradient(0, 0, 1, 100)
  109. grGtoR.setColorAt(1.0, Qt.darkGreen)
  110. grGtoR.setColorAt(0.67, Qt.yellow)
  111. grGtoR.setColorAt(0.33, Qt.red)
  112. grGtoR.setColorAt(0.0, Qt.darkRed)
  113. pmp.setBrush(QBrush(grGtoR))
  114. pmp.setPen(Qt.NoPen)
  115. pmp.drawRect(0, 0, 24, 100)
  116. gradientGtoRPB = QPushButton(self)
  117. gradientGtoRPB.setIcon(QIcon(pm))
  118. gradientGtoRPB.setIconSize(QSize(24, 100))
  119. #必须控制先后释放顺序
  120. del pmp
  121. del pm
  122. colorHBox = QHBoxLayout()
  123. colorHBox.addWidget(gradientBtoYPB)
  124. colorHBox.addWidget(gradientGtoRPB)
  125. colorGroupBox.setLayout(colorHBox)
  126. vLayout.addWidget(modelGroupBox)
  127. vLayout.addWidget(selectionGroupBox)
  128. vLayout.addWidget(QLabel('列范围'))
  129. vLayout.addWidget(axisMinSliderX)
  130. vLayout.addWidget(axisMaxSliderX)
  131. vLayout.addWidget(QLabel('行范围'))
  132. vLayout.addWidget(axisMinSliderZ)
  133. vLayout.addWidget(axisMaxSliderZ)
  134. vLayout.addWidget(QLabel('主题'))
  135. vLayout.addWidget(themeList)
  136. vLayout.addWidget(colorGroupBox)
  137. self.modifier = SurfaceGraph(widgetgraph)
  138. heightMapModelRB.toggled.connect(self.modifier.enableHeightMapModel)
  139. sqrtSinModelRB.toggled.connect(self.modifier.enableSqrtSinModel)
  140. modeNoneRB.toggled.connect(self.modifier.toggleModeNone)
  141. modeItemRB.toggled.connect(self.modifier.toggleModeItem)
  142. modeSliceRowRB.toggled.connect(self.modifier.toggleModeSliceRow)
  143. modeSliceColumnRB.toggled.connect(self.modifier.toggleModeSliceColumn)
  144. axisMinSliderX.valueChanged.connect(self.modifier.adjustXMin)
  145. axisMaxSliderX.valueChanged.connect(self.modifier.adjustXMax)
  146. axisMinSliderZ.valueChanged.connect(self.modifier.adjustZMin)
  147. axisMaxSliderZ.valueChanged.connect(self.modifier.adjustZMax)
  148. themeList.currentIndexChanged.connect(self.modifier.changeTheme)
  149. gradientBtoYPB.pressed.connect(self.modifier.setBlackToYellowGradient)
  150. gradientGtoRPB.pressed.connect(self.modifier.setGreenToRedGradient)
  151. self.modifier.setAxisMinSliderX(axisMinSliderX)
  152. self.modifier.setAxisMaxSliderX(axisMaxSliderX)
  153. self.modifier.setAxisMinSliderZ(axisMinSliderZ)
  154. self.modifier.setAxisMaxSliderZ(axisMaxSliderZ)
  155. sqrtSinModelRB.setChecked(True)
  156. modeItemRB.setChecked(True)
  157. themeList.setCurrentIndex(2)
  158. self.setLayout(hLayout)
  159. if __name__ == '__main__':
  160. app = QApplication(sys.argv)
  161. window = DemoWidget()
  162. window.show()
  163. sys.exit(app.exec())

运行结果如下图。

 3D表面图映射效果

3D表面图交互演示 

三、本文知识点

  • 三维表面图的不同模式(表面模式,表面加线模式等);
  • 数据可视化中的三维表面图交互控制。

前一篇:实战PyQt5:168-数据可视化之三维散点图交互演示

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/132428
推荐阅读
相关标签
  

闽ICP备14008679号