-
-
Notifications
You must be signed in to change notification settings - Fork 8k
Simplify and improve Qt borders/spacing tool. #8683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Replaced sliders in Qt borders/spacing tool by spinboxes, which 1. should be easier to set to an exact value, and 2. do not continuously trigger redraws unless the user presses enter or uses the arrows to step the values (the redraws can be quite slow when working with a complex plot). The spinbox step size of 0.005 was chosen for consistency with the earlier choice of 5/1000. Greatly simplified the implementation. Attributes on the SubplotToolQt instance are not kept because it is impossible to keep back-compatibility (the sliders simply don't exist anymore). New attributes are all private; only `.default` (which has the same meaning) is kept as is. Tested with PyQt 4.12, PySide 1.2.4, PyQt 5.8.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -782,97 +782,47 @@ class SubplotToolQt(SubplotTool, UiSubplotTool): | |
def __init__(self, targetfig, parent): | ||
UiSubplotTool.__init__(self, None) | ||
|
||
self.targetfig = targetfig | ||
self.parent = parent | ||
self.donebutton.clicked.connect(self.close) | ||
self.resetbutton.clicked.connect(self.reset) | ||
self.tightlayout.clicked.connect(self.functight) | ||
|
||
# constraints | ||
self.sliderleft.valueChanged.connect(self.sliderright.setMinimum) | ||
self.sliderright.valueChanged.connect(self.sliderleft.setMaximum) | ||
self.sliderbottom.valueChanged.connect(self.slidertop.setMinimum) | ||
self.slidertop.valueChanged.connect(self.sliderbottom.setMaximum) | ||
|
||
self.defaults = {} | ||
for attr in ('left', 'bottom', 'right', 'top', 'wspace', 'hspace', ): | ||
val = getattr(self.targetfig.subplotpars, attr) | ||
self.defaults[attr] = val | ||
slider = getattr(self, 'slider' + attr) | ||
txt = getattr(self, attr + 'value') | ||
slider.setMinimum(0) | ||
slider.setMaximum(1000) | ||
slider.setSingleStep(5) | ||
# do this before hooking up the callbacks | ||
slider.setSliderPosition(int(val * 1000)) | ||
txt.setText("%.2f" % val) | ||
slider.valueChanged.connect(getattr(self, 'func' + attr)) | ||
self._setSliderPositions() | ||
|
||
def _setSliderPositions(self): | ||
for attr in ('left', 'bottom', 'right', 'top', 'wspace', 'hspace', ): | ||
slider = getattr(self, 'slider' + attr) | ||
slider.setSliderPosition(int(self.defaults[attr] * 1000)) | ||
|
||
def funcleft(self, val): | ||
if val == self.sliderright.value(): | ||
val -= 1 | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(left=val) | ||
self.leftvalue.setText("%.2f" % val) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def funcright(self, val): | ||
if val == self.sliderleft.value(): | ||
val += 1 | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(right=val) | ||
self.rightvalue.setText("%.2f" % val) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def funcbottom(self, val): | ||
if val == self.slidertop.value(): | ||
val -= 1 | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(bottom=val) | ||
self.bottomvalue.setText("%.2f" % val) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def functop(self, val): | ||
if val == self.sliderbottom.value(): | ||
val += 1 | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(top=val) | ||
self.topvalue.setText("%.2f" % val) | ||
self._figure = targetfig | ||
|
||
for lower, higher in [("bottom", "top"), ("left", "right")]: | ||
self._widgets[lower].valueChanged.connect( | ||
lambda val: self._widgets[higher].setMinimum(val + .001)) | ||
self._widgets[higher].valueChanged.connect( | ||
lambda val: self._widgets[lower].setMaximum(val - .001)) | ||
|
||
self.defaults = { | ||
attr: getattr(self._figure.subplotpars, attr) | ||
for attr in ["left", "bottom", "right", "top", "wspace", "hspace"]} | ||
# Set values after setting the range callbacks, but before setting up | ||
# the redraw callbacks. | ||
self._reset() | ||
|
||
for attr in self.defaults: | ||
self._widgets[attr].valueChanged.connect(self._on_value_changed) | ||
for action, method in [("Tight Layout", self._tight_layout), | ||
("Reset", self._reset), | ||
("Close", self.close)]: | ||
self._widgets[action].clicked.connect(method) | ||
|
||
def _on_value_changed(self): | ||
self._figure.subplots_adjust( | ||
**{attr: self._widgets[attr].value() for attr in self.defaults}) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def funcwspace(self, val): | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(wspace=val) | ||
self.wspacevalue.setText("%.2f" % val) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def funchspace(self, val): | ||
val /= 1000. | ||
self.targetfig.subplots_adjust(hspace=val) | ||
self.hspacevalue.setText("%.2f" % val) | ||
self._figure.canvas.draw_idle() | ||
|
||
def _tight_layout(self): | ||
self._figure.tight_layout() | ||
for attr in self.defaults: | ||
widget = self._widgets[attr] | ||
widget.blockSignals(True) | ||
widget.setValue(getattr(self._figure.subplotpars, attr)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then I would probably use the new dict() method to make a dictionary after calling tight_layout, and use that dictionary to replace the getattr calls. This is a minor matter of taste, and I wouldn't insist on it, but to me it would be more pythonic. Regardless, having something like the dict() method available would be generally useful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've never used |
||
widget.blockSignals(False) | ||
if self.drawon: | ||
self.targetfig.canvas.draw_idle() | ||
|
||
def functight(self): | ||
self.targetfig.tight_layout() | ||
self._setSliderPositions() | ||
self.targetfig.canvas.draw_idle() | ||
self._figure.canvas.draw_idle() | ||
|
||
def reset(self): | ||
self.targetfig.subplots_adjust(**self.defaults) | ||
self._setSliderPositions() | ||
self.targetfig.canvas.draw_idle() | ||
def _reset(self): | ||
for attr in self.defaults: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
self._widgets[attr].setValue(self.defaults[attr]) | ||
|
||
|
||
def error_msg_qt(msg, parent=None): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest making this dictionary generation a method of Figure.SubplotParams, so the line would become, e.g.,