python3+PyQt5实现柱状图

本文通过Python3+pyqt5实现了python Qt GUI 快速编程的16章的excise例子。

#!/usr/bin/env python3

import random
import sys
from PyQt5.QtCore import (QAbstractListModel, QAbstractTableModel,
  QModelIndex, QSize, QTimer, QVariant, Qt,pyqtSignal)
from PyQt5.QtWidgets import (QApplication, QDialog, QHBoxLayout,
  QListView, QSpinBox, QStyledItemDelegate,QStyleOptionViewItem, QWidget)
from PyQt5.QtGui import QColor,QPainter,QPixmap

class BarGraphModel(QAbstractListModel):
 dataChanged=pyqtSignal(QModelIndex,QModelIndex)
 def __init__(self):
  super(BarGraphModel, self).__init__()
  self.__data = []
  self.__colors = {}
  self.minValue = 0
  self.maxValue = 0

 def rowCount(self, index=QModelIndex()):
  return len(self.__data)

 def insertRows(self, row, count):
  extra = row + count
  if extra >= len(self.__data):
   self.beginInsertRows(QModelIndex(), row, row + count - 1)
   self.__data.extend([0] * (extra - len(self.__data) + 1))
   self.endInsertRows()
   return True
  return False

 def flags(self, index):
  #return (QAbstractTableModel.flags(self, index)|Qt.ItemIsEditable)
  return (QAbstractListModel.flags(self, index)|Qt.ItemIsEditable)

 def setData(self, index, value, role=Qt.DisplayRole):
  row = index.row()
  if not index.isValid() or 0 > row >= len(self.__data):
   return False
  changed = False
  if role == Qt.DisplayRole:
   value = value
   self.__data[row] = value
   if self.minValue > value:
    self.minValue = value
   if self.maxValue < value:
    self.maxValue = value
   changed = True
  elif role == Qt.UserRole:
   self.__colors[row] = value
   #self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
   #   index, index)
   self.dataChanged[QModelIndex,QModelIndex].emit(index, index)
   changed = True
  if changed:
   #self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
    #   index, index)
   self.dataChanged[QModelIndex,QModelIndex].emit(index, index)
  return changed

 def data(self, index, role=Qt.DisplayRole):
  row = index.row()
  if not index.isValid() or 0 > row >= len(self.__data):
   return QVariant()
  if role == Qt.DisplayRole:
   return self.__data[row]
  if role == Qt.UserRole:
   return QVariant(self.__colors.get(row,
     QColor(Qt.red)))
  if role == Qt.DecorationRole:
   color = QColor(self.__colors.get(row,
     QColor(Qt.red)))
   pixmap = QPixmap(20, 20)
   pixmap.fill(color)
   return QVariant(pixmap)
  return QVariant()

class BarGraphDelegate(QStyledItemDelegate):

 def __init__(self, minimum=0, maximum=100, parent=None):
  super(BarGraphDelegate, self).__init__(parent)
  self.minimum = minimum
  self.maximum = maximum

 def paint(self, painter, option, index):
  myoption = QStyleOptionViewItem(option)
  myoption.displayAlignment |= (Qt.AlignRight|Qt.AlignVCenter)
  QStyledItemDelegate.paint(self, painter, myoption, index)

 def createEditor(self, parent, option, index):
  spinbox = QSpinBox(parent)
  spinbox.setRange(self.minimum, self.maximum)
  spinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
  return spinbox

 def setEditorData(self, editor, index):
  value = index.model().data(index, Qt.DisplayRole)
  editor.setValue(value)

 def setModelData(self, editor, model, index):
  editor.interpretText()
  model.setData(index, editor.value())

