【问题标题】:Matplotlib interfering with PyQtMatplotlib 干扰 PyQt
【发布时间】:2020-04-01 09:12:08
【问题描述】:

我有一种情况,在显示一个对话框后,设置参数,然后处理一个按钮单击的回调,关闭对话框并返回要用于在 matplotlib 中绘图的值。问题是组合框小部件将保持可见,有时对话框将保持可见等并干扰绘图。

这是一个可重现的问题示例。我修改了其中一个 PyQt 示例(02 PyQt Widgets)并添加了一些 matplotlib 绘图函数。当您运行脚本并选择组合框的选项之一(在 GUI 的左上部分)时,这些选项将保持可见(请参阅屏幕截图)。

from PyQt5.QtCore import QDateTime, Qt, QTimer
from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QDateTimeEdit,
QDial, QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit,
QProgressBar, QPushButton, QRadioButton, QScrollBar, QSizePolicy,
QSlider, QSpinBox, QStyleFactory, QTableWidget, QTabWidget, QTextEdit,
QVBoxLayout, QWidget)
from PyQt5.QtWidgets import *

import sys
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pandas as pd
import numpy as np
from time import time, sleep, strftime, gmtime

class WidgetGallery(QDialog):
def init(self, parent=None):
super(WidgetGallery, self).init(parent)

    self.originalPalette = QApplication.palette()

    styleComboBox = QComboBox()
    styleComboBox.addItems(QStyleFactory.keys())

    styleLabel = QLabel("&Style:")
    styleLabel.setBuddy(styleComboBox)

    self.useStylePaletteCheckBox = QCheckBox("&Use style's standard palette")
    self.useStylePaletteCheckBox.setChecked(True)

    disableWidgetsCheckBox = QCheckBox("&Disable widgets")

    self.createTopLeftGroupBox()
    self.createTopRightGroupBox()
    self.createBottomLeftTabWidget()
    self.createBottomRightGroupBox()
    self.createProgressBar()

    styleComboBox.activated[str].connect(self.changeStyle)
    self.useStylePaletteCheckBox.toggled.connect(self.changePalette)
    disableWidgetsCheckBox.toggled.connect(self.topLeftGroupBox.setDisabled)
    disableWidgetsCheckBox.toggled.connect(self.topRightGroupBox.setDisabled)
    disableWidgetsCheckBox.toggled.connect(self.bottomLeftTabWidget.setDisabled)
    disableWidgetsCheckBox.toggled.connect(self.bottomRightGroupBox.setDisabled)

    topLayout = QHBoxLayout()
    topLayout.addWidget(styleLabel)
    topLayout.addWidget(styleComboBox)
    topLayout.addStretch(1)
    topLayout.addWidget(self.useStylePaletteCheckBox)
    topLayout.addWidget(disableWidgetsCheckBox)

    mainLayout = QGridLayout()
    mainLayout.addLayout(topLayout, 0, 0, 1, 2)
    mainLayout.addWidget(self.topLeftGroupBox, 1, 0)
    mainLayout.addWidget(self.topRightGroupBox, 1, 1)
    mainLayout.addWidget(self.bottomLeftTabWidget, 2, 0)
    mainLayout.addWidget(self.bottomRightGroupBox, 2, 1)
    mainLayout.addWidget(self.progressBar, 3, 0, 1, 2)
    mainLayout.setRowStretch(1, 1)
    mainLayout.setRowStretch(2, 1)
    mainLayout.setColumnStretch(0, 1)
    mainLayout.setColumnStretch(1, 1)
    self.setLayout(mainLayout)
    self.setWindowTitle("Styles")
    self.changeStyle('Windows')

def on_button_clicked(self):
    alert = QMessageBox()
    alert.setText('You clicked the button!')

    self.button_state = self.radioButton1.isChecked()
    print("self.button_state ", self.button_state)

    alert.exec_()
    sleep(1)

    self.accept()
self.done(0)
self.close()
generate_plots()
def changeStyle(self, styleName):
    QApplication.setStyle(QStyleFactory.create(styleName))
    self.changePalette()

