QML PieSeries 自定义模型与自定义数据

huangapple go评论102阅读模式
英文:

QML PieSeries custom model with custom data

问题

我想加载一些自定义数据(不仅仅是标签和大小,还有其他我需要的内容)。比如说,我想要从模型中加载每个切片的颜色。如何访问“第三列”值 - “黑色”或“白色”,并让 QML 使用它?
这是我有的代码:

main.py:

  1. import sys
  2. from PyQt5 import QtCore, QtWidgets, QtQuick
  3. import custom_model
  4. if __name__ == '__main__':
  5. app = QtWidgets.QApplication(sys.argv)
  6. view = QtQuick.QQuickView()
  7. outer_ring_model = custom_model.OuterRingModel()
  8. view.rootContext().setContextProperty('outerRingModel', outer_ring_model)
  9. view.setSource(QtCore.QUrl("main.qml"))
  10. view.show()
  11. sys.exit(app.exec_())

custom_model.py:

  1. from PyQt5 import QtCore
  2. class OuterRingModel(QtCore.QAbstractTableModel):
  3. def __init__(self, parent=None):
  4. super().__init__(parent)
  5. self.column_count = 2
  6. self.row_count = 100
  7. self.data = []
  8. i = 0
  9. while i < (self.row_count / 2):
  10. self.data.append(['Black', 50, 'black'])
  11. self.data.append(['White', 50, 'white'])
  12. i += 1
  13. def rowCount(self, parent):
  14. return len(self.data)
  15. def columnCount(self, parent):
  16. return self.column_count
  17. def data(self, index, role):
  18. if role == QtCore.Qt.DisplayRole:
  19. return self.data[index.row()][index.column()]
  20. elif role == QtCore.Qt.EditRole:
  21. return self.data[index.row()][index.column()]
  22. elif role == QtCore.Qt.BackgroundRole:
  23. return QtGui.QColor(QtCore.Qt.white)
  24. return QtCore.QVariant()

main.qml:

  1. import QtQuick 2.7
  2. import QtQuick.Window 2.0
  3. import QtQuick.Controls 1.4
  4. import QtCharts 2.1
  5. Grid {
  6. id: grid1
  7. width: 1024
  8. height: 600
  9. spacing: 10
  10. rows: 1
  11. columns: 2
  12. Component.onCompleted: { update() }
  13. ChartView {
  14. id: chart
  15. width: 600
  16. height: 600
  17. antialiasing: true
  18. animationDuration: 1000
  19. animationOptions: ChartView.AllAnimations
  20. title: "MyTitle"
  21. legend.visible: false
  22. PieSeries {
  23. id: serie0
  24. name: "Outer Ring"
  25. size: 0.75
  26. holeSize: 0.7
  27. onSliceAdded: {
  28. slice.color = Qt.lighter("red", 1.5)
  29. // slice.color = 如何在此处导入模型数据
  30. }
  31. VPieModelMapper {
  32. id: model0
  33. model: outerRingModel
  34. labelsColumn: 0
  35. valuesColumn: 1
  36. firstRow: 0
  37. rowCount: 100
  38. }
  39. }
  40. }
  41. }
英文:

I want to load some custom data (not Just label and size, but something else I need too). Let say - I want to load every slice's color out of the model too. How can I access the "third column" value - "black" or "white" and make QML to use it?
This is the code I have:

