-
Notifications
You must be signed in to change notification settings - Fork 39
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
feat: toggle switch #284
base: main
Are you sure you want to change the base?
feat: toggle switch #284
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #284 +/- ##
==========================================
- Coverage 87.28% 87.00% -0.28%
==========================================
Files 47 49 +2
Lines 3554 3772 +218
==========================================
+ Hits 3102 3282 +180
- Misses 452 490 +38 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
why is there a need to have two separate class? Why could it not be as QCheckBox that could be labeled by additional constructor argument or call the method? Why does it not inherit from QCheckBox? |
Hi @Czaki , thank you for your feedback.
You are right... 🥲
Is there any benefit inheriting QCheckBox? |
thanks @hanjinliu! this is awesome. and something i've wanted as well. I agree that a single class is probably sufficient. Since this is most like a QCheckBox, making it a drop-in replacement for QCheckbox would be great (perhaps you already did that? I haven't looked closely yet... but the methods should be the same when possible). Inheriting from QCheckBox would be nice for isinstance checks, and |
That it could be used as a checkbox replacement. It will make mypy happy to work with function that accept already QCheckBox. It will be easier to use in code for autogenerate GUI (for example, magicgui may in some moments allow configuring toggle switch in place of check box) etc |
hmm, something went wrong in old pyqt6 ... but probably we can just skip that test. |
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.
Thanks for your work on this @hanjinliu, I had a moment to take a bit of a closer look.
I think there are many things that could potentially be improved with regards to making this feel more integrated with the styling of other widgets (things like awareness of widget active state and possibly hover state). and there's a couple small bugs at the moment:
- unlike for QCheckBox:
checkStateChanged
gets emitted when you click on the button, but not when you click on the text (even though the check state does indeed change). - the sizeHint doesn't quite seem to work for width. if you enter a label with a long word
QToggleSwitch("SomeLongWord")
, it gets cropped on the right - All calls to fixed sizes need to be removed like (
setFixedSize
andsetMaximumHeight
, since those always end up playing poorly eventually (even if they initially solve a style problem). I think this means you'll need to add more logic to determine the exact rect for the rounded rect (rather than just assuming you can fill the entire widget width/height). def size(self) -> int:
doesn't match the parent API.size()
needs to return aQSize
... so can't be used for as a synonym for toggle switch width.- in looking closer, I think we should subclass
QAbstractButton
, rather than QCheckBox, but implement as many methods as possible to mimic the final QCheckBox API where appropriate (leaving out things like tristate compatibility) - Since QAbstractButton already has
text()/setText()
, I think you should use that rather than creating a new QLabel widget (you will need to add it to your paintEvent). This means the whole thing will be oneQAbstractButton
rather than something containing a_QToggleSwitch
inner widget. (this avoids a couple edge cases with composing widgets too)
When implementing paintEvents from scratch I think looking through qtbase is very helpful for learning patterns. for checkbox it looks like this:
first initialize a style option that contains all the instructions for the styles (this is a nice pattern that first puts all of the style related things into a single object)
https://github.com/qt/qtbase/blob/3c919b6d0df486b7319faf8e4f366ab457e9f852/src/widgets/widgets/qcheckbox.cpp#L286-L292
use that in the paint event, calling lower level primitives to draw grooves, controls, etc...
https://github.com/qt/qtbase/blob/3c919b6d0df486b7319faf8e4f366ab457e9f852/src/widgets/styles/qcommonstyle.cpp#L1410-L1429
but, to be clear: I don't expect you to necessarily reconsider the entire design following the C-style patterns just for this PR. I really appreciate having something rather than nothing, and what you have here is an excellent start. I would, however, like to leave open the possibility of adding even more low level native integrations in the future, without breaking things.
maybe just address any of the points above that you think are important before merge and ping me when ready?
Thank you for your review @tlambert03 ! |
Hey @tlambert03 , I think problems are solved. I also added |
this is fantastic work @hanjinliu ... love what you did. I've made some comments and suggestions in a PR to your branch hanjinliu#1 |
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.
This PR looks really nice. Next to @tlambert03 remarks I have few small.
assert not wdg.isChecked() | ||
|
||
|
||
def test_signal_emission_order(qtbot): |
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.
def test_signal_emission_order(qtbot): | |
def test_signal_emission_order(qtbot): | |
"""Check if event emmision is same for QToggleSwitch and QCheckBox""" |
self.on_color = QtGui.QColor("#4D79C7") | ||
self.off_color = QtGui.QColor("#909090") | ||
self.handle_color = QtGui.QColor("#d5d5d5") |
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.
Hm. Is there a way to integrate it with qss styles (like for napari). Especially for toggling theme?
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.
He made them Qproperties… which I believe means you can style with qss
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.
Thank you for your thorough review @tlambert03 ! I was wondering why my widget didn't work with the super-class methods but |
suggestions for toggle switch
I have been using toggle switch in many places of my repositories and I thought that it would be better to have one in superqt.