class BarGraphView(QWidget):

 WIDTH = 20

 def __init__(self, parent=None):
  super(BarGraphView, self).__init__(parent)
  self.model = None

 def setModel(self, model):
  self.model = model
  #self.connect(self.model,
  #  SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
  #  self.update)
  self.model.dataChanged[QModelIndex,QModelIndex].connect(self.update)
  #self.connect(self.model, SIGNAL("modelReset()"), self.update)
  self.model.modelReset.connect(self.update)

 def sizeHint(self):
  return self.minimumSizeHint()

 def minimumSizeHint(self):
  if self.model is None:
   return QSize(BarGraphView.WIDTH * 10, 100)
  return QSize(BarGraphView.WIDTH * self.model.rowCount(), 100)

 def paintEvent(self, event):
  if self.model is None:
   return
  painter = QPainter(self)
  painter.setRenderHint(QPainter.Antialiasing)
  span = self.model.maxValue - self.model.minValue
  painter.setWindow(0, 0, BarGraphView.WIDTH * self.model.rowCount(),
       span)
  for row in range(self.model.rowCount()):
   x = row * BarGraphView.WIDTH
   index = self.model.index(row)
   color = QColor(self.model.data(index, Qt.UserRole))
   y = self.model.data(index)
   painter.fillRect(x, span - y, BarGraphView.WIDTH, y, color)

class MainForm(QDialog):

 def __init__(self, parent=None):
  super(MainForm, self).__init__(parent)

  self.model = BarGraphModel()
  self.barGraphView = BarGraphView()
  self.barGraphView.setModel(self.model)
  self.listView = QListView()
  self.listView.setModel(self.model)
  self.listView.setItemDelegate(BarGraphDelegate(0, 1000, self))
  self.listView.setMaximumWidth(100)
  self.listView.setEditTriggers(QListView.DoubleClicked|
          QListView.EditKeyPressed)
  layout = QHBoxLayout()
  layout.addWidget(self.listView)
  layout.addWidget(self.barGraphView, 1)
  self.setLayout(layout)

  self.setWindowTitle("Bar Grapher")
  QTimer.singleShot(0, self.initialLoad)

 def initialLoad(self):
  # Generate fake data
  count = 20
  self.model.insertRows(0, count - 1)
  for row in range(count):
   value = random.randint(1, 150)
   color = QColor(random.randint(0, 255), random.randint(0, 255),
       random.randint(0, 255))
   index = self.model.index(row)
   self.model.setData(index, value)
   self.model.setData(index, QVariant(color), Qt.UserRole)

app = QApplication(sys.argv)
form = MainForm()
form.resize(600, 400)
form.show()
app.exec_()

运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • python3+PyQt5实现自定义流体混合窗口部件
  • python3+PyQt5实现拖放功能
  • python3+PyQt5使用数据库表视图
  • python3+PyQt5使用数据库窗口视图
  • python3+PyQt5实现文档打印功能
  • python3+PyQt5实现自定义分数滑块部件
(0)

