python 3+PyQt 5 사용자 정의 보기 상세 설명
#!/usr/bin/env python3
import gzip
import os
import platform
import sys
from PyQt5.QtCore import (QAbstractTableModel, QDateTime, QModelIndex,
QSize, QTimer, QVariant, Qt,pyqtSignal)
from PyQt5.QtGui import ( QColor, QCursor, QFont,
QFontDatabase, QFontMetrics, QPainter, QPalette, QPixmap)
from PyQt5.QtWidgets import QApplication,QDialog,QHBoxLayout, QLabel, QMessageBox,QScrollArea, QSplitter, QTableView,QWidget
(TIMESTAMP, TEMPERATURE, INLETFLOW, TURBIDITY, CONDUCTIVITY,
COAGULATION, RAWPH, FLOCCULATEDPH) = range(8)
TIMESTAMPFORMAT = "yyyy-MM-dd hh:mm"
class WaterQualityModel(QAbstractTableModel):
def __init__(self, filename):
super(WaterQualityModel, self).__init__()
self.filename = filename
self.results = []
def load(self):
self.beginResetModel()
exception = None
fh = None
try:
if not self.filename:
raise IOError("no filename specified for loading")
self.results = []
line_data = gzip.open(self.filename).read()
for line in line_data.decode("utf8").splitlines():
parts = line.rstrip().split(",")
date = QDateTime.fromString(parts[0] + ":00",
Qt.ISODate)
result = [date]
for part in parts[1:]:
result.append(float(part))
self.results.append(result)
except (IOError, ValueError) as e:
exception = e
finally:
if fh is not None:
fh.close()
self.endResetModel()
if exception is not None:
raise exception
def data(self, index, role=Qt.DisplayRole):
if (not index.isValid() or
not (0 <= index.row() < len(self.results))):
return QVariant()
column = index.column()
result = self.results[index.row()]
if role == Qt.DisplayRole:
item = result[column]
if column == TIMESTAMP:
#item = item.toString(TIMESTAMPFORMAT)
item=item
else:
#item = QString("%1").arg(item, 0, "f", 2)
item = "{0:.2f}".format(item)
return item
elif role == Qt.TextAlignmentRole:
if column != TIMESTAMP:
return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
return QVariant(int(Qt.AlignLeft|Qt.AlignVCenter))
elif role == Qt.TextColorRole and column == INLETFLOW:
if result[column] < 0:
return QVariant(QColor(Qt.red))
elif (role == Qt.TextColorRole and
column in (RAWPH, FLOCCULATEDPH)):
ph = result[column]
if ph < 7:
return QVariant(QColor(Qt.red))
elif ph >= 8:
return QVariant(QColor(Qt.blue))
else:
return QVariant(QColor(Qt.darkGreen))
return QVariant()
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.TextAlignmentRole:
if orientation == Qt.Horizontal:
return QVariant(int(Qt.AlignCenter))
return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
if role != Qt.DisplayRole:
return QVariant()
if orientation == Qt.Horizontal:
if section == TIMESTAMP:
return "Timestamp"
elif section == TEMPERATURE:
return "\u00B0" +"C"
elif section == INLETFLOW:
return "Inflow"
elif section == TURBIDITY:
return "NTU"
elif section == CONDUCTIVITY:
return "\u03BCS/cm"
elif section == COAGULATION:
return "mg/L"
elif section == RAWPH:
return "Raw Ph"
elif section == FLOCCULATEDPH:
return "Floc Ph"
return int(section + 1)
def rowCount(self, index=QModelIndex()):
return len(self.results)
def columnCount(self, index=QModelIndex()):
return 8
class WaterQualityView(QWidget):
clicked = pyqtSignal(QModelIndex)
FLOWCHARS = (chr(0x21DC), chr(0x21DD), chr(0x21C9))
def __init__(self, parent=None):
super(WaterQualityView, self).__init__(parent)
self.scrollarea = None
self.model = None
self.setFocusPolicy(Qt.StrongFocus)
self.selectedRow = -1
self.flowfont = self.font()
size = self.font().pointSize()
if platform.system() == "Windows":
fontDb = QFontDatabase()
for face in [face.toLower() for face in fontDb.families()]:
if face.contains("unicode"):
self.flowfont = QFont(face, size)
break
else:
self.flowfont = QFont("symbol", size)
WaterQualityView.FLOWCHARS = (chr(0xAC), chr(0xAE),
chr(0xDE))
def setModel(self, model):
self.model = model
#self.connect(self.model,
# SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
# self.setNewSize)
self.model.dataChanged.connect(self.setNewSize)
#self.connect(self.model, SIGNAL("modelReset()"), self.setNewSize)
self.model.modelReset.connect(self.setNewSize)
self.setNewSize()
def setNewSize(self):
self.resize(self.sizeHint())
self.update()
self.updateGeometry()
def minimumSizeHint(self):
size = self.sizeHint()
fm = QFontMetrics(self.font())
size.setHeight(fm.height() * 3)
return size
def sizeHint(self):
fm = QFontMetrics(self.font())
size = fm.height()
return QSize(fm.width("9999-99-99 99:99 ") + (size * 4),
(size / 4) + (size * self.model.rowCount()))
def paintEvent(self, event):
if self.model is None:
return
fm = QFontMetrics(self.font())
timestampWidth = fm.width("9999-99-99 99:99 ")
size = fm.height()
indicatorSize = int(size * 0.8)
offset = int(1.5 * (size - indicatorSize))
minY = event.rect().y()
maxY = minY + event.rect().height() + size
minY -= size
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setRenderHint(QPainter.TextAntialiasing)
y = 0
for row in range(self.model.rowCount()):
x = 0
if minY <= y <= maxY:
painter.save()
painter.setPen(self.palette().color(QPalette.Text))
if row == self.selectedRow:
painter.fillRect(x, y + (offset * 0.8),
self.width(), size, self.palette().highlight())
painter.setPen(self.palette().color(
QPalette.HighlightedText))
#timestamp = self.model.data(
#self.model.index(row, TIMESTAMP)).toDateTime()
timestamp = self.model.data(self.model.index(row, TIMESTAMP))
painter.drawText(x, y + size,
timestamp.toString(TIMESTAMPFORMAT))
#print(timestamp.toString(TIMESTAMPFORMAT))
x += timestampWidth
temperature = self.model.data(
self.model.index(row, TEMPERATURE))
#temperature = temperature.toDouble()[0]
temperature = float(temperature)
if temperature < 20:
color = QColor(0, 0,
int(255 * (20 - temperature) / 20))
elif temperature > 25:
color = QColor(int(255 * temperature / 100), 0, 0)
else:
color = QColor(0, int(255 * temperature / 100), 0)
painter.setPen(Qt.NoPen)
painter.setBrush(color)
painter.drawEllipse(x, y + offset, indicatorSize,
indicatorSize)
x += size
rawPh = self.model.data(self.model.index(row, RAWPH))
#rawPh = rawPh.toDouble()[0]
rawPh = float(rawPh)
if rawPh < 7:
color = QColor(int(255 * rawPh / 10), 0, 0)
elif rawPh >= 8:
color = QColor(0, 0, int(255 * rawPh / 10))
else:
color = QColor(0, int(255 * rawPh / 10), 0)
painter.setBrush(color)
painter.drawEllipse(x, y + offset, indicatorSize,
indicatorSize)
x += size
flocPh = self.model.data(
self.model.index(row, FLOCCULATEDPH))
#flocPh = flocPh.toDouble()[0]
flocPh = float(flocPh)
if flocPh < 7:
color = QColor(int(255 * flocPh / 10), 0, 0)
elif flocPh >= 8:
color = QColor(0, 0, int(255 * flocPh / 10))
else:
color = QColor(0, int(255 * flocPh / 10), 0)
painter.setBrush(color)
painter.drawEllipse(x, y + offset, indicatorSize,
indicatorSize)
painter.restore()
painter.save()
x += size
flow = self.model.data(
self.model.index(row, INLETFLOW))
#flow = flow.toDouble()[0]
flow = float(flow)
char = None
if flow <= 0:
char = WaterQualityView.FLOWCHARS[0]
elif flow < 3.6:
char = WaterQualityView.FLOWCHARS[1]
elif flow > 4.7:
char = WaterQualityView.FLOWCHARS[2]
if char is not None:
painter.setFont(self.flowfont)
painter.drawText(x, y + size, char)
painter.restore()
y += size
if y > maxY:
break
def mousePressEvent(self, event):
fm = QFontMetrics(self.font())
self.selectedRow = event.y() // fm.height()
self.update()
#self.emit(SIGNAL("clicked(QModelIndex)"),
# self.model.index(self.selectedRow, 0))
self.clicked.emit(self.model.index(self.selectedRow, 0))
def keyPressEvent(self, event):
if self.model is None:
return
row = -1
if event.key() == Qt.Key_Up:
row = max(0, self.selectedRow - 1)
elif event.key() == Qt.Key_Down:
row = min(self.selectedRow + 1, self.model.rowCount() - 1)
if row != -1 and row != self.selectedRow:
self.selectedRow = row
if self.scrollarea is not None:
fm = QFontMetrics(self.font())
y = fm.height() * self.selectedRow
print(y)
self.scrollarea.ensureVisible(0, y)
self.update()
#self.emit(SIGNAL("clicked(QModelIndex)"),
# self.model.index(self.selectedRow, 0))
self.clicked.emit(self.model.index(self.selectedRow, 0))
else:
QWidget.keyPressEvent(self, event)
class MainForm(QDialog):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.model = WaterQualityModel(os.path.join(
os.path.dirname(__file__), "waterdata.csv.gz"))
self.tableView = QTableView()
self.tableView.setAlternatingRowColors(True)
self.tableView.setModel(self.model)
self.waterView = WaterQualityView()
self.waterView.setModel(self.model)
scrollArea = QScrollArea()
scrollArea.setBackgroundRole(QPalette.Light)
scrollArea.setWidget(self.waterView)
self.waterView.scrollarea = scrollArea
splitter = QSplitter(Qt.Horizontal)
splitter.addWidget(self.tableView)
splitter.addWidget(scrollArea)
splitter.setSizes([600, 250])
layout = QHBoxLayout()
layout.addWidget(splitter)
self.setLayout(layout)
self.setWindowTitle("Water Quality Data")
QTimer.singleShot(0, self.initialLoad)
def initialLoad(self):
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
splash = QLabel(self)
pixmap = QPixmap(os.path.join(os.path.dirname(__file__),
"iss013-e-14802.jpg"))
#print(os.path.join(os.path.dirname(__file__),
# "iss013-e-14802.jpg"))
splash.setPixmap(pixmap)
splash.setWindowFlags(Qt.SplashScreen)
splash.move(self.x() + ((self.width() - pixmap.width()) / 2),
self.y() + ((self.height() - pixmap.height()) / 2))
splash.show()
QApplication.processEvents()
try:
self.model.load()
except IOError as e:
QMessageBox.warning(self, "Water Quality - Error", e)
else:
self.tableView.resizeColumnsToContents()
splash.close()
QApplication.processEvents()
QApplication.restoreOverrideCursor()
app = QApplication(sys.argv)
form = MainForm()
form.resize(850, 620)
form.show()
app.exec_()
실행 결과:이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Jupyter 공식 DockerHub에 대한 메모에 기재되어 있다. base-notebook minimal-notebook scipy-notebook tensorflow-notebook datascience-notebook pyspark-notebook all-s...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.