2017-10-19 107 views
1

我正在使用两个选项卡在一个项目上使用GUI(用手编写),并在每个选项卡上使用不同的画布(以在每个选项卡中绘制不同的内容)。 但是,我还在这些标签上添加了一些小部件,并且在将它们添加到布局时,如果我在布局中的按钮的相同位置添加画布,我可以再次点击此按钮。 我知道在PyQt可以提高小部件的水平,所以有办法用画布做同样的事情吗?QWidget在matplotlib画布上方

非常感谢您的帮助。在这个例子中,“退出”仅在右半部分有效。

import sys 
from PyQt5.QtGui import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 

import matplotlib 
matplotlib.use('Qt5Agg') 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
import matplotlib.pyplot as plt 
from mpl_toolkits.axes_grid1 import make_axes_locatable 

class FenetrePrincipale(QWidget): 
    def __init__(self, parent=None): 
     super(FenetrePrincipale, self).__init__(parent) 
     self.setupUi(self) 

    # Fonction de configuration de la classe 
    def setupUi(self, Form): 
     self.Form = Form 

     Form.setMinimumSize(1220, 850) 

     self.creation_GUI() 
     self.creation_figure() 
     self.creation_layout() 

     self.tabWidget.setCurrentIndex(0) 
     self.Bouton_quitter.clicked.connect(self.close) 

    def resizeEvent(self, QResizeEvent): 
     self.tabWidget.setMinimumSize(QSize(self.width() - 20, self.height() - 60)) 

    def creation_GUI(self): 
     self.tabWidget = QTabWidget() 
     self.tab1 = QWidget() 

     self.Widget_choixPalette_Label = QLabel(self.tab1) 
     self.Widget_choixPalette_Label.setText("Text1") 
     self.Widget_choixPalette_ComboBox = QComboBox(self.tab1) 
     self.Widget_choixPalette_ComboBox.addItem("Try1") 
     self.Widget_choixPalette_ComboBox.addItem("Try2") 

     self.Bouton_quitter = QPushButton(self.tab1) 
     self.Bouton_quitter.setText("Quit") 

    def creation_layout(self): 
     LayoutForm = QGridLayout(self.Form) 
     LayoutG1 = QGridLayout() 
     LayoutTab1 = QGridLayout(self.tab1) 
     WidgetTemp = QWidget() 
     LayoutWidgetTemp = QGridLayout() 

     LayoutG1.addWidget(self.Bouton_quitter, 21, 29, 1, 2, Qt.AlignRight | Qt.AlignBottom) 
     LayoutG1.addWidget(self.canvas, 2, 10, 20, 20) 

     LayoutWidgetTemp.addWidget(self.Widget_choixPalette_Label, 0, 0, 1, 4) 
     LayoutWidgetTemp.addWidget(self.Widget_choixPalette_ComboBox, 1, 0, 1, 4) 
     WidgetTemp.setLayout(LayoutWidgetTemp) 
     LayoutG1.addWidget(WidgetTemp, 1, 18, 2, 4) 

     LayoutTab1.addLayout(LayoutG1, 0, 0, 1, 1) 

     self.tabWidget.addTab(self.tab1, " Tab1 ") 

     LayoutForm.addWidget(self.tabWidget, 1, 0, 1, 1) 

    def creation_figure(self): 
     # Create figure (transparent background) 
     self.figure = plt.figure() 
     self.figure.patch.set_facecolor('None') 
     self.canvas = FigureCanvas(self.figure) 
     self.canvas.setStyleSheet("background-color:transparent;") 

     # Adding one subplot for image 
     self.axe0 = self.figure.add_subplot(111) 
     self.axe0.get_xaxis().set_visible(False) 
     self.axe0.get_yaxis().set_visible(False) 
     plt.tight_layout() 

     # Data for init image 
     self.imageInit = [[255] * 320 for i in range(240)] 
     self.imageInit[0][0] = 0 

     # Init image and add colorbar 
     self.image = self.axe0.imshow(self.imageInit, interpolation='none') 
     divider = make_axes_locatable(self.axe0) 
     cax = divider.new_vertical(size="5%", pad=0.05, pack_start=True) 
     self.colorbar = self.figure.add_axes(cax) 
     self.figure.colorbar(self.image, cax=cax, orientation='horizontal') 

     self.canvas.draw() 

if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    # QApplication.setStyle(QStyleFactory.create("plastique")) 
    form = FenetrePrincipale() 
    form.show() 
    sys.exit(app.exec_()) 
  • 操作系统:Windows 7专业版
  • Matplotlib版本:4.0.4
  • Matplotlib后端:Qt5Agg
  • Python版本:3.6
  • 其他库:PyQt5

编辑25/10/17:例如新代码

+1

你为什么试图在同一位置添加两个小部件?这是永远不会工作。你想达到什么目的? – ekhumoro

+0

这是因为这个图不占用画布的所有空间,所以我想优化空间,添加我的按钮的地方不是。 –

+0

解决此问题的正确方法是删除画布顶部的空白区域。也许尝试:'plt.tight_layout()'。 – ekhumoro

回答

2

以下是您的示例脚本的一个版本,它修复了所有问题。大部分问题都是由于布局非常混乱造成的。我不得不完全用 重新编写creation_layout方法,以便获得一个理智的起点,以便我可以看到问题出在哪里。我还临时恢复了画布的背景颜色,以便更容易地看到这些小部件相对于彼此展开的方式。我意识到将我的一些更改并入您的真实代码并不容易。但希望它会给你一些关于如何简化你的布局结构的想法。

最重要的修复方法是在creation_figure方法中使用subplots_adjust。这将删除画布顶部的所有空白空间,因此不再需要尝试在其上放置其他小部件。

import sys 
from PyQt5.QtGui import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 

