Построение графика в виджете
Необходимо реализовать функцию, которая при нажатии кнопки "Подгрузить данные", данные из Excel подтягивались и визуализировались в виде графика в виджет - "widgetGraph", и в виде таблицы в QTableView - "tableView".
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(815, 403)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widgetGraph = QtWidgets.QWidget(self.centralwidget)
self.widgetGraph.setGeometry(QtCore.QRect(30, 50, 311, 231))
self.widgetGraph.setObjectName("widgetGraph")
self.tableView = QtWidgets.QTableView(self.centralwidget)
self.tableView.setGeometry(QtCore.QRect(410, 50, 331, 231))
self.tableView.setObjectName("tableView")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(30, 10, 311, 31))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(410, 10, 331, 31))
self.textEdit_2.setObjectName("textEdit_2")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(34, 290, 301, 24))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 815, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"</style></head><body style=\" font-family:\'Segoe UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:700;\">График</span></p></body></html>"))
self.textEdit_2.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"</style></head><body style=\" font-family:\'Segoe UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:700;\">Табличные значения</span></p></body></html>"))
self.pushButton.setText(_translate("MainWindow", "Подгрузить данные"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Обратите внимание, я заменил
self.widgetGraph = QtWidgets.QWidget(self.centralwidget)
на
self.widgetGraph = pg.PlotWidget(title='PlotItem')
Одно из возможных решений может выглядеть примерно так:
#from PyQt6 import QtCore, QtGui, QtWidgets # PyQt6
from PyQt5 import QtCore, QtGui, QtWidgets # PyQt5
import pandas as pd # +++
import pyqtgraph as pg # +++
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(815, 403)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# self.widgetGraph = QtWidgets.QWidget(self.centralwidget)
self.widgetGraph = pg.PlotWidget(title='PlotItem') # !!! +++
self.widgetGraph.setGeometry(QtCore.QRect(30, 50, 311, 231))
self.widgetGraph.setObjectName("widgetGraph")
self.tableView = QtWidgets.QTableView(self.centralwidget)
self.tableView.setGeometry(QtCore.QRect(410, 50, 331, 231))
self.tableView.setObjectName("tableView")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(30, 10, 311, 31))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(410, 10, 331, 31))
self.textEdit_2.setObjectName("textEdit_2")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(34, 290, 301, 24))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 815, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
# self.statusbar = QtWidgets.QStatusBar(MainWindow)
# self.statusbar.setObjectName("statusbar")
# MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"</style></head><body style=\" font-family:\'Segoe UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:700;\">График</span></p></body></html>"))
self.textEdit_2.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"</style></head><body style=\" font-family:\'Segoe UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:700;\">Табличные значения</span></p></body></html>"))
self.pushButton.setText(_translate("MainWindow", "Подгрузить данные"))
class DataFrameModel(QtCore.QAbstractTableModel):
DtypeRole = QtCore.Qt.UserRole + 1000
ValueRole = QtCore.Qt.UserRole + 1001
def __init__(self, df=pd.DataFrame(), parent=None):
super(DataFrameModel, self).__init__(parent)
self._dataframe = df
def setDataFrame(self, dataframe):
self.beginResetModel()
self._dataframe = dataframe.copy()
self.endResetModel()
def dataFrame(self):
return self._dataframe
dataFrame = QtCore.pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame)
@QtCore.pyqtSlot(int, QtCore.Qt.Orientation, result=str)
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self._dataframe.columns[section]
else:
return str(self._dataframe.index[section])
return QtCore.QVariant()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._dataframe.index)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._dataframe.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or not (0 <= index.row() < self.rowCount() \
and 0 <= index.column() < self.columnCount()):
return QtCore.QVariant()
row = self._dataframe.index[index.row()]
col = self._dataframe.columns[index.column()]
dt = self._dataframe[col].dtype
val = self._dataframe.iloc[row][col]
if role == QtCore.Qt.DisplayRole:
return str(val)
elif role == DataFrameModel.ValueRole:
return val
if role == DataFrameModel.DtypeRole:
return dt
return QtCore.QVariant()
def roleNames(self):
roles = {
QtCore.Qt.DisplayRole: b'display',
DataFrameModel.DtypeRole: b'dtype',
DataFrameModel.ValueRole: b'value'
}
return roles
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.textEdit.setReadOnly(True)
self.textEdit.setMaximumHeight(30)
self.textEdit_2.setReadOnly(True)
self.textEdit_2.setMaximumHeight(30)
self.pushButton_2 = QtWidgets.QPushButton('Построить график') # +++
self.spinboxX = QtWidgets.QSpinBox(prefix="X : ", suffix=" столбец.") # +++
self.spinboxX.setRange(0, 1)
self.spinboxY = QtWidgets.QSpinBox(prefix="Y : ", suffix=" столбец.") # +++
self.spinboxY.setRange(0, 1)
self.widget = QtWidgets.QWidget()
layoutH = QtWidgets.QHBoxLayout(self.widget)
layoutH.addWidget(self.spinboxX)
layoutH.addWidget(self.spinboxY)
self.widget.hide()
self.layout = QtWidgets.QGridLayout(self.centralwidget)
self.layout.addWidget(self.textEdit, 0, 0, alignment=QtCore.Qt.AlignTop)
self.layout.addWidget(self.textEdit_2, 0, 1)
self.layout.addWidget(self.widgetGraph, 1, 0)
self.layout.addWidget(self.tableView, 1, 1)
self.layout.addWidget(self.pushButton_2, 2, 0)
self.layout.addWidget(self.pushButton, 2, 1)
self.layout.addWidget(self.widget, 3, 1)
self.layout.setColumnStretch(0, 1)
self.layout.setColumnStretch(1, 1)
self.pushButton.clicked.connect(self.load_data)
self.pushButton_2.clicked.connect(self.draw_graph)
def draw_graph(self):
if self.tableView.model() is None:
return
header_col = self.spinboxX.value()
header = self.tableView.model().headerData(header_col, QtCore.Qt.Horizontal)
x = self.tableView.model()._dataframe[header].values.tolist()
header_col = self.spinboxY.value()
header = self.tableView.model().headerData(header_col, QtCore.Qt.Horizontal)
y = self.tableView.model()._dataframe[header].values.tolist()
self.pg_calc(x, y)
def pg_calc(self, x, y):
self.widgetGraph.clear()
self.widgetGraph.plot(x, y, pen='r')
def load_data(self):
self.file_open()
def file_open(self):
path, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
'Open Excel',
'',
'*.xlsx *.xls'
)
if path:
df = pd.read_excel(path)
model = DataFrameModel(df)
self.tableView.setModel(model)
columns = self.tableView.model().columnCount()
self.spinboxX.setRange(0, columns-1)
self.spinboxY.setRange(0, columns-1)
self.spinboxY.setValue(1)
self.widget.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())