def changePalette(self):
    if (self.useStylePaletteCheckBox.isChecked()):
        QApplication.setPalette(QApplication.style().standardPalette())
    else:
        QApplication.setPalette(self.originalPalette)

def advanceProgressBar(self):
    curVal = self.progressBar.value()
    maxVal = self.progressBar.maximum()
    self.progressBar.setValue(curVal + (maxVal - curVal) / 100)
def createTopLeftGroupBox(self):
    self.topLeftGroupBox = QGroupBox("Group 1")
    self.radioButton1 = QRadioButton("Radio button 1")
    radioButton2 = QRadioButton("Radio button 2")
    radioButton3 = QRadioButton("Radio button 3")
    self.radioButton1.setChecked(True)
    checkBox = QCheckBox("Tri-state check box")
    checkBox.setTristate(True)
    checkBox.setCheckState(Qt.PartiallyChecked)
    layout = QVBoxLayout()
    layout.addWidget(self.radioButton1)
    layout.addWidget(radioButton2)
    layout.addWidget(radioButton3)
    layout.addWidget(checkBox)
    layout.addStretch(1)
    self.topLeftGroupBox.setLayout(layout)    

def createTopRightGroupBox(self):
    self.topRightGroupBox = QGroupBox("Group 2")

    defaultPushButton = QPushButton("Default Push Button")
    defaultPushButton.setDefault(True)
    togglePushButton = QPushButton("Toggle Push Button")
    togglePushButton.setCheckable(True)
    togglePushButton.setChecked(True)
    flatPushButton = QPushButton("Flat Push Button")
    flatPushButton.setFlat(True)
    button = QPushButton('Click This One')
    button.clicked.connect(self.on_button_clicked)
    layout = QVBoxLayout()
    layout.addWidget(button)
    layout.addWidget(defaultPushButton)
    layout.addWidget(togglePushButton)
    layout.addWidget(flatPushButton)
    layout.addStretch(1)
    self.topRightGroupBox.setLayout(layout)

def createBottomLeftTabWidget(self):
    self.bottomLeftTabWidget = QTabWidget()
    self.bottomLeftTabWidget.setSizePolicy(QSizePolicy.Preferred,
            QSizePolicy.Ignored)

    tab1 = QWidget()
    tableWidget = QTableWidget(10, 10)
    tab1hbox = QHBoxLayout()
    tab1hbox.setContentsMargins(5, 5, 5, 5)
    tab1hbox.addWidget(tableWidget)
    tab1.setLayout(tab1hbox)
    tab2 = QWidget()
    textEdit = QTextEdit()
    textEdit.setPlainText("Twinkle, twinkle, little star,\n"
                          "How I wonder what you are.\n" 
                          "Up above the world so high,\n"
                          "Like a diamond in the sky.\n"
                          "Twinkle, twinkle, little star,\n" 
                          "How I wonder what you are!\n")

    tab2hbox = QHBoxLayout()
    tab2hbox.setContentsMargins(5, 5, 5, 5)
    tab2hbox.addWidget(textEdit)
    tab2.setLayout(tab2hbox)

    self.bottomLeftTabWidget.addTab(tab1, "&Table")
    self.bottomLeftTabWidget.addTab(tab2, "Text &Edit")

def createBottomRightGroupBox(self):
    self.bottomRightGroupBox = QGroupBox("Group 3")
    self.bottomRightGroupBox.setCheckable(True)
    self.bottomRightGroupBox.setChecked(True)

    lineEdit = QLineEdit('s3cRe7')
    lineEdit.setEchoMode(QLineEdit.Password)
    spinBox = QSpinBox(self.bottomRightGroupBox)
    spinBox.setValue(50)
    dateTimeEdit = QDateTimeEdit(self.bottomRightGroupBox)
    dateTimeEdit.setDateTime(QDateTime.currentDateTime())
    slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox)
    slider.setValue(40)
    scrollBar = QScrollBar(Qt.Horizontal, self.bottomRightGroupBox)
    scrollBar.setValue(60)
    dial = QDial(self.bottomRightGroupBox)
    dial.setValue(30)
    dial.setNotchesVisible(True)

    layout = QGridLayout()
    layout.addWidget(lineEdit, 0, 0, 1, 2)
    layout.addWidget(spinBox, 1, 0, 1, 2)
    layout.addWidget(dateTimeEdit, 2, 0, 1, 2)
    layout.addWidget(slider, 3, 0)
    layout.addWidget(scrollBar, 4, 0)
    layout.addWidget(dial, 3, 1, 2, 1)
    layout.setRowStretch(5, 1)
    self.bottomRightGroupBox.setLayout(layout)

