Получение PySide2 QCharts для отображения при использовании Qt Designer - PullRequest
2 голосов
/ 21 января 2020

Новый программист с моим первым официальным вопросом StackOverflow здесь ...

У меня есть похожая проблема с вопросом здесь: Как вставить QChartView в форму с Qt Designer?

Итак, я создал главное окно моего пользовательского интерфейса в Qt Designer, и я пытаюсь заставить QtChart отображаться внутри одной из вкладок в моем окне. Я импортирую файл .ui в программу python, и до сих пор у меня получалось нормально отображать главное окно, но не график. Я потратил большую часть дня, пытаясь следовать инструкциям, перечисленным в ответе выше, но до сих пор я не смог заставить мой продвинутый виджет правильно импортировать в мою основную программу. Мне было интересно, если одна из причин в том, что я пытаюсь сделать это в python версии Qt (т.е. PySide2) вместо версии C ++, для которой, вероятно, был написан этот ответ.

I ' мы пытались использовать и QWidget, и рекомендованный QGraphicsView в качестве базы для продвижения моего QChartView, но до сих пор каждая попытка выдает ошибку, которая гласит: "QFormBuilder was unable to create a custom widget of the class 'QChartView'; defaulting to base class 'QWidget'." Что я делаю неправильно?

Как и связанные состояния вопроса / ответа, я установил для своего повышенного виджета значение «Имя продвигаемого класса», равное QChartView, и «Файл заголовка», равное QtCHarts. Ниже приведен базовый код моей Python программы (вначале игнорируйте мой странный импорт, так как это отдельная проблема, с которой я сталкиваюсь, когда моя программа не найдет импорт классов, если я не отформатирую их таким образом.)

Любая помощь будет принята с благодарностью! Спасибо!

import sys
import PySide2.QtCore as Qt_Core
import PySide2.QtGui as Qt_Gui
import PySide2.QtWidgets as Qt_Widgets
import PySide2.QtUiTools as Qt_UiTools
import PySide2.QtCharts as Qt_Chart
from PySide2.QtCharts import QtCharts
import Pico_Image_Resources
import Chart_UI

# Having import issues with submodules.
# Need to explicitly import submodules.
QMainWindow = Qt_Widgets.QMainWindow
QApplication = Qt_Widgets.QApplication
QGraphicsView = Qt_Widgets.QGraphicsView
QUiLoader = Qt_UiTools.QUiLoader
QFile = Qt_Core.QFile
QStyleFactory = Qt_Widgets.QStyleFactory
QtCharts = Qt_Chart.QtCharts
QChartView = QtCharts.QChartView
QPainter = Qt_Gui.QPainter
#-----------------------------------------

class MainWindow(QMainWindow):

    def __init__(self, ui_file, parent=None):
        super(MainWindow, self).__init__(parent)
        ui_file = QFile(ui_file)
        ui_file.open(QFile.ReadOnly)

        chartUI = Chart_UI.generateChart()
        self.chart = QtCharts.QChart()

        """
        Code that defines my chart setup is here

        """

        loader = QUiLoader()
        self.window = loader.load(ui_file)
        QApplication.setStyle(QStyleFactory.create('Fusion'))
        ui_file.close()

        #Normal Way to set up 'ChartView'
        # self.chartView = QChartView(self.chart)

        self.chartView = self.window.findChild(QChartView, 'calibrationChart')
        self.chartView.setChart(self.chart)
        self.chartView.setRenderHint(QPainter.Antialiasing)

        self.window.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow('My_Main_Window.ui')
    sys.exit(app.exec_())

