首頁>資訊>

簡介

在本文中,我們將演示如何繪製繪製一個三維柱狀圖,並結合使用GUI部件來控制柱狀圖的繪製引數。本文的示例演示了:

使用Q3DBars和一些部件建立應用程式;使用QBar3DSeries和QBarDataProxy將資料設定為圖形;使用部件控制元件調整一些圖形和序列的屬性;透過單擊軸標籤選擇行或列;負的數值如何影響圖形繪製。GraphModifer類

定義GraphModifer類來設定圖形序列資料,座標軸, 相機和縮放參數等,並實現對圖形的控制方法。這些控制方法包括:

changeRange(self, range): 改變年度座標的範圍。changeStyle(self, style): 改變圖形的網格樣式。changePresetCamera(self): 改變預置相機。changeTheme(self, theme): 改變圖形主題樣式。changeLabelBackground(self): 啟用/禁用標籤的背景。changeSelectionMode(self, selectionMode):改變圖形的選擇模式。changeFont(self, font): 改變標籤字型。changeFontSize(self, fontsize): 改變標籤字型的尺寸。changeLabelRotation(self, rotation): 對座標軸進行旋轉。setAxisTitleVisibility(self, enabled):設定座標軸的標籤可見還是隱藏。setAxisTitleFixed(self, enabled): 是否固定座標軸的標籤。zoomToSelectedBar(self): 縮放選中的柱狀條。changeShadowQuality(self, quality):陰影質量控制。rotateX(self, rotation):繞X軸旋轉。rotateY(self, rotation):繞Y軸旋轉。使用部件控制圖形繪製

根據GraphModifer實現的控制方法,在主介面中新增控制部件,實現對三維柱狀圖繪製的互動控制,這些互動功能包括:

旋轉圖形;修改標籤樣式;預設相機控制;背景是否可見;網格是否可見;控制柱狀條的陰影平滑度;是否顯示第二個柱狀條序列。座標軸標題是否可見及旋轉控制。控制顯示的資料範圍。控制柱狀圖的顯示主題方式。控制柱狀條的顯示風格。控制選擇方式。控制陰影質量。控制字型和字型大小。控制座標軸的旋轉。圖形縮放顯示。示例程式碼

程式程式碼為GraphModifer類的實現和主程式控制兩部分,其程式碼分別如下:

GraphModifer類 實現部分(graphmodifier.py):