def createProgressBar(self):
    self.progressBar = QProgressBar()
    self.progressBar.setRange(0, 10000)
    self.progressBar.setValue(0)

    timer = QTimer(self)
    timer.timeout.connect(self.advanceProgressBar)
    timer.start(1000)
def plot_data(df, title, fig_num):
FIGURE_SIZE = (8, 6)
df_len = len(df)
x_series = np.arange(0, df_len)

fig, axs = plt.subplots(nrows=2, num=fig_num, figsize=FIGURE_SIZE, 
                dpi=72, facecolor='w', edgecolor='k', sharex=True, sharey=False, 
                    gridspec_kw={'hspace': 0.25}, tight_layout=False)

plt.suptitle('Plot Some Data', fontsize=12, fontweight='bold')
plt_axes = plt.gca()
plt_axes.set_ylim(-10.0, 10.0)

axs[0].plot(x_series, df['data1'], alpha=0.8, ms=1, color='b', label='Data 1')  
axs[0].xaxis.set_major_locator(ticker.MultipleLocator(10.))
axs[0].xaxis.set_minor_locator(ticker.MultipleLocator(10./5.))
axs[0].set(title=title, ylabel="Amp") 

axs[1].plot(x_series, df['data2'], alpha=0.8, ms=1, color='b', label='Data 2')  
axs[1].xaxis.set_major_locator(ticker.MultipleLocator(10.))
axs[1].xaxis.set_minor_locator(ticker.MultipleLocator(10./5.))
axs[1].set(title=title, ylabel="Amp") 
plt.savefig('data_plot.png', dpi=300)
plt.show()  
plt.close()
def generate_plots():

data_df = pd.DataFrame({
        'data1': {17384: 98125, 2680: 98107, 722: 98005, 18754: 98109, 14554: 98155}, 
        'data2': {17384: 1.5, 2680: 0.75, 722: 3.25, 18754: 1.0, 14554: 2.5}, 
        'data3': {17384: 1650, 2680: 3700, 722: 51836, 18754: 2640, 14554: 9603}, 
        'data4': {17384: 2, 2680: 2, 722: 4, 18754: 2, 14554: 4}, 
        'data4': {17384: 1430, 2680: 1440, 722: 4670, 18754: 1130, 14554: 3180}, 
        'data5': {17384: 3.0, 2680: 1.0, 722: 2.0, 18754: 1.0, 14554: 2.0}
        })
print (data_df)

plot_data(data_df, 'data plot', 30)
def main(date_time_now):

print("main() - date_time_now: ", date_time_now)

app = QApplication(sys.argv)
gallery = WidgetGallery()
gallery.show()
sys.exit(app.exec_())
app.exec_()
app.quit() 

print("main(): gallery.button_state: ", gallery.button_state)
generate_plots()
if name == 'main':

date_time_now = strftime('%Y-%m-%d-%H.%M.%S', gmtime())
main(date_time_now)

【问题讨论】:

    标签: python matplotlib pyqt pyqt5


    【解决方案1】:

    此问题已在 PyQt 论坛上得到解答。

    Here's the link to the answer

    matplotlib 还有一个基于 Qt 的后端,所以这两个可能会干扰 彼此。我建议你直接使用 该后端的类以将 matplotlib 与您的 Qt 集成 申请。

    我只需要在我的脚本中添加一个 this 就可以了。

    import matplotlib
    matplotlib.use('Qt5Agg')
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 2015-02-09
      • 2012-07-17
      • 2019-06-17
      • 2015-02-12
      • 2011-04-02
      • 2017-08-27
      相关资源
      最近更新 更多