[РЕДАКТИРОВАТЬ]: Вот код файла .ui, который я загружаю по запросу. Это не полный файл, так как оригинал слишком длинный для публикации, но этого должно быть достаточно, чтобы понять:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <author></author>
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1280</width>
    <height>720</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>1280</width>
    <height>720</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <property name="toolButtonStyle">
   <enum>Qt::ToolButtonFollowStyle</enum>
  </property>
  <widget class="QWidget" name="centralwidget">
   <property name="styleSheet">
    <string notr="true"/>
   </property>
   <widget class="QTabWidget" name="tabWidget">
    <property name="geometry">
     <rect>
      <x>400</x>
      <y>10</y>
      <width>871</width>
      <height>641</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>10</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="focusPolicy">
     <enum>Qt::TabFocus</enum>
    </property>
    <property name="currentIndex">
     <number>0</number>
    </property>
    <widget class="QWidget" name="tabCalib">
     <property name="enabled">
      <bool>true</bool>
     </property>
     <attribute name="title">
      <string>Chart 1</string>
     </attribute>
     <widget class="QChartView" name="calibrationChart" native="true">
      <property name="geometry">
       <rect>
        <x>19</x>
        <y>19</y>
        <width>821</width>
        <height>571</height>
       </rect>
      </property>
     </widget>
    </widget>
    <widget class="QWidget" name="tabDynamic">
     <attribute name="title">
      <string>Chart 2</string>
     </attribute>
     <widget class="QGraphicsView" name="graphicsView_2">
      <property name="geometry">
       <rect>
        <x>10</x>
        <y>10</y>
        <width>861</width>
        <height>591</height>
       </rect>
      </property>
      <property name="frameShape">
       <enum>QFrame::StyledPanel</enum>
      </property>
      <property name="frameShadow">
       <enum>QFrame::Sunken</enum>
      </property>
      <property name="renderHints">
       <set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
      </property>
     </widget>
    </widget>
   </widget>
   <widget class="QWidget" name="verticalLayoutWidget">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>10</y>
      <width>361</width>
      <height>451</height>
     </rect>
    </property>
    <layout class="QVBoxLayout" name="verticalLayout">
     <property name="spacing">
      <number>10</number>
     </property>
     <property name="sizeConstraint">
      <enum>QLayout::SetDefaultConstraint</enum>
     </property>
     <property name="leftMargin">
      <number>0</number>
     </property>
     <item>
      <widget class="QLabel" name="label_20">
       <property name="minimumSize">
        <size>
         <width>0</width>
         <height>32</height>
        </size>
       </property>
       <property name="maximumSize">
        <size>
         <width>16777215</width>
         <height>32</height>
        </size>
       </property>
       <property name="font">
        <font>
         <family>Calibri</family>
         <pointsize>11</pointsize>
         <weight>75</weight>
         <bold>true</bold>
         <strikeout>false</strikeout>
        </font>
       </property>
       <property name="frameShape">
        <enum>QFrame::StyledPanel</enum>
       </property>
       <property name="frameShadow">
        <enum>QFrame::Plain</enum>
       </property>
       <property name="text">
        <string>Test Title Here</string>
       </property>
       <property name="alignment">
        <set>Qt::AlignCenter</set>
       </property>
       <property name="wordWrap">
        <bool>false</bool>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QGroupBox" name="groupBox">
       <property name="title">
        <string>Please fill in the following data boxes:</string>
       </property>
       <widget class="QWidget" name="layoutWidget">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>40</y>
          <width>341</width>
          <height>271</height>
         </rect>
        </property>
        <layout class="QFormLayout" name="formLayout">
         <property name="labelAlignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
         <property name="horizontalSpacing">
          <number>10</number>
         </property>
         <property name="verticalSpacing">
          <number>10</number>
         </property>
         <item row="0" column="0">
          <widget class="QLabel" name="label_2">
           <property name="text">
            <string>Field One:</string>
           </property>
          </widget>
         </item>
         <item row="0" column="1">
          <widget class="QLineEdit" name="lineEdit_8"/>
         </item>
         <item row="1" column="0">
          <widget class="QLabel" name="label_3">
           <property name="text">
            <string>Field Two:</string>
           </property>
          </widget>
         </item>
         <item row="1" column="1">
          <widget class="QLineEdit" name="lineEdit"/>
         </item>
         <item row="2" column="0">
          <widget class="QLabel" name="label_4">
           <property name="text">
            <string>Field Three:</string>
           </property>
          </widget>
         </item>
         <item row="2" column="1">
          <widget class="QLineEdit" name="lineEdit_2"/>
         </item>
         <item row="4" column="0">
          <widget class="QLabel" name="label_5">
           <property name="text">
            <string>Field Five:</string>
           </property>
          </widget>
         </item>
         <item row="4" column="1">
          <widget class="QLineEdit" name="lineEdit_3"/>
         </item>
         <item row="5" column="0">
          <widget class="QLabel" name="label_6">
           <property name="text">
            <string>Field Six:</string>
           </property>
          </widget>
         </item>
         <item row="5" column="1">
          <widget class="QLineEdit" name="lineEdit_4"/>
         </item>
         <item row="6" column="0">
          <widget class="QLabel" name="label_7">
           <property name="text">
            <string>Selection One:</string>
           </property>
          </widget>
         </item>
         <item row="6" column="1">
          <widget class="QComboBox" name="comboBox">
           <property name="currentIndex">
            <number>3</number>
           </property>
           <item>
            <property name="text">
             <string>123</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>456</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>789</string>
            </property>
           </item>
          </widget>
         </item>
         <item row="7" column="0">
          <widget class="QLabel" name="label_8">
           <property name="text">
            <string>Selection Two:</string>
           </property>
          </widget>
         </item>
         <item row="7" column="1">
          <widget class="QComboBox" name="comboBox_2">
           <property name="currentIndex">
            <number>3</number>
           </property>
           <item>
            <property name="text">
             <string>123</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>456</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>789</string>
            </property>
           </item>
          </widget>
         </item>
         <item row="8" column="0">
          <widget class="QLabel" name="label_9">
           <property name="text">
            <string>Output:</string>
           </property>
          </widget>
         </item>
         <item row="8" column="1">
          <widget class="QLineEdit" name="lineEdit_7">
           <property name="enabled">
            <bool>false</bool>
           </property>
          </widget>
         </item>
         <item row="3" column="0">
          <widget class="QLabel" name="label_21">
           <property name="text">
            <string>Field Four:</string>
           </property>
          </widget>
         </item>
         <item row="3" column="1">
          <widget class="QLineEdit" name="lineEdit_5">
           <property name="enabled">
            <bool>false</bool>
           </property>
           <property name="readOnly">
            <bool>true</bool>
           </property>
           <property name="clearButtonEnabled">
            <bool>false</bool>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </widget>
     </item>
    </layout>
   </widget>
   <widget class="Line" name="line">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>470</y>
      <width>361</width>
      <height>21</height>
     </rect>
    </property>
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>140</x>
      <y>500</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Calibri</family>
      <pointsize>14</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color: rgb(85, 255, 0)</string>
    </property>
    <property name="text">
     <string>START TEST</string>
    </property>
    <property name="checkable">
     <bool>false</bool>
    </property>
    <property name="checked">
     <bool>false</bool>
    </property>
    <property name="default">
     <bool>false</bool>
    </property>
    <property name="flat">
     <bool>false</bool>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1280</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFile">
    <property name="title">
     <string>File</string>
    </property>
    <addaction name="actionSettings"/>
    <addaction name="separator"/>
    <addaction name="actionClose"/>
   </widget>
   <widget class="QMenu" name="menuAbout">
    <property name="title">
     <string>About</string>
    </property>
   </widget>
   <addaction name="menuFile"/>
   <addaction name="menuAbout"/>
  </widget>
  <widget class="QStatusBar" name="statusbar">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="autoFillBackground">
    <bool>false</bool>
   </property>
   <property name="styleSheet">
    <string notr="true">background-color: rgb(0, 132, 203);</string>
   </property>
   <property name="sizeGripEnabled">
    <bool>true</bool>
   </property>
  </widget>
  <action name="actionSettings">
   <property name="text">
    <string>Settings</string>
   </property>
  </action>
  <action name="actionClose">
   <property name="text">
    <string>Close</string>
   </property>
  </action>
 </widget>
 <customwidgets>
  <customwidget>
   <class>QChartView</class>
   <extends>QWidget</extends>
   <header>QtCharts</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources>
 </resources>
 <connections/>
