Closed multimeric closed 11 months ago
You can access the native backend widget on any magicgui widget instance using the native
attribute.
We don't do it in the constructor, because not all backends would support the same api. If you want to use backend-specific stuff, your best bet is to modify the .native widget
here's an example:
from typing import TYPE_CHECKING, cast
from magicgui import widgets
if TYPE_CHECKING:
from qtpy.QtWidgets import QLabel
label = widgets.Label(value="Hello World!")
qlabel = cast("QLabel", label.native)
qlabel.setStyleSheet("font-size: 20pt; font-family: Comic Sans MS;")
# or:
# font = qlabel.font()
# font.setPointSize(20)
# font.setFamily("Comic Sans MS")
# qlabel.setFont(font)
label.show(run=True)
Thanks, that's super helpful!
Just as a thought, I wonder if there could be a nice way to inject native args into the constructor.
The issue I'm hitting right now is that if we modify the native widget after construction, we can actually lose data. For example:
from magicgui.widgets import FloatSpinBox
box = FloatSpinBox(value = 0.14982345)
box.native.setDecimals(10)
print(box.value)
box.show(run=True)
In this case we get 0.15000
logged in the console and GUI, meaning that the true value has been lossily rounded up. However, if we could tell the SpinBox
to have 10 decimals from the start, this wouldn't happen.
Of course I understand the point about the backends, so I wonder if there could just be a qtpy_args
dictionary that gets passed to the native widget if that backend is being used. Then I could do the following:
box = FloatSpinBox(value = 0.14982345, qtpy_args = {"decimals": 10})
thanks for following up, I'll reopen until the discussion is concluded. I have two thoughts here:
first, unlike styling (fonts, etc...) anything that is value-related (like decimals) definitely is in scope for handling directly by magicgui. So if you can find additional examples where the value itself is being modified, definitely feel free to raise them. In this case however, the step
value for all RangedWidget
subclasses can control the number of available decimals:
from magicgui.widgets import FloatSpinBox
box = FloatSpinBox(value=0.14982345, step=1e-10)
print(box.value) # prints 0.14982345
the second thought is that even QDoubleSpinBox doesn't have a way to set the decimals (or even the value for that matter) in the constructor itself. So there too, you must instantiate a widget, set the decimals and then reset the value:
from qtpy.QtWidgets import QDoubleSpinBox, QApplication
app = QApplication([])
box = QDoubleSpinBox() # no way to set decimals or value here
# has to be done here ...
box.setDecimals(10)
box.setValue(0.14982345)
so even if we did have a qtpy_args
dict... we would A) need have an API adapter to convert keys to commands and then B) perform something very similar to the above... which can already be done without using the backend API:
box = FloatSpinBox()
box.step = 1e-10
box.value = 0.14982345
print(box.value)
did you have any additional thoughts here @multimeric? I might close this otherwise. It's still possible that someday we'll have a killer app for providing kwargs to the backend... but as described above, i don't think we're quite there yet
No, if passing args to the native constructor wouldn't help with this issue then I can't see any immediate need to implement it now. Although it probably would come in handy down the track.
❓ Questions and Help
I'm trying to do some styling of a
Label
widget. I want it to change the font colour, and to enable word wrap so it doesn't force the containing panel to be larger.However, there doesn't seem to be an easy way to do that in
magicgui
. The widget constructor doesn't seem to pass anything to the finalQWidget
, and I can't work out how to access the CSS that QT uses either. Any pointers here?[x] I have searched the documentation