在使用 Qt Designer 时显示 PySide2 QCharts

问题描述 投票:0回答:2

我对这里的问题有类似的问题:How to insert QChartView in form with Qt Designer?

所以我在 Qt Designer 中创建了我的 UI 主窗口,我试图让一个

QtChart
显示在我窗口的一个选项卡中。我正在将 .ui 文件导入 python 程序,到目前为止我可以让主窗口正常显示,但不是图表。我一天中的大部分时间都在尝试按照上述答案中列出的说明进行操作,但到目前为止,我还无法让我的升级小部件正确导入到我的主程序中。我一直想知道部分原因是否是我正在尝试在 Qt 的 python 版本(即 PySide2)而不是 C++ 版本中执行此操作,这个答案可能是为此编写的。

我尝试同时使用

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>

python qt-designer pyside2 qchart qchartview
2个回答
6
投票

QWidget 作为容器:

在这种情况下,我不建议应用促销,因为它会使任务复杂化很多,但我将展示如何应用我的其他答案中所示的解决方案:使用 QWidget 作为 .ui 中的容器

例如,我创建了一个包含多个组件的 .ui 文件,在您要放置 QChartView 的位置放置一个 QWidget(为了使其可见,我设置了绿色背景色):

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>

然后逻辑很简单:通过objectName获取QWidget,在本例中是“widget”,然后在该widget中放置一个布局,然后通过布局将QChartView放置在widget中。

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_())


QChartView推广:

如果您仍想使用提升方法,那么如果类名是 QChartView,则必须通过返回 QChartView 实现自定义 QUiLoader 覆盖 createWidget 方法:

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_())

0
投票

我能想到的最简单的解决方案是:

  1. 创建一个 QChartViewPointer.py 文件并将其放在您的 main.py 文件旁边

  2. 在QChartViewPointer.py文件中只写2行:

from PySide2.QtCharts import QtCharts
QChartView=QtCharts.QChartView

此代码创建一个指向 QtCharts.QChartView 类的 QChartView 变量

  1. 在QtDesiner中,在窗体中添加QGraphicsView(也可以使用QWidget,但我更喜欢QGraphicsView,因为QChartView继承自QGraphicsView)

  2. 右键单击 QGraphicsView 并选择“提升为...”

5.设置:

提升类名称: QChartView(QChartView 是 QChartViewPointer.py 文件中指向 QtCharts.QChartView 类的变量)

头文件: QChartViewPointer.h(QChartViewPointer.h是声明QChartView变量的文件名。不用py写h——这是写PySide的C++语言的语法)

然后按添加按钮,最后按推广。

© www.soinside.com 2019 - 2024. All rights reserved.