import mathfrom PyQt5.QtCore import QObject,QPropertyAnimation, pyqtSignal, QByteArrayfrom PyQt5.QtGui import QFont, QVector3Dfrom PyQt5.QtDataVisualization import (Q3DBars, QBar3DSeries, QBarDataProxy, QAbstract3DSeries,                                       QValue3DAxis, QCategory3DAxis, QAbstract3DGraph,                                        Q3DCamera, QBarDataItem) class GraphModifer(QObject):    shadowQualityChanged = pyqtSignal(int)    backgroundEnabledChanged = pyqtSignal(bool)    gridEnabledChanged = pyqtSignal(bool)    fontChanged = pyqtSignal(QFont)    fontSizeChanged = pyqtSignal(int)        def __init__(self, bargraph):        super(GraphModifer, self).__init__()         self.animationCameraX = QPropertyAnimation()        self.animationCameraY = QPropertyAnimation()        self.animationCameraZoom = QPropertyAnimation()        self.animationCameraTarget = QPropertyAnimation()         self.preset = Q3DCamera.CameraPresetFront         self.graph = bargraph        self.xRotation = 0.0        self.yRotation = 0.0        self.fontSize = 30        self.segments = 4        self.subSegments = 3        self.minVal = -20.0        self.maxVal = 20.0                self.temperatureAxis = QValue3DAxis()        self.yearAxis = QCategory3DAxis()        self.monthAxis = QCategory3DAxis()        self.primarySeries = QBar3DSeries()        self.secondarySeries = QBar3DSeries()                self.barMesh = QAbstract3DSeries.MeshBevelBar        self.smooth = False                self.graph.setShadowQuality(QAbstract3DGraph.ShadowQualitySoftMedium)        self.graph.activeTheme().setBackgroundEnabled(False)        self.graph.activeTheme().setFont(QFont('Times New Roman', self.fontSize))        self.graph.activeTheme().setLabelBackgroundEnabled(True)        self.graph.setMultiSeriesUniform(True)                #self.months = ['January', 'February', 'March', 'April', 'May', 'June',        #               'July', 'August', 'September', 'October', 'November', 'December']        self.months = ['一月', '二月', '三月', '四月', '五月', '六月',                       '七月', '八月', '九月', '十月', '十一月', '十二月']        self.years = ['2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013']                self.temperatureAxis.setTitle('平均氣溫')        self.temperatureAxis.setSegmentCount(self.segments)        self.temperatureAxis.setSubSegmentCount(self.subSegments)        self.temperatureAxis.setRange(self.minVal, self.maxVal)        self.temperatureAxis.setLabelFormat('%.1f ' + '\u00b0'+'C')        self.temperatureAxis.setLabelAutoRotation(30.0)        self.temperatureAxis.setTitleVisible(True)                self.yearAxis.setTitle('年')        self.yearAxis.setLabelAutoRotation(30.0)        self.yearAxis.setTitleVisible(True)        self.monthAxis.setTitle('月')        self.monthAxis.setLabelAutoRotation(30.0)        self.monthAxis.setTitleVisible(True)                self.graph.setValueAxis(self.temperatureAxis)        self.graph.setRowAxis(self.yearAxis)        self.graph.setColumnAxis(self.monthAxis)                self.graph.setValueAxis(self.temperatureAxis)        self.graph.setRowAxis(self.yearAxis)        self.graph.setColumnAxis(self.monthAxis)                self.primarySeries.setItemLabelFormat('Oulu - @colLabel @rowLabel: @valueLabel')        self.primarySeries.setMesh(QAbstract3DSeries.MeshBevelBar)        self.primarySeries.setMeshSmooth(False)                self.secondarySeries.setItemLabelFormat('Helsinki - @colLabel @rowLabel: @valueLabel')        self.secondarySeries.setMesh(QAbstract3DSeries.MeshBevelBar)        self.secondarySeries.setMeshSmooth(False)        self.secondarySeries.setVisible(False)                self.graph.addSeries(self.primarySeries)        self.graph.addSeries(self.secondarySeries)                self.changePresetCamera()                self.resetTemperatureData()                # 設定屬性動畫以縮放到所選的欄        camera = self.graph.scene().activeCamera()        self.defaultAngleX = camera.xRotation()        self.defaultAngleY = camera.yRotation()        self.defaultZoom = camera.zoomLevel()        self.defaultTarget = camera.target()               self.animationCameraX.setTargetObject(camera)        self.animationCameraY.setTargetObject(camera)        self.animationCameraZoom.setTargetObject(camera)        self.animationCameraTarget.setTargetObject(camera)         self.animationCameraX.setPropertyName(bytes('xRotation', 'ascii'))        self.animationCameraY.setPropertyName(bytes('yRotation', 'ascii'))        self.animationCameraZoom.setPropertyName(bytes('zoomLevel', 'ascii'))        self.animationCameraTarget.setPropertyName(bytes('target', 'ascii'))                duration = 1700        self.animationCameraX.setDuration(duration)        self.animationCameraY.setDuration(duration)        self.animationCameraZoom.setDuration(duration)        self.animationCameraTarget.setDuration(duration)                zoomOutFraction = 0.3        self.animationCameraX.setKeyValueAt(zoomOutFraction, 0.0)        self.animationCameraY.setKeyValueAt(zoomOutFraction, 90.0)        self.animationCameraZoom.setKeyValueAt(zoomOutFraction, 50.0)        self.animationCameraTarget.setKeyValueAt(zoomOutFraction, QVector3D(0.0, 0.0, 0.0))                    def resetTemperatureData(self):        tempOulu = [            [-6.7, -11.7, -9.7, 3.3, 9.2, 14.0, 16.3, 17.8, 10.2, 2.1, -2.6, -0.3],    # 2006            [-6.8, -13.3, 0.2, 1.5, 7.9, 13.4, 16.1, 15.5, 8.2, 5.4, -2.6, -0.8],      # 2007            [-4.2, -4.0, -4.6, 1.9, 7.3, 12.5, 15.0, 12.8, 7.6, 5.1, -0.9, -1.3],      # 2008            [-7.8, -8.8, -4.2, 0.7, 9.3, 13.2, 15.8, 15.5, 11.2, 0.6, 0.7, -8.4],      # 2009            [-14.4, -12.1, -7.0, 2.3, 11.0, 12.6, 18.8, 13.8, 9.4, 3.9, -5.6, -13.0],  # 2010            [-9.0, -15.2, -3.8, 2.6, 8.3, 15.9, 18.6, 14.9, 11.1, 5.3, 1.8, -0.2],     # 2011            [-8.7, -11.3, -2.3, 0.4, 7.5, 12.2, 16.4, 14.1, 9.2, 3.1, 0.3, -12.1],     # 2012            [-7.9, -5.3, -9.1, 0.8, 11.6, 16.6, 15.9, 15.5, 11.2, 4.0, 0.1, -1.9]      # 2013        ]                tempHelsinki = [            [-3.7, -7.8, -5.4, 3.4, 10.7, 15.4, 18.6, 18.7, 14.3, 8.5, 2.9, 4.1],      # 2006            [-1.2, -7.5, 3.1, 5.5, 10.3, 15.9, 17.4, 17.9, 11.2, 7.3, 1.1, 0.5],       # 2007            [-0.6, 1.2, 0.2, 6.3, 10.2, 13.8, 18.1, 15.1, 10.1, 9.4, 2.5, 0.4],        # 2008            [-2.9, -3.5, -0.9, 4.7, 10.9, 14.0, 17.4, 16.8, 13.2, 4.1, 2.6, -2.3],     # 2009            [-10.2, -8.0, -1.9, 6.6, 11.3, 14.5, 21.0, 18.8, 12.6, 6.1, -0.5, -7.3],   # 2010            [-4.4, -9.1, -2.0, 5.5, 9.9, 15.6, 20.8, 17.8, 13.4, 8.9, 3.6, 1.5],       # 2011            [-3.5, -3.2, -0.7, 4.0, 11.1, 13.4, 17.3, 15.8, 13.1, 6.4, 4.1, -5.1],     # 2012            [-4.8, -1.8, -5.0, 2.9, 12.8, 17.2, 18.0, 17.1, 12.5, 7.5, 4.5, 2.3]       # 2013        ]         #建立資料列表        dataSet = []        dataSet2 = []         for year in range(len(self.years)):            #生成一個數據行            dataRow = [None] * len(self.months)            dataRow2 = [None] * len(self.months)            for month in range(len(self.months)):                #新增一個數據行                dataRow[month] = QBarDataItem(tempOulu[year][month])                dataRow2[month] = QBarDataItem(tempHelsinki[year][month])            #向集合中新增行            dataSet.append(dataRow)            dataSet2.append(dataRow2)         #將資料新增到代理中        self.primarySeries.dataProxy().resetArray(dataSet, self.years, self.months)        self.secondarySeries.dataProxy().resetArray(dataSet2, self.years, self.months)     def changeRange(self, range):        if range >= len(self.years):            self.yearAxis.setRange(0, len(self.years) - 1)        else:            self.yearAxis.setRange(range, range)     def changeStyle(self, style):        combox = self.sender()        if combox:            self.barMesh = QAbstract3DSeries.Mesh(int(combox.itemData(style)))            self.primarySeries.setMesh(self.barMesh)            self.secondarySeries.setMesh(self.barMesh)     def changePresetCamera(self):        self.animationCameraX.stop()        self.animationCameraY.stop()        self.animationCameraZoom.stop()        self.animationCameraTarget.stop()         #如果動畫改變了相機的目標,則恢復回去        self.graph.scene().activeCamera().setTarget(QVector3D(0.0, 0.0, 0.0))         self.graph.scene().activeCamera().setCameraPreset(self.preset)        self.preset += 1        if self.preset > Q3DCamera.CameraPresetDirectlyBelow:            self.preset = Q3DCamera.CameraPresetFrontLow     def changeTheme(self, theme):        currentTheme = self.graph.activeTheme()        currentTheme.setType(theme)        self.backgroundEnabledChanged.emit(currentTheme.isBackgroundEnabled())        self.gridEnabledChanged.emit(currentTheme.isGridEnabled())        self.fontChanged.emit(currentTheme.font())        self.fontSizeChanged.emit(currentTheme.font().pointSize())     def changeLabelBackground(self):        self.graph.activeTheme().setLabelBackgroundEnabled(not self.graph.activeTheme().isLabelBackgroundEnabled())     def changeSelectionMode(self, selectionMode):        comboBox = self.sender()        if comboBox:            flags = comboBox.itemData(selectionMode)            self.graph.setSelectionMode(QAbstract3DGraph.SelectionFlags(flags))     def changeFont(self, font):        self.graph.activeTheme().setFont(font)     def changeFontSize(self, fontsize):        self.fontSize = fontsize        font = self.graph.activeTheme().font()        font.setPointSize(fontsize)        self.graph.activeTheme().setFont(font)     def shadowQualityUpdatedByVisual(self, sq):        self.shadowQualityChanged.emit(sq)     def changeLabelRotation(self, rotation):        self.temperatureAxis.setLabelAutoRotation(rotation)        self.monthAxis.setLabelAutoRotation(rotation)        self.yearAxis.setLabelAutoRotation(rotation)     def setAxisTitleVisibility(self, enabled):        self.temperatureAxis.setTitleVisible(enabled)        self.monthAxis.setTitleVisible(enabled)        self.yearAxis.setTitleVisible(enabled)     def setAxisTitleFixed(self, enabled):        self.temperatureAxis.setTitleFixed(enabled)        self.monthAxis.setTitleFixed(enabled)        self.yearAxis.setTitleFixed(enabled)     def zoomToSelectedBar(self):        self.animationCameraX.stop()        self.animationCameraY.stop()        self.animationCameraZoom.stop()        self.animationCameraTarget.stop()         camera = self.graph.scene().activeCamera()        currentX = camera.xRotation()        currentY = camera.yRotation()        currentZoom = camera.zoomLevel()        currentTarget = camera.target()         self.animationCameraX.setStartValue(currentX)        self.animationCameraY.setStartValue(currentY)        self.animationCameraZoom.setStartValue(currentZoom)        self.animationCameraTarget.setStartValue(currentTarget)         if self.graph.selectedSeries():            selectedBar = self.graph.selectedSeries().selectedBar()        else:            selectedBar = QBar3DSeries.invalidSelectionPosition()         if selectedBar != QBar3DSeries.invalidSelectionPosition():            #根據座標軸的範圍對選中的柱形條做歸一化處理以確定目標座標            xMin = self.graph.columnAxis().min()            xRange = self.graph.columnAxis().max() - xMin            zMin  = self.graph.rowAxis().min()            zRange = self.graph.rowAxis().max() - zMin            endTarget = QVector3D()            endTarget.setX((selectedBar.y() - xMin) / xRange * 2.0 - 1.0)            endTarget.setZ((selectedBar.x() - zMin) / zRange * 2.0 - 1.0)             #旋轉像機,使其始終近似地指向圖形中心            endAngleX = 90.0 - math.atan2(endTarget.z(), endTarget.x()) * 180.0 / math.pi            if endTarget.x() > 0.0:                endAngleX -= 180.0            barValue = self.graph.selectedSeries().dataProxy().itemAt(selectedBar.x(), selectedBar.y()).value()            if barValue >= 0.0:                endAngleY = 30.0            else:                endAngleY = -30.0            if self.graph.valueAxis().reversed():                endAngleY *= 1.0             self.animationCameraX.setEndValue(endAngleX)            self.animationCameraY.setEndValue(endAngleY)            self.animationCameraZoom.setEndValue(250.0)            self.animationCameraTarget.setEndValue(endTarget)        else:            #未選擇柱狀條,設定為預設值            self.animationCameraX.setEndValue(self.defaultAngleX)            self.animationCameraY.setEndValue(self.defaultAngleY)            self.animationCameraZoom.setEndValue(self.defaultZoom)            self.animationCameraTarget.setEndValue(self.defaultTarget)         self.animationCameraX.start()        self.animationCameraY.start()        self.animationCameraZoom.start()        self.animationCameraTarget.start()     def changeShadowQuality(self, quality):        sq = QAbstract3DGraph.ShadowQuality(quality)        self.graph.setShadowQuality(sq)        self.shadowQualityChanged.emit(quality)     def rotateX(self, rotation):        self.xRotation = rotation        self.graph.scene().activeCamera().setCameraPosition(self.xRotation, self.yRotation)     def rotateY(self, rotation):        self.yRotation = rotation        self.graph.scene().activeCamera().setCameraPosition(self.xRotation, self.yRotation)        def setBackgroundEnabled(self, enabled):        self.graph.activeTheme().setBackgroundEnabled(enabled)     def setGridEnabled(self, enabled):        self.graph.activeTheme().setGridEnabled(enabled)     def setSmoothBars(self, smooth):        self.primarySeries.setMeshSmooth(smooth)        self.secondarySeries.setMeshSmooth(smooth)     def setSeriesVisibility(self, enabled:int):        self.secondarySeries.setVisible(enabled)     def setReverseValueAxis(self, enabled):        self.graph.valueAxis().setReversed(enabled)     def setReflection(self, enabled):        self.graph.setReflection(enabled) 