import matplotlib 
matplotlib.use('Qt5Agg') 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
import matplotlib.pyplot as plt 
from mpl_toolkits.axes_grid1 import make_axes_locatable 

class FenetrePrincipale(QWidget): 
    def __init__(self, parent=None): 
     super(FenetrePrincipale, self).__init__(parent) 
     self.setupUi(self) 

    # Fonction de configuration de la classe 
    def setupUi(self, Form): 
     self.Form = Form 

     Form.setMinimumSize(1220, 850) 

     self.creation_GUI() 
     self.creation_figure() 
     self.creation_layout() 

     self.tabWidget.setCurrentIndex(0) 
     self.Bouton_quitter.clicked.connect(self.close) 

    def resizeEvent(self, QResizeEvent): 
     self.tabWidget.setMinimumSize(QSize(self.width() - 20, self.height() - 60)) 

    def creation_GUI(self): 
     self.tabWidget = QTabWidget() 
     self.tab1 = QWidget() 
     self.tabWidget.addTab(self.tab1, " Tab1 ") 

     self.Widget_choixPalette_Label = QLabel(self.tab1) 
     self.Widget_choixPalette_Label.setText("Text1") 
     self.Widget_choixPalette_ComboBox = QComboBox(self.tab1) 
     self.Widget_choixPalette_ComboBox.addItem("Try1") 
     self.Widget_choixPalette_ComboBox.addItem("Try2") 

     self.Bouton_quitter = QPushButton(self.tab1) 
     self.Bouton_quitter.setText("Quit") 

    def creation_layout(self): 
     LayoutForm = QGridLayout(self) 
     LayoutForm.addWidget(self.tabWidget, 0, 0, 1, 1) 

     LayoutTab1 = QGridLayout(self.tab1) 

     LayoutTab1.addWidget(self.Widget_choixPalette_Label, 0, 1, 1, 1) 
     LayoutTab1.addWidget(self.Widget_choixPalette_ComboBox, 1, 1, 1, 1) 
     self.Widget_choixPalette_ComboBox.setMinimumWidth(200) 

     LayoutTab1.addWidget(self.canvas, 2, 0, 1, 3) 
     LayoutTab1.addWidget(self.Bouton_quitter, 2, 3, 1, 1, Qt.AlignRight | Qt.AlignBottom) 

     LayoutTab1.setRowStretch(2, 1) 
     LayoutTab1.setColumnStretch(0, 1) 
     LayoutTab1.setColumnStretch(2, 1) 

    def creation_figure(self): 
     # Create figure (transparent background) 
     self.figure = plt.figure() 
     # self.figure.patch.set_facecolor('None') 
     self.canvas = FigureCanvas(self.figure) 
     self.canvas.setStyleSheet("background-color:transparent;") 

     # Adding one subplot for image 
     self.axe0 = self.figure.add_subplot(111) 
     self.axe0.get_xaxis().set_visible(False) 
     self.axe0.get_yaxis().set_visible(False) 
     # plt.tight_layout() 

     # Data for init image 
     self.imageInit = [[255] * 320 for i in range(240)] 
     self.imageInit[0][0] = 0 

     # Init image and add colorbar 
     self.image = self.axe0.imshow(self.imageInit, interpolation='none') 
     divider = make_axes_locatable(self.axe0) 
     cax = divider.new_vertical(size="5%", pad=0.05, pack_start=True) 
     self.colorbar = self.figure.add_axes(cax) 
     self.figure.colorbar(self.image, cax=cax, orientation='horizontal') 

     plt.subplots_adjust(left=0, bottom=0.05, right=1, top=1, wspace=0, hspace=0) 

     self.canvas.draw() 

if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    # QApplication.setStyle(QStyleFactory.create("plastique")) 
    form = FenetrePrincipale() 
    form.show() 
    sys.exit(app.exec_()) 
+0

我感谢您的回答!我承认我的'creation_layout'方法非常混乱,但这里有一个来自我的真实GUI的小例子,它有大约30个小部件。下次我将使用QtDesigner,因为有人向我展示如何像canvas一样为外部小部件提升小部件。 因为我不知道它是什么,所以我会再看'拉伸'^^ –

+0

非常感谢!在'subplots_adjust'和'addColumnStretch'方法之间我不知道,手工创建布局非常舒适! –

+0

@MathieuGauquelin。是的,我打算建议使用Qt Designer进行窗口小部件升级,但是我想这可能需要很多工作来转换现有的代码。但从长远来看,它会让你的生活变得更容易。 – ekhumoro

1

只需将您添加到布局的顺序颠倒即可。首先添加画布,然后顶部的按钮

LayoutForm.addWidget(canvas,1,0,1,6) 
    LayoutForm.addWidget(button,1,0,1,2) 
+0

它不适用于我的真实代码,我使用5个控件执行相同操作: ' LayoutG2.add Widget(canvas2,1,10,21,20)' 'LayoutG2。addWidget(Widget_choixPalette_2_Label,0,11,1,4)'' LayoutG2.addWidget(Widget_choixPalette_2_ComboBox,1,11,1,4)'' LayoutG2.addWidget(Widget_imageSelectionnee_Label,0,15,1,3)'' LayoutG2 .addWidget(Widget_imageSelectionnee_Edit,1,15,1,3)' 'LayoutG2.addWidget(slide,1,18,1,5)' 但我只能与幻灯片交互,而不是QEdit或QPushButton。也许我想念别的东西? 我在我的GUI上有多个布局(因为我有选项卡)的信息。 –

+0

如果你没有绘图,你可以与其余的对象进行交互吗?如果是,将它们添加到布局,并将布局放置在画布上方 – Andrei

+0

我会尝试添加两种不同布局的小部件并返回。 –