</ui>

1 Ответ

3 голосов
/ 21 января 2020

QWidget в качестве контейнера:

В этом случае я не рекомендую применять рекламную акцию, потому что это сильно усложняет задачу, но я покажу, как применить решение, показанное в мой другой ответ : Используйте QWidget в качестве контейнера в .ui.

Для примера, я создал .ui с несколькими компонентами, и где вы хотите разместить QChartView, поместите QWidget (чтобы сделать его видимым, у меня есть установить зеленый цвет фона):

enter image description here

design.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>636</width>
    <height>480</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
    <item row="0" column="0">
     <widget class="QListWidget" name="listWidget"/>
    </item>
    <item row="1" column="0">
     <widget class="QTableWidget" name="tableWidget"/>
    </item>
    <item row="0" column="1" rowspan="2">
     <widget class="QWidget" name="widget" native="true">
      <property name="styleSheet">
       <string notr="true">background-color: rgb(138, 226, 52);</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>636</width>
     <height>24</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Тогда лог c просто: получите QWidget через objectName, которое в данном случае является «виджетом», затем поместите макет внутри этого виджета, а затем поместите QChartView внутри виджета через макет.

import random
import sys

from PySide2 import QtCore, QtGui, QtUiTools, QtWidgets
from PySide2.QtCharts import QtCharts