相关推荐

  • python3+PyQt5使用数据库表视图

    上文提到窗体可以一次性呈现出来自同一记录的各个域,但是对于用户希望能看到多条记录的表来说,就需要使用表格化的视图了.本文通过python3+pyqt5改写实现了python Qt gui 快速变成15章的例子,用户能够一次看到多条记录. #!/usr/bin/env python3 import os import sys from PyQt5.QtCore import (PYQT_VERSION_STR, QDate, QFile, QRegExp, QVariant, QModelInde

  • python3+PyQt5实现文档打印功能

    本文通过Python3+PyQt5实现<python Qt Gui 快速编程>这本书13章文档打印功能.本文共通过三种方式: 1.使用HTML和QTextDOcument打印文档 2.使用QTextCusor和QTextDocument打印文档 3.使用QPainter打印文档 使用Qpainter打印文档比QTextDocument需要更操心和复杂的计算,但是QPainter确实能够对输出赋予完全控制. #!/usr/bin/env python3 import math import sy

  • python3+PyQt5实现自定义分数滑块部件

    本文通过Python3+PyQt5实现自定义部件–分数滑块.它既能支持键盘也支持鼠标,使用物理(视口)坐标通过绘制方式显示. #!/usr/bin/env python3 import platform from PyQt5.QtCore import (QPointF, QRectF, QSize, Qt,pyqtSignal) from PyQt5.QtWidgets import (QApplication, QDialog,QSizePolicy, QGridLayout, QLCDNu

  • python3+PyQt5使用数据库窗口视图

    能够为数据库数据提供的最简单的用户界面之一就是窗体,窗体可以一次性呈现出来自同一记录的各个域.本文通过python3+pyqt5改写实现了python Qt gui 快速变成15章的例子. #!/usr/bin/env python3 import os import sys from PyQt5.QtCore import (QDate, QDateTime, QFile, QVariant, Qt) from PyQt5.QtWidgets import (QApplication, QDa

  • python3+PyQt5实现自定义流体混合窗口部件

    本文通过Python3+PyQt5实现自定义部件–流体混合窗口部件.通过逻辑(窗口)坐标绘制而成.调用setWindow,所有的绘制工作都会根据逻辑坐标系发生. #!/usr/bin/env python3 from PyQt5.QtCore import (QPointF, QSize, Qt,pyqtSignal) from PyQt5.QtWidgets import (QApplication, QFrame, QLabel, QSizePolicy, QSpinBox, QWidget

  • python3+PyQt5实现拖放功能

    本文是对<Python Qt GUI快速编程>的第10章的例子拖放用Python3+PyQt5进行改写,对图表列表,表格等进行相互拖放,基本原理雷同,均采用setAcceptDrops(True)和setDragEnabled(True). #!/usr/bin/env python3 import os import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QApplication, QDialog, QHBo

  • python3+PyQt5实现柱状图

    本文通过Python3+pyqt5实现了python Qt GUI 快速编程的16章的excise例子. #!/usr/bin/env python3 import random import sys from PyQt5.QtCore import (QAbstractListModel, QAbstractTableModel, QModelIndex, QSize, QTimer, QVariant, Qt,pyqtSignal) from PyQt5.QtWidgets import (

  • python3+PyQt5实现使用剪贴板做复制与粘帖示例

    本文是对<Python Qt GUI快速编程>的第10章的例子剪贴板用Python3+PyQt5进行改写,分别对文本,图片和html文本的复制与粘帖,三种做法大同小异. #!/usr/bin/env python3 import os import sys from PyQt5.QtCore import (QMimeData, Qt) from PyQt5.QtWidgets import (QApplication, QDialog, QGridLayout, QLabel, QPushB

  • python3+PyQt5实现自定义窗口部件Counters

    本文通过Python3+PyQt5实现自定义部件–Counters自定 窗口部件.这个窗口是3*3的网格.本文有两个例子如下: /home/yrd/eric_workspace/chap11/counters.py. /home/yrd/eric_workspace/chap11/counters_dnd.py 第二个例子在第一个例子的基础上实现能通过鼠标拖拽球到不同的网格中. /home/yrd/eric_workspace/chap11/counters.py #!/usr/bin/env

  • python3+PyQt5+Qt Designer实现扩展对话框

    本文是对<Python Qt GUI快速编程>的第9章的扩展对话框例子Find and replace用Python3+PyQt5+Qt Designer进行改写. 第一部分无借用Qt Designer,完全用代码实现. 第二部分则借用Qt Designer,快速实现. 第一部分: import sys from PyQt5.QtCore import Qt,pyqtSignal from PyQt5.QtWidgets import (QApplication, QCheckBox, QDi

  • python3+PyQt5+Qt Designer实现堆叠窗口部件

    本文是对<Python Qt GUI快速编程>的第9章的堆叠窗口例子Vehicle Rental用Python3+PyQt5+Qt Designer进行改写. 第一部分无借用Qt Designer,完全用代码实现. 第二部分则借用Qt Designer,快速实现. 第一部分: import sys from PyQt5.QtCore import (Qt) from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog, QDialo

随机推荐