Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e169aff

Browse files
authored
Merge pull request #8683 from anntzer/qt-subplottool
ENH: Simplify and improve Qt borders/spacing tool
2 parents eea8e4f + 56e9f1b commit e169aff

File tree

3 files changed

+112
-317
lines changed

3 files changed

+112
-317
lines changed

lib/matplotlib/backends/backend_qt4.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from matplotlib.widgets import SubplotTool
2525

2626
from .qt_compat import QtCore, QtWidgets, _getSaveFileName, __version__
27-
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
2827

2928
from .backend_qt5 import (backend_version, SPECIAL_KEYS, SUPER, ALT, CTRL,
3029
SHIFT, MODIFIER_KEYS, fn_name, cursord,

lib/matplotlib/backends/backend_qt5.py

Lines changed: 63 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from matplotlib._pylab_helpers import Gcf
2222
from matplotlib.figure import Figure
2323

24-
from matplotlib.widgets import SubplotTool
2524
import matplotlib.backends.qt_editor.figureoptions as figureoptions
2625

2726
from .qt_compat import (QtCore, QtGui, QtWidgets, _getSaveFileName,
@@ -778,101 +777,72 @@ def save_figure(self, *args):
778777
QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)
779778

780779

781-
class SubplotToolQt(SubplotTool, UiSubplotTool):
780+
class SubplotToolQt(UiSubplotTool):
782781
def __init__(self, targetfig, parent):
783782
UiSubplotTool.__init__(self, None)
784783

785-
self.targetfig = targetfig
786-
self.parent = parent
787-
self.donebutton.clicked.connect(self.close)
788-
self.resetbutton.clicked.connect(self.reset)
789-
self.tightlayout.clicked.connect(self.functight)
790-
791-
# constraints
792-
self.sliderleft.valueChanged.connect(self.sliderright.setMinimum)
793-
self.sliderright.valueChanged.connect(self.sliderleft.setMaximum)
794-
self.sliderbottom.valueChanged.connect(self.slidertop.setMinimum)
795-
self.slidertop.valueChanged.connect(self.sliderbottom.setMaximum)
796-
797-
self.defaults = {}
798-
for attr in ('left', 'bottom', 'right', 'top', 'wspace', 'hspace', ):
799-
val = getattr(self.targetfig.subplotpars, attr)
800-
self.defaults[attr] = val
801-
slider = getattr(self, 'slider' + attr)
802-
txt = getattr(self, attr + 'value')
803-
slider.setMinimum(0)
804-
slider.setMaximum(1000)
805-
slider.setSingleStep(5)
806-
# do this before hooking up the callbacks
807-
slider.setSliderPosition(int(val * 1000))
808-
txt.setText("%.2f" % val)
809-
slider.valueChanged.connect(getattr(self, 'func' + attr))
810-
self._setSliderPositions()
811-
812-
def _setSliderPositions(self):
813-
for attr in ('left', 'bottom', 'right', 'top', 'wspace', 'hspace', ):
814-
slider = getattr(self, 'slider' + attr)
815-
slider.setSliderPosition(int(self.defaults[attr] * 1000))
816-
817-
def funcleft(self, val):
818-
if val == self.sliderright.value():
819-
val -= 1
820-
val /= 1000.
821-
self.targetfig.subplots_adjust(left=val)
822-
self.leftvalue.setText("%.2f" % val)
823-
if self.drawon:
824-
self.targetfig.canvas.draw_idle()
825-
826-
def funcright(self, val):
827-
if val == self.sliderleft.value():
828-
val += 1
829-
val /= 1000.
830-
self.targetfig.subplots_adjust(right=val)
831-
self.rightvalue.setText("%.2f" % val)
832-
if self.drawon:
833-
self.targetfig.canvas.draw_idle()
834-
835-
def funcbottom(self, val):
836-
if val == self.slidertop.value():
837-
val -= 1
838-
val /= 1000.
839-
self.targetfig.subplots_adjust(bottom=val)
840-
self.bottomvalue.setText("%.2f" % val)
841-
if self.drawon:
842-
self.targetfig.canvas.draw_idle()
843-
844-
def functop(self, val):
845-
if val == self.sliderbottom.value():
846-
val += 1
847-
val /= 1000.
848-
self.targetfig.subplots_adjust(top=val)
849-
self.topvalue.setText("%.2f" % val)
850-
if self.drawon:
851-
self.targetfig.canvas.draw_idle()
852-
853-
def funcwspace(self, val):
854-
val /= 1000.
855-
self.targetfig.subplots_adjust(wspace=val)
856-
self.wspacevalue.setText("%.2f" % val)
857-
if self.drawon:
858-
self.targetfig.canvas.draw_idle()
859-
860-
def funchspace(self, val):
861-
val /= 1000.
862-
self.targetfig.subplots_adjust(hspace=val)
863-
self.hspacevalue.setText("%.2f" % val)
864-
if self.drawon:
865-
self.targetfig.canvas.draw_idle()
866-
867-
def functight(self):
868-
self.targetfig.tight_layout()
869-
self._setSliderPositions()
870-
self.targetfig.canvas.draw_idle()
871-
872-
def reset(self):
873-
self.targetfig.subplots_adjust(**self.defaults)
874-
self._setSliderPositions()
875-
self.targetfig.canvas.draw_idle()
784+
self._figure = targetfig
785+
786+
for lower, higher in [("bottom", "top"), ("left", "right")]:
787+
self._widgets[lower].valueChanged.connect(
788+
lambda val: self._widgets[higher].setMinimum(val + .001))
789+
self._widgets[higher].valueChanged.connect(
790+
lambda val: self._widgets[lower].setMaximum(val - .001))
791+
792+
self._attrs = ["top", "bottom", "left", "right", "hspace", "wspace"]
793+
self._defaults = {attr: vars(self._figure.subplotpars)[attr]
794+
for attr in self._attrs}
795+
796+
# Set values after setting the range callbacks, but before setting up
797+
# the redraw callbacks.
798+
self._reset()
799+
800+
for attr in self._attrs:
801+
self._widgets[attr].valueChanged.connect(self._on_value_changed)
802+
for action, method in [("Export values", self._export_values),
803+
("Tight layout", self._tight_layout),
804+
("Reset", self._reset),
805+
("Close", self.close)]:
806+
self._widgets[action].clicked.connect(method)
807+
808+
def _export_values(self):
809+
# Explicitly round to 3 decimals (which is also the spinbox precision)
810+
# to avoid numbers of the form 0.100...001.
811+
dialog = QtWidgets.QDialog()
812+
layout = QtWidgets.QVBoxLayout()
813+
dialog.setLayout(layout)
814+
text = QtWidgets.QPlainTextEdit()
815+
text.setReadOnly(True)
816+
layout.addWidget(text)
817+
text.setPlainText(
818+
",\n".join("{}={:.3}".format(attr, self._widgets[attr].value())
819+
for attr in self._attrs))
820+
# Adjust the height of the text widget to fit the whole text, plus
821+
# some padding.
822+
size = text.maximumSize()
823+
size.setHeight(
824+
QtGui.QFontMetrics(text.document().defaultFont())
825+
.size(0, text.toPlainText()).height() + 20)
826+
text.setMaximumSize(size)
827+
dialog.exec_()
828+
829+
def _on_value_changed(self):
830+
self._figure.subplots_adjust(**{attr: self._widgets[attr].value()
831+
for attr in self._attrs})
832+
self._figure.canvas.draw_idle()
833+
834+
def _tight_layout(self):
835+
self._figure.tight_layout()
836+
for attr in self._attrs:
837+
widget = self._widgets[attr]
838+
widget.blockSignals(True)
839+
widget.setValue(vars(self._figure.subplotpars)[attr])
840+
widget.blockSignals(False)
841+
self._figure.canvas.draw_idle()
842+
843+
def _reset(self):
844+
for attr, value in self._defaults.items():
845+
self._widgets[attr].setValue(value)
876846

877847

878848
def error_msg_qt(msg, parent=None):

0 commit comments

Comments
 (0)