main.py:

  1. import sys
  2. from PyQt5 import QtCore, QtWidgets, QtQuick
  3. import custom_model
  4. if __name__ == &#39;__main__&#39;:
  5. app = QtWidgets.QApplication( sys.argv )
  6. view = QtQuick.QQuickView()
  7. outer_ring_model = custom_model.OuterRingModel()
  8. view.rootContext().setContextProperty( &#39;outerRingModel&#39;, outer_ring_model )
  9. view.setSource( QtCore.QUrl( &quot;main.qml&quot; ) )
  10. view.show()
  11. sys.exit( app.exec_() )

custom_model.py:

  1. from PyQt5 import QtCore
  2. class OuterRingModel( QtCore.QAbstractTableModel ):
  3. def __init__( self, parent=None ):
  4. super().__init__( parent )
  5. self.column_count = 2
  6. self.row_count = 100
  7. self.data = []
  8. i = 0
  9. while i &lt; (self.row_count / 2):
  10. self.data.append([&#39;Black&#39;, 50, &#39;black&#39;])
  11. self.data.append([&#39;White&#39;, 50, &#39;white&#39;])
  12. i += 1
  13. def rowCount( self, parent ):
  14. return len( self.data )
  15. def columnCount( self, parent ):
  16. return self.column_count
  17. def data( self, index, role ):
  18. if role == QtCore.Qt.DisplayRole:
  19. return self.data[ index.row() ][ index.column() ]
  20. elif role == QtCore.Qt.EditRole:
  21. return self.data[ index.row() ][ index.column() ]
  22. elif role == QtCore.Qt.BackgroundRole:
  23. return QtGui.QColor( QtCore.Qt.white )
  24. return QtCore.QVariant()

main.qml:

  1. import QtQuick 2.7
  2. import QtQuick.Window 2.0
  3. import QtQuick.Controls 1.4
  4. import QtCharts 2.1
  5. Grid {
  6. id: grid1
  7. width: 1024
  8. height: 600
  9. spacing: 10
  10. rows: 1
  11. columns: 2
  12. Component.onCompleted: { update() }
  13. ChartView {
  14. id: chart
  15. width: 600
  16. height: 600
  17. antialiasing: true
  18. animationDuration: 1000
  19. animationOptions: ChartView.AllAnimations
  20. title: &quot;MyTitle&quot;
  21. legend.visible: false
  22. PieSeries {
  23. id: serie0
  24. name: &quot;Outer Ring&quot;
  25. size: 0.75
  26. holeSize: 0.7
  27. onSliceAdded: {
  28. slice.color = Qt.lighter(&quot;red&quot;, 1.5)
  29. // slice.color = HOW_TO_IMPORT_MODEL_DATA_HERE
  30. }
  31. VPieModelMapper {
  32. id: model0
  33. model: outerRingModel
  34. labelsColumn: 0
  35. valuesColumn: 1
  36. firstRow: 0
  37. rowCount: 100
  38. }
  39. }
  40. }
  41. }

答案1

得分: 2

以下是您要翻译的代码部分:

  1. What you require cannot be implemented in QML since you cannot know the index associated with the slice so you will have to implement that logic in Python/C++. In addition, your model has errors that I have already corrected.
  2. **main.py**
  3. ```python
  4. import os
  5. import sys
  6. from PyQt5 import QtCore, QtGui, QtWidgets, QtQuick, QtChart
  7. import custom_model
  8. class Manager(QtCore.QObject):
  9. @QtCore.pyqtSlot(
  10. QtChart.QPieSeries, QtChart.QPieSlice, QtCore.QAbstractItemModel, int
  11. )
  12. def updateSlice(self, serie, sl, model, firstRow):
  13. row = firstRow + serie.slices().index(sl)
  14. index = model.index(row, 2)
  15. color = model.data(index) or &quot;&quot;
  16. sl.setColor(QtGui.QColor(color))
  17. if __name__ == &quot;__main__&quot;:
  18. app = QtWidgets.QApplication(sys.argv)
  19. view = QtQuick.QQuickView()
  20. manager = Manager()
  21. outer_ring_model = custom_model.OuterRingModel()
  22. view.rootContext().setContextProperty(&quot;manager&quot;, manager)
  23. view.rootContext().setContextProperty(&quot;outerRingModel&quot;, outer_ring_model)
  24. filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), &quot;main.qml&quot;)
  25. view.setSource(QtCore.QUrl.fromLocalFile(filename))
  26. view.show()
  27. sys.exit(app.exec_())

custom_model.py

  1. from PyQt5 import QtCore
  2. class OuterRingModel(QtCore.QAbstractTableModel):
  3. def __init__(self, parent=None):
  4. super().__init__(parent)
  5. self.column_count = 3
  6. self._data = []
  7. for i in range(50):
  8. self._data.append([&quot;Black&quot;, 50, &quot;black&quot;])
  9. self._data.append([&quot;White&quot;, 50, &quot;white&quot;])
  10. def rowCount(self, parent):
  11. return len(self._data)
  12. def columnCount(self, parent):
  13. return self.column_count
  14. def data(self, index, role=QtCore.Qt.DisplayRole):
  15. if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole,):
  16. return self._data[index.row()][index.column()]

main.qml

  1. import QtQuick 2.7
  2. import QtQuick.Window 2.0
  3. import QtQuick.Controls 1.4
  4. import QtCharts 2.1
  5. Grid {
  6. id: grid1
  7. width: 1024
  8. height: 600
  9. spacing: 10
  10. rows: 1
  11. columns: 2
  12. VPieModelMapper {
  13. id: mapper0
  14. model: outerRingModel
  15. series: serie0
  16. labelsColumn: 0
  17. valuesColumn: 1
  18. firstRow: 0
  19. rowCount: 100
  20. }
  21. ChartView {
  22. id: chart
  23. width: 600
  24. height: 600
  25. antialiasing: true
  26. animationDuration: 1000
  27. animationOptions: ChartView.AllAnimations
  28. title: &quot;MyTitle&quot;
  29. legend.visible: false
  30. PieSeries {
  31. id: serie0
  32. name: &quot;Outer Ring&quot;
  33. size: 0.75
  34. holeSize: 0.7
  35. onSliceAdded: {
  36. manager.updateSlice(mapper0.series, slice, mapper0.model, mapper0.firstRow)
  37. }
  38. }
  39. }
  40. }

QML PieSeries 自定义模型与自定义数据

  1. <details>
  2. <summary>英文:</summary>
  3. What you require cannot be implemented in QML since you cannot know the index associated with the slice so you will have to implement that logic in Python/C++. In addition, your model has errors that I have already corrected.
  4. **main.py**
  5. ```python
  6. import os
  7. import sys
  8. from PyQt5 import QtCore, QtGui, QtWidgets, QtQuick, QtChart
  9. import custom_model
  10. class Manager(QtCore.QObject):
  11. @QtCore.pyqtSlot(
  12. QtChart.QPieSeries, QtChart.QPieSlice, QtCore.QAbstractItemModel, int
  13. )
  14. def updateSlice(self, serie, sl, model, firstRow):
  15. row = firstRow + serie.slices().index(sl)
  16. index = model.index(row, 2)
  17. color = model.data(index) or &quot;&quot;
  18. sl.setColor(QtGui.QColor(color))
  19. if __name__ == &quot;__main__&quot;:
  20. app = QtWidgets.QApplication(sys.argv)
  21. view = QtQuick.QQuickView()
  22. manager = Manager()
  23. outer_ring_model = custom_model.OuterRingModel()
  24. view.rootContext().setContextProperty(&quot;manager&quot;, manager)
  25. view.rootContext().setContextProperty(&quot;outerRingModel&quot;, outer_ring_model)
  26. filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), &quot;main.qml&quot;)
  27. view.setSource(QtCore.QUrl.fromLocalFile(filename))
  28. view.show()
  29. sys.exit(app.exec_())

custom_model.py

  1. from PyQt5 import QtCore
  2. class OuterRingModel(QtCore.QAbstractTableModel):
  3. def __init__(self, parent=None):
  4. super().__init__(parent)
  5. self.column_count = 3
  6. self._data = []
  7. for i in range(50):
  8. self._data.append([&quot;Black&quot;, 50, &quot;black&quot;])
  9. self._data.append([&quot;White&quot;, 50, &quot;white&quot;])
  10. def rowCount(self, parent):
  11. return len(self._data)
  12. def columnCount(self, parent):
  13. return self.column_count
  14. def data(self, index, role=QtCore.Qt.DisplayRole):
  15. if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole,):
  16. return self._data[index.row()][index.column()]

main.qml

  1. import QtQuick 2.7
  2. import QtQuick.Window 2.0
  3. import QtQuick.Controls 1.4
  4. import QtCharts 2.1
  5. Grid {
  6. id: grid1
  7. width: 1024
  8. height: 600
  9. spacing: 10
  10. rows: 1
  11. columns: 2
  12. VPieModelMapper {
  13. id: mapper0
  14. model: outerRingModel
  15. series: serie0
  16. labelsColumn: 0
  17. valuesColumn: 1
  18. firstRow: 0
  19. rowCount: 100
  20. }
  21. ChartView {
  22. id: chart
  23. width: 600
  24. height: 600
  25. antialiasing: true
  26. animationDuration: 1000
  27. animationOptions: ChartView.AllAnimations
  28. title: &quot;MyTitle&quot;
  29. legend.visible: false
  30. PieSeries {
  31. id: serie0
  32. name: &quot;Outer Ring&quot;
  33. size: 0.75
  34. holeSize: 0.7
  35. onSliceAdded: {
  36. manager.updateSlice(mapper0.series, slice, mapper0.model, mapper0.firstRow)
  37. }
  38. }
  39. }
  40. }

QML PieSeries 自定义模型与自定义数据

答案2

得分: 0

以下是翻译好的部分:

我已经成功完成了,没有任何新的实现。

我的切片列表如下所示:

  1. property variant pieArray: [
  2. {
  3. "label":"10",
  4. "value":0.1,
  5. "active":true,
  6. "originalColor":"#ff9900",
  7. "labelColor":"#000000",
  8. "labelFont":"Arial",
  9. "labelPointSize":20,
  10. "borderWidth":6,
  11. "borderColor":"#000000",
  12. "explodeDistanceFactor":0.0,
  13. "exploded":false,
  14. "from":0,
  15. "to":10
  16. }
  17. ]

以下是用于添加饼图和其自定义属性的函数。自定义属性将自动添加,您无需考虑它。

  1. function addPies(pieArr) {
  2. for (var i = 0; i < pieArr.length; i++) {
  3. console.log(pieArr[i]["label"], pieArr[i]["value"]);
  4. pieOuter.append(pieArr[i]["label"], pieArr[i]["value"]);
  5. pieOuter.find(pieArr[i]["label"]).labelPosition = PieSlice.LabelInsideHorizontal;
  6. pieOuter.find(pieArr[i]["label"]).labelVisible = true;
  7. pieOuter.find(pieArr[i]["label"]).labelColor = pieArr[i]["labelColor"];
  8. pieOuter.find(pieArr[i]["label"]).labelFont.family = pieArr[i]["labelFont"];
  9. pieOuter.find(pieArr[i]["label"]).labelFont.pointSize = pieArr[i]["labelPointSize"];
  10. pieOuter.find(pieArr[i]["label"]).borderWidth = pieArr[i]["borderWidth"];
  11. pieOuter.find(pieArr[i]["label"]).borderColor = pieArr[i]["borderColor"];
  12. pieOuter.find(pieArr[i]["label"]).explodeDistanceFactor = pieArr[i]["explodeDistanceFactor"];
  13. pieOuter.find(pieArr[i]["label"]).exploded = pieArr[i]["exploded"];
  14. pieOuter.find(pieArr[i]["label"]).color = pieArr[i]["originalColor"];
  15. pieOuter.find(pieArr[i]["label"]).originalColor = pieArr[i]["originalColor"];
  16. pieOuter.find(pieArr[i]["label"]).active = pieArr[i]["active"];
  17. pieOuter.find(pieArr[i]["label"]).from = pieArr[i]["from"];
  18. pieOuter.find(pieArr[i]["label"]).to = pieArr[i]["to"];
  19. pieOuter.find(pieArr[i]["label"]).to = pieArr[i]["to"];
  20. }
  21. }

然后在Component.onCompleted或任何其他您想要使用的事件中调用它:

  1. Component.onCompleted: {
  2. addPies(pieArray);
  3. }
英文:

I've managed to do it without any new implementations.

My Slice list is something like this:

  1. property variant pieArray: [
  2. {
  3. &quot;label&quot;:&quot;10&quot;,
  4. &quot;value&quot;:0.1,
  5. &quot;active&quot;:true,
  6. &quot;originalColor&quot;:&quot;#ff9900&quot;,
  7. &quot;labelColor&quot;:&quot;#000000&quot;,
  8. &quot;labelFont&quot;:&quot;Arial&quot;,
  9. &quot;labelPointSize&quot;:20,
  10. &quot;borderWidth&quot;:6,
  11. &quot;borderColor&quot;:&quot;#000000&quot;,
  12. &quot;explodeDistanceFactor&quot;:0.0,
  13. &quot;exploded&quot;:false,
  14. &quot;from&quot;:0,
  15. &quot;to&quot;:10}]

And this is the function to add the pies and it's custom properties. Custom properties are added automatically, you don't have to think about it.

  1. function addPies(pieArr) {
  2. for (var i = 0; i&lt; pieArr.length; i++) {
  3. console.log(pieArr[i][&quot;label&quot;],pieArr[i][&quot;value&quot;]);
  4. pieOuter.append(pieArr[i][&quot;label&quot;],pieArr[i][&quot;value&quot;]);
  5. pieOuter.find(pieArr[i][&quot;label&quot;]).labelPosition = PieSlice.LabelInsideHorizontal;
  6. pieOuter.find(pieArr[i][&quot;label&quot;]).labelVisible= true;
  7. pieOuter.find(pieArr[i][&quot;label&quot;]).labelColor=pieArr[i][&quot;labelColor&quot;]
  8. pieOuter.find(pieArr[i][&quot;label&quot;]).labelFont.family=pieArr[i][&quot;labelFont&quot;]
  9. pieOuter.find(pieArr[i][&quot;label&quot;]).labelFont.pointSize=pieArr[i][&quot;labelPointSize&quot;]
  10. pieOuter.find(pieArr[i][&quot;label&quot;]).borderWidth=pieArr[i][&quot;borderWidth&quot;]
  11. pieOuter.find(pieArr[i][&quot;label&quot;]).borderColor=pieArr[i][&quot;borderColor&quot;]
  12. pieOuter.find(pieArr[i][&quot;label&quot;]).explodeDistanceFactor=pieArr[i][&quot;explodeDistanceFactor&quot;]
  13. pieOuter.find(pieArr[i][&quot;label&quot;]).exploded=pieArr[i][&quot;exploded&quot;]
  14. pieOuter.find(pieArr[i][&quot;label&quot;]).color=pieArr[i][&quot;originalColor&quot;]
  15. pieOuter.find(pieArr[i][&quot;label&quot;]).originalColor=pieArr[i][&quot;originalColor&quot;]
  16. pieOuter.find(pieArr[i][&quot;label&quot;]).active=pieArr[i][&quot;active&quot;]
  17. pieOuter.find(pieArr[i][&quot;label&quot;]).from=pieArr[i][&quot;from&quot;]
  18. pieOuter.find(pieArr[i][&quot;label&quot;]).to=pieArr[i][&quot;to&quot;]
  19. pieOuter.find(pieArr[i][&quot;label&quot;]).to=pieArr[i][&quot;to&quot;]
  20. }
  21. }

And then call it with Component.onCompleted or any other event you want to use:

  1. Component.onCompleted: {
  2. addPies(pieArray);}

huangapple
  • 本文由 发表于 2020年1月6日 22:24:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613774.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定