PyQt/QtDataVisualization/ScatterVisualization.py

296 lines
10 KiB
Python
Raw Permalink Normal View History

2019-10-04 23:39:16 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019/10/4
@author: Irony
2021-07-13 14:52:26 +08:00
@site: https://pyqt.site , https://github.com/PyQt5
2019-10-04 23:39:16 +08:00
@email: 892768447@qq.com
@file: ScatterVisualization
@description:
"""
#############################################################################
##
## Copyright (C) 2014 Riverbank Computing Limited.
## Copyright (C) 2014 Digia Plc
## All rights reserved.
## For any questions to Digia, please use contact form at http://qt.digia.com
##
## This file is part of the QtDataVisualization module.
##
## Licensees holding valid Qt Enterprise licenses may use this file in
## accordance with the Qt Enterprise License Agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and Digia.
##
## If you have questions regarding the use of this file, please use
## contact form at http://qt.digia.com
##
#############################################################################
import math
from PyQt5.QtCore import pyqtSignal, QObject, QSize, Qt, QLocale
from PyQt5.QtDataVisualization import (Q3DCamera, Q3DTheme, Q3DScatter,
QAbstract3DGraph, QAbstract3DSeries, QScatter3DSeries,
QScatterDataItem, QScatterDataProxy)
from PyQt5.QtGui import QFont, QVector3D
from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QFontComboBox,
QHBoxLayout, QLabel, QPushButton, QSizePolicy, QVBoxLayout, QWidget)
country = QLocale.system().country()
if country in (QLocale.China, QLocale.HongKong, QLocale.Taiwan):
Tr = {
'A Cosine Wave': '余弦波',
'Change label style': '更改label样式',
'Smooth dots': '平滑圆点',
'Change camera preset': '更改相机预设',
'Show background': '显示背景',
'Show grid': '显示网格',
'Change dot style': '更改点样式',
'Change theme': '更改主题',
'Adjust shadow quality': '调整阴影质量',
'Change font': '更改字体'
}
else:
Tr = {}
class ScatterDataModifier(QObject):
numberOfItems = 3600
curveDivider = 3.0
lowerNumberOfItems = 900
lowerCurveDivider = 0.75
backgroundEnabledChanged = pyqtSignal(bool)
gridEnabledChanged = pyqtSignal(bool)
shadowQualityChanged = pyqtSignal(int)
fontChanged = pyqtSignal(QFont)
def __init__(self, scatter):
super(ScatterDataModifier, self).__init__()
self.m_graph = scatter # Q3DScatter实例
self.m_fontSize = 40.0
self.m_style = QAbstract3DSeries.MeshSphere
self.m_smooth = True
self.m_itemCount = self.lowerNumberOfItems
self.m_curveDivider = self.lowerCurveDivider
# 设置当前主题类型
self.m_graph.activeTheme().setType(Q3DTheme.ThemeEbony)
# 设置当前主题的字体
font = self.m_graph.activeTheme().font()
font.setPointSize(self.m_fontSize)
self.m_graph.activeTheme().setFont(font)
# 设置阴影质量
self.m_graph.setShadowQuality(QAbstract3DGraph.ShadowQualitySoftLow)
self.m_graph.scene().activeCamera().setCameraPreset(
Q3DCamera.CameraPresetFront)
proxy = QScatterDataProxy()
series = QScatter3DSeries(proxy)
series.setItemLabelFormat(
"@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel")
series.setMeshSmooth(self.m_smooth)
self.m_graph.addSeries(series)
self.addData()
def addData(self):
# 添加数据
self.m_graph.axisX().setTitle("X")
self.m_graph.axisY().setTitle("Y")
self.m_graph.axisZ().setTitle("Z")
dataArray = []
limit = math.sqrt(self.m_itemCount) / 2.0
i = -limit
while i < limit:
j = -limit
while j < limit:
itm = QScatterDataItem(
QVector3D(i + 0.5,
math.cos(
math.radians((i * j) / self.m_curveDivider)),
j + 0.5))
dataArray.append(itm)
j += 1.0
i += 1.0
self.m_graph.seriesList()[0].dataProxy().resetArray(dataArray)
def changeStyle(self, style):
comboBox = self.sender()
if isinstance(comboBox, QComboBox):
self.m_style = QAbstract3DSeries.Mesh(comboBox.itemData(style))
self.m_graph.seriesList()[0].setMesh(self.m_style)
def setSmoothDots(self, smooth):
self.m_smooth = bool(smooth)
self.m_graph.seriesList()[0].setMeshSmooth(self.m_smooth)
def changeTheme(self, theme):
currentTheme = self.m_graph.activeTheme()
currentTheme.setType(Q3DTheme.Theme(theme))
self.backgroundEnabledChanged.emit(currentTheme.isBackgroundEnabled())
self.gridEnabledChanged.emit(currentTheme.isGridEnabled())
self.fontChanged.emit(currentTheme.font())
preset = int(Q3DCamera.CameraPresetFrontLow)
def changePresetCamera(self):
self.m_graph.scene().activeCamera().setCameraPreset(
Q3DCamera.CameraPreset(self.preset))
self.preset += 1
if self.preset > Q3DCamera.CameraPresetDirectlyBelow:
self.preset = int(Q3DCamera.CameraPresetFrontLow)
def changeLabelStyle(self):
self.m_graph.activeTheme().setLabelBackgroundEnabled(
not self.m_graph.activeTheme().isLabelBackgroundEnabled())
def changeFont(self, font):
newFont = QFont(font)
newFont.setPointSizeF(self.m_fontSize)
self.m_graph.activeTheme().setFont(newFont)
def shadowQualityUpdatedByVisual(self, sq):
self.shadowQualityChanged.emit(int(sq))
def changeShadowQuality(self, quality):
sq = QAbstract3DGraph.ShadowQuality(quality)
self.m_graph.setShadowQuality(sq)
def setBackgroundEnabled(self, enabled):
self.m_graph.activeTheme().setBackgroundEnabled(enabled)
def setGridEnabled(self, enabled):
self.m_graph.activeTheme().setGridEnabled(enabled)
def toggleItemCount(self):
if self.m_itemCount == self.numberOfItems:
self.m_itemCount = self.lowerNumberOfItems
self.m_curveDivider = self.lowerCurveDivider
else:
self.m_itemCount = self.numberOfItems
self.m_curveDivider = self.curveDivider
self.m_graph.seriesList()[0].dataProxy().resetArray(None)
self.addData()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
graph = Q3DScatter()
container = QWidget.createWindowContainer(graph)
screenSize = graph.screen().size()
container.setMinimumSize(
QSize(screenSize.width() / 2, screenSize.height() / 1.5))
container.setMaximumSize(screenSize)
container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
container.setFocusPolicy(Qt.StrongFocus)
widget = QWidget()
hLayout = QHBoxLayout(widget)
vLayout = QVBoxLayout()
hLayout.addWidget(container, 1)
hLayout.addLayout(vLayout)
widget.setWindowTitle(Tr.get("A Cosine Wave", "A Cosine Wave"))
themeList = QComboBox()
themeList.addItem("Qt")
themeList.addItem("Primary Colors")
themeList.addItem("Digia")
themeList.addItem("Stone Moss")
themeList.addItem("Army Blue")
themeList.addItem("Retro")
themeList.addItem("Ebony")
themeList.addItem("Isabelle")
themeList.setCurrentIndex(6)
labelButton = QPushButton(Tr.get("Change label style", "Change label style"))
smoothCheckBox = QCheckBox(Tr.get("Smooth dots", "Smooth dots"), checked=True)
itemStyleList = QComboBox()
itemStyleList.addItem("Sphere", QAbstract3DSeries.MeshSphere)
itemStyleList.addItem("Cube", QAbstract3DSeries.MeshCube)
itemStyleList.addItem("Minimal", QAbstract3DSeries.MeshMinimal)
itemStyleList.addItem("Point", QAbstract3DSeries.MeshPoint)
itemStyleList.setCurrentIndex(0)
cameraButton = QPushButton(Tr.get("Change camera preset", "Change camera preset"))
itemCountButton = QPushButton(Tr.get("Toggle item count", "Toggle item count"))
backgroundCheckBox = QCheckBox(Tr.get("Show background", "Show background"), checked=True)
gridCheckBox = QCheckBox(Tr.get("Show grid", "Show grid"), checked=True)
shadowQuality = QComboBox()
shadowQuality.addItem("None")
shadowQuality.addItem("Low")
shadowQuality.addItem("Medium")
shadowQuality.addItem("High")
shadowQuality.addItem("Low Soft")
shadowQuality.addItem("Medium Soft")
shadowQuality.addItem("High Soft")
shadowQuality.setCurrentIndex(4)
fontList = QFontComboBox()
fontList.setCurrentFont(QFont('Arial'))
vLayout.addWidget(labelButton, 0, Qt.AlignTop)
vLayout.addWidget(cameraButton, 0, Qt.AlignTop)
vLayout.addWidget(itemCountButton, 0, Qt.AlignTop)
vLayout.addWidget(backgroundCheckBox)
vLayout.addWidget(gridCheckBox)
vLayout.addWidget(smoothCheckBox, 0, Qt.AlignTop)
vLayout.addWidget(QLabel(Tr.get("Change dot style", "Change dot style")))
vLayout.addWidget(itemStyleList)
vLayout.addWidget(QLabel(Tr.get("Change theme", "Change theme")))
vLayout.addWidget(themeList)
vLayout.addWidget(QLabel(Tr.get("Adjust shadow quality", "Adjust shadow quality")))
vLayout.addWidget(shadowQuality)
vLayout.addWidget(QLabel(Tr.get("Change font", "Change font")))
vLayout.addWidget(fontList, 1, Qt.AlignTop)
modifier = ScatterDataModifier(graph)
cameraButton.clicked.connect(modifier.changePresetCamera)
labelButton.clicked.connect(modifier.changeLabelStyle)
itemCountButton.clicked.connect(modifier.toggleItemCount)
backgroundCheckBox.stateChanged.connect(modifier.setBackgroundEnabled)
gridCheckBox.stateChanged.connect(modifier.setGridEnabled)
smoothCheckBox.stateChanged.connect(modifier.setSmoothDots)
modifier.backgroundEnabledChanged.connect(backgroundCheckBox.setChecked)
modifier.gridEnabledChanged.connect(gridCheckBox.setChecked)
itemStyleList.currentIndexChanged.connect(modifier.changeStyle)
themeList.currentIndexChanged.connect(modifier.changeTheme)
shadowQuality.currentIndexChanged.connect(modifier.changeShadowQuality)
modifier.shadowQualityChanged.connect(shadowQuality.setCurrentIndex)
graph.shadowQualityChanged.connect(modifier.shadowQualityUpdatedByVisual)
fontList.currentFontChanged.connect(modifier.changeFont)
modifier.fontChanged.connect(fontList.setCurrentFont)
widget.show()
sys.exit(app.exec_())