def ui_to_window(filename, parent=None):
    file = QtCore.QFile(filename)
    if not file.open(QtCore.QFile.ReadOnly):
        return
    loader = QtUiTools.QUiLoader()
    window = loader.load(file, parent)
    return window


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = ui_to_window("design.ui")
    window.widget.setContentsMargins(0, 0, 0, 0)
    lay = QtWidgets.QVBoxLayout(window.widget)
    lay.setContentsMargins(0, 0, 0, 0)

    chartview = QtCharts.QChartView()
    chartview.setContentsMargins(0, 0, 0, 0)
    lay.addWidget(chartview)

    series = QtCharts.QLineSeries()

    for i in range(10):
        series << QtCore.QPointF(i, random.uniform(0, 10))

    # Create Chart and set General Chart setting
    chart = QtCharts.QChart()
    chart.addSeries(series)
    chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)

    # X Axis Settings
    axisX = QtCharts.QValueAxis()
    chart.addAxis(axisX, QtCore.Qt.AlignBottom)
    series.attachAxis(axisX)

    # Y Axis Settings
    axisY = QtCharts.QValueAxis()
    chart.addAxis(axisY, QtCore.Qt.AlignLeft)
    series.attachAxis(axisY)

    chartview.setChart(chart)

    window.show()
    sys.exit(app.exec_())

enter image description here


Повышение QChartView:

Если вы все еще хотите использовать метод повышения, вы должны реализовать пользовательский QUiLoader, переопределяющий метод createWidget, возвращая QChartView если имя_класса я s QChartView:

import random
import sys

from PySide2 import QtCore, QtGui, QtUiTools, QtWidgets
from PySide2.QtCharts import QtCharts


class UiLoader(QtUiTools.QUiLoader):
    def createWidget(self, className, parent=None, name=""):
        if className == "QChartView":
            return QtCharts.QChartView(parent)
        return super().createWidget(className, parent, name)


def ui_to_window(filename, parent=None):
    file = QtCore.QFile(filename)
    if not file.open(QtCore.QFile.ReadOnly):
        return
    loader = UiLoader()
    window = loader.load(file, parent)
    return window


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = ui_to_window("Pico_LaserCal_MainWindow.ui")
    series = QtCharts.QLineSeries()

    for i in range(10):
        series << QtCore.QPointF(i, random.uniform(0, 10))

    # Create Chart and set General Chart setting
    chart = QtCharts.QChart()
    chart.addSeries(series)
    chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)

    # X Axis Settings
    axisX = QtCharts.QValueAxis()
    chart.addAxis(axisX, QtCore.Qt.AlignBottom)
    series.attachAxis(axisX)

    # Y Axis Settings
    axisY = QtCharts.QValueAxis()
    chart.addAxis(axisY, QtCore.Qt.AlignLeft)
    series.attachAxis(axisY)

    window.calibrationChart.setChart(chart)

    window.show()
    sys.exit(app.exec_())
...