主程式部分:

import sysfrom PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtCore import Qt, QSizefrom PyQt5.QtGui import QFontfrom PyQt5.QtWidgets import (QApplication, QWidget, QMessageBox, QSizePolicy,                            QHBoxLayout, QVBoxLayout, QComboBox, QPushButton,                            QCheckBox, QSlider, QFontComboBox, QLabel)from PyQt5.QtDataVisualization import (Q3DBars, QAbstract3DSeries, QAbstract3DGraph) from graphmodifier import GraphModifer class DemoWidget(QWidget):    def __init__(self, parent=None):        super(DemoWidget, self).__init__(parent)                    # 設定視窗標題        self.setWindowTitle('實戰 Qt for Python: 城市平均溫度視覺化演示')              # 設定視窗大小        self.resize(640, 480)              self.initUi()            def initUi(self):        widgetgraph  = Q3DBars()        container = QWidget.createWindowContainer(widgetgraph)         if not widgetgraph.hasContext():            msgBox = QMessageBox()            msgBox.setText('不能初始化OpenGL上下文')            msgBox.exec()            return;         screenSize = widgetgraph.screen().size()        container.setMinimumSize(QSize(int(screenSize.width() / 2.0), int(screenSize.height() / 1.5)))        container.setMaximumSize(screenSize)        container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)        container.setFocusPolicy(Qt.StrongFocus)         hLayout = QHBoxLayout()        vLayout = QVBoxLayout()        hLayout.addWidget(container, 1) #左邊繪圖部分        hLayout.addLayout(vLayout)      #右邊控制部分         #圖表主題控制        themeList = QComboBox(self)        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(0)         labelButton = QPushButton(self)        labelButton.setText('改變標籤樣式')         smoothCheckBox  = QCheckBox(self)        smoothCheckBox.setText('平滑柱狀條')        smoothCheckBox.setChecked(False)         #柱狀條樣式        barStyleList = QComboBox(self)        barStyleList.addItem('Bar', int(QAbstract3DSeries.MeshBar))        barStyleList.addItem('Pyramid', int(QAbstract3DSeries.MeshPyramid))        barStyleList.addItem('Cone', int(QAbstract3DSeries.MeshCone))        barStyleList.addItem('Cylinder', int(QAbstract3DSeries.MeshCylinder))        barStyleList.addItem('Bevel bar', int(QAbstract3DSeries.MeshBevelBar))        barStyleList.addItem('Sphere', int(QAbstract3DSeries.MeshSphere))        barStyleList.setCurrentIndex(4)         cameraButton = QPushButton(self)        cameraButton.setText('改變相機設定')         zoomToSelectedButton  = QPushButton(self)        zoomToSelectedButton.setText('縮放選擇的柱狀條')         #選擇模式列表        selectionModeList = QComboBox(self)        selectionModeList.addItem('None', int(QAbstract3DGraph.SelectionNone))        selectionModeList.addItem('Bar', int(QAbstract3DGraph.SelectionItem))        selectionModeList.addItem('Row', int(QAbstract3DGraph.SelectionRow))        selectionModeList.addItem('Bar and Row', int(QAbstract3DGraph.SelectionItemAndRow))        selectionModeList.addItem('Column', int(QAbstract3DGraph.SelectionColumn))        selectionModeList.addItem('Bar and Column', int(QAbstract3DGraph.SelectionItemAndColumn))        selectionModeList.addItem('Row and Column', int(QAbstract3DGraph.SelectionRowAndColumn))        selectionModeList.addItem('Bar, Row and Column', int(QAbstract3DGraph.SelectionItemRowAndColumn))        selectionModeList.addItem('Slice into Row', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionRow))        selectionModeList.addItem('"Slice into Row and Item', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionItemAndRow))        selectionModeList.addItem('Slice into Column', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionColumn))        selectionModeList.addItem('Slice into Column and Item', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionItemAndColumn))        selectionModeList.addItem('Multi: Bar, Row, Col', int(QAbstract3DGraph.SelectionItemRowAndColumn | QAbstract3DGraph.SelectionMultiSeries))        selectionModeList.addItem('Multi, Slice: Row, Item', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionItemAndRow | QAbstract3DGraph.SelectionMultiSeries))        selectionModeList.addItem('Multi, Slice: Col, Item', int(QAbstract3DGraph.SelectionSlice | QAbstract3DGraph.SelectionItemAndColumn | QAbstract3DGraph.SelectionMultiSeries))        selectionModeList.setCurrentIndex(1)         backgroundCheckBox = QCheckBox(self)        backgroundCheckBox.setText('顯示背景')        backgroundCheckBox.setChecked(False)         gridCheckBox = QCheckBox(self)        gridCheckBox.setText('顯示網格')        gridCheckBox.setChecked(True)         seriesCheckBox  = QCheckBox(self)        seriesCheckBox.setText('顯示第二個序列')        seriesCheckBox.setChecked(False)         reverseValueAxisCheckBox = QCheckBox(self)        reverseValueAxisCheckBox.setText('翻轉數值座標軸')        reverseValueAxisCheckBox.setChecked(False)         reflectionCheckBox = QCheckBox(self)        reflectionCheckBox.setText('顯示反射')        reflectionCheckBox.setChecked(False)         #旋轉         rotationSliderX = QSlider(Qt.Horizontal, self)        rotationSliderX.setTickInterval(30)        rotationSliderX.setTickPosition(QSlider.TicksBelow)        rotationSliderX.setMinimum(-180)        rotationSliderX.setValue(0)        rotationSliderX.setMaximum(180)        rotationSliderY = QSlider(Qt.Horizontal, self)        rotationSliderY.setTickInterval(15)        rotationSliderY.setTickPosition(QSlider.TicksAbove)        rotationSliderY.setMinimum(-90)        rotationSliderY.setValue(0)        rotationSliderY.setMaximum(90)         fontSizeSlider = QSlider(Qt.Horizontal, self)        fontSizeSlider.setTickInterval(10)        fontSizeSlider.setTickPosition(QSlider.TicksBelow)        fontSizeSlider.setMinimum(1)        fontSizeSlider.setValue(30)        fontSizeSlider.setMaximum(100)         fontList = QFontComboBox(self)        fontList.setCurrentFont(QFont('Times New Roman'))         #陰影質量        shadowQuality = QComboBox(self)        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(5)         #範圍選擇        rangeList = QComboBox(self)        rangeList.addItem('2006')        rangeList.addItem('2007')        rangeList.addItem('2008')        rangeList.addItem('2009')        rangeList.addItem('2010')        rangeList.addItem('2011')        rangeList.addItem('2012')        rangeList.addItem('2013')        rangeList.addItem('All')        rangeList.setCurrentIndex(8)         axisTitlesVisibleCB = QCheckBox(self)        axisTitlesVisibleCB.setText('座標軸標籤可見')        axisTitlesVisibleCB.setChecked(True)         axisTitlesFixedCB = QCheckBox(self)        axisTitlesFixedCB.setText('座標軸標籤固定')        axisTitlesFixedCB.setChecked(True)         axisLabelRotationSlider = QSlider(Qt.Horizontal, self)        axisLabelRotationSlider.setTickInterval(10)        axisLabelRotationSlider.setTickPosition(QSlider.TicksBelow)        axisLabelRotationSlider.setMinimum(0)        axisLabelRotationSlider.setValue(30)        axisLabelRotationSlider.setMaximum(90)         vLayout.addWidget(QLabel('水平旋轉'))        vLayout.addWidget(rotationSliderX, 0, Qt.AlignTop)        vLayout.addWidget(QLabel('垂直旋轉'))        vLayout.addWidget(rotationSliderY, 0, Qt.AlignTop)        vLayout.addWidget(labelButton, 0, Qt.AlignTop)        vLayout.addWidget(cameraButton, 0, Qt.AlignTop)        vLayout.addWidget(zoomToSelectedButton, 0, Qt.AlignTop)        vLayout.addWidget(backgroundCheckBox)        vLayout.addWidget(gridCheckBox)        vLayout.addWidget(smoothCheckBox)        vLayout.addWidget(reflectionCheckBox)        vLayout.addWidget(seriesCheckBox)        vLayout.addWidget(reverseValueAxisCheckBox)        vLayout.addWidget(axisTitlesVisibleCB)        vLayout.addWidget(axisTitlesFixedCB)        vLayout.addWidget(QLabel('顯示年份'))        vLayout.addWidget(rangeList)        vLayout.addWidget(QLabel('改變柱狀條樣式'))        vLayout.addWidget(barStyleList)        vLayout.addWidget(QLabel('改變選擇模式'))        vLayout.addWidget(selectionModeList)        vLayout.addWidget(QLabel('改變主題'))        vLayout.addWidget(themeList)        vLayout.addWidget(QLabel('調整陰影質量'))        vLayout.addWidget(shadowQuality)        vLayout.addWidget(QLabel('改變字型'))        vLayout.addWidget(fontList)        vLayout.addWidget(QLabel('調整字型尺寸'))        vLayout.addWidget(fontSizeSlider)        vLayout.addWidget(QLabel('旋轉座標軸標籤'))        vLayout.addWidget(axisLabelRotationSlider, 1, Qt.AlignTop)         self.modifier = GraphModifer(widgetgraph)         rotationSliderX.valueChanged.connect(self.modifier.rotateX)        rotationSliderY.valueChanged.connect(self.modifier.rotateY)                labelButton.clicked.connect(self.modifier.changeLabelBackground)        cameraButton.clicked.connect(self.modifier.changePresetCamera)        zoomToSelectedButton.clicked.connect(self.modifier.zoomToSelectedBar)         backgroundCheckBox.stateChanged.connect(self.modifier.setBackgroundEnabled)        gridCheckBox.stateChanged.connect(self.modifier.setGridEnabled)        smoothCheckBox.stateChanged.connect(self.modifier.setSmoothBars)        seriesCheckBox.stateChanged.connect(self.modifier.setSeriesVisibility)        reverseValueAxisCheckBox.stateChanged.connect(self.modifier.setReverseValueAxis)        reflectionCheckBox.stateChanged.connect(self.modifier.setReflection)         self.modifier.backgroundEnabledChanged.connect(backgroundCheckBox.setChecked)        self.modifier.gridEnabledChanged.connect(gridCheckBox.setChecked)         rangeList.currentIndexChanged.connect(self.modifier.changeRange)        barStyleList.currentIndexChanged.connect(self.modifier.changeStyle)        selectionModeList.currentIndexChanged.connect(self.modifier.changeSelectionMode)        themeList.currentIndexChanged.connect(self.modifier.changeTheme)        shadowQuality.currentIndexChanged.connect(self.modifier.changeShadowQuality)         self.modifier.shadowQualityChanged.connect(shadowQuality.setCurrentIndex)        widgetgraph.shadowQualityChanged.connect(self.modifier.shadowQualityUpdatedByVisual)         fontSizeSlider.valueChanged.connect(self.modifier.changeFontSize)        fontList.currentFontChanged.connect(self.modifier.changeFont)         self.modifier.fontSizeChanged.connect(fontSizeSlider.setValue)        self.modifier.fontChanged.connect(fontList.setCurrentFont)         axisTitlesVisibleCB.stateChanged.connect(self.modifier.setAxisTitleVisibility)        axisTitlesFixedCB.stateChanged.connect(self.modifier.setAxisTitleFixed)        axisLabelRotationSlider.valueChanged.connect(self.modifier.changeLabelRotation)         self.setLayout(hLayout)     if __name__ == '__main__':    app = QApplication(sys.argv)    window = DemoWidget()    window.show()    sys.exit(app.exec())   

最終執行結果如下圖:

7
最新評論
  • 購得日本70萬平方公尺小島的中國女子是誰?
  • 熊絨做的保暖衣,薄薄一件好暖和,極地工作者都青睞