From dac6dd3158ef6b35611b74c516be0bacce65ed6b Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 10 Oct 2022 08:23:30 -0400 Subject: [PATCH] Deployed abf544c with MkDocs version: 1.4.0 --- 404.html | 16 + __pycache__/_macros.cpython-310.pyc | Bin 4475 -> 4475 bytes _auto_images/QDoubleRangeSlider.png | Bin 2450 -> 2556 bytes _auto_images/QDoubleSlider.png | Bin 2266 -> 2338 bytes _auto_images/QEnumComboBox.png | Bin 3019 -> 4408 bytes _auto_images/QLabeledDoubleRangeSlider.png | Bin 6418 -> 6516 bytes _auto_images/QLabeledDoubleSlider.png | Bin 3631 -> 3694 bytes _auto_images/QLabeledRangeSlider.png | Bin 6112 -> 6195 bytes _auto_images/QLabeledSlider.png | Bin 3092 -> 3167 bytes _auto_images/QLargeIntSpinBox.png | Bin 3356 -> 3501 bytes _auto_images/QQuantity.png | Bin 0 -> 3720 bytes _auto_images/QRangeSlider.png | Bin 2450 -> 2555 bytes _auto_images/QSearchableComboBox.png | Bin 3084 -> 3375 bytes _auto_images/QSearchableListWidget.png | Bin 10743 -> 11059 bytes faq/index.html | 16 + index.html | 16 + objects.inv | Bin 1171 -> 1266 bytes search/search_index.json | 2 +- sitemap.xml | 51 +- sitemap.xml.gz | Bin 389 -> 395 bytes utilities/code_syntax_highlight/index.html | 16 + utilities/fonticon/index.html | 16 + utilities/index.html | 16 + utilities/qmessagehandler/index.html | 16 + utilities/thread_decorators/index.html | 16 + utilities/threading/index.html | 16 + utilities/throttling/index.html | 16 + widgets/index.html | 20 + widgets/qcollapsible/index.html | 16 + widgets/qdoublerangeslider/index.html | 16 + widgets/qdoubleslider/index.html | 16 + widgets/qelidinglabel/index.html | 16 + widgets/qenumcombobox/index.html | 16 + widgets/qlabeleddoublerangeslider/index.html | 56 +- widgets/qlabeleddoubleslider/index.html | 16 + widgets/qlabeledrangeslider/index.html | 56 +- widgets/qlabeledslider/index.html | 16 + widgets/qlargeintspinbox/index.html | 38 +- widgets/qquantity/index.html | 1468 ++++++++++++++++++ widgets/qrangeslider/index.html | 20 +- widgets/qsearchablecombobox/index.html | 16 + widgets/qsearchablelistwidget/index.html | 16 + 42 files changed, 1938 insertions(+), 77 deletions(-) create mode 100644 _auto_images/QQuantity.png create mode 100644 widgets/qquantity/index.html diff --git a/404.html b/404.html index 524a0ac..dcf7b87 100644 --- a/404.html +++ b/404.html @@ -419,6 +419,8 @@ + + @@ -589,6 +591,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/__pycache__/_macros.cpython-310.pyc b/__pycache__/_macros.cpython-310.pyc index 0a7a7885f4409e11cce67f161515bc25a04a6846..6d9de98038686b3e59cbe13c6e6f7a5d267df26f 100644 GIT binary patch delta 19 ZcmeyZ^jnE5pO=@50SLC$Z{#Wz1OPhH1xf$_ delta 19 ZcmeyZ^jnE5pO=@50SKNIZsaNy1OPj%1#AES diff --git a/_auto_images/QDoubleRangeSlider.png b/_auto_images/QDoubleRangeSlider.png index 86c26f93b11fa1cd96e2acac13deb8fd5b5ff4d8..bd6696622ab420cdcab410538a8a2129b581ec6b 100644 GIT binary patch literal 2556 zcmc(g`#aQm8^=FmXAmQ!^=OF8v2~2mI!rWVB&3Fs9fy!Zm{nxfnMAY8rZlOfl7__) znz6`frX13;yVQtgtq^M->oAR>8AirozjZy=^A9{fJU@Ky_xJjKKi7TV-}iN2uRGs| z;I5*ir33&_@$@+A3&0oi(6f)C925~h|7r)xt^|+3L;#e({B&TTq!bOkV|gBR@k=We zPI_M$3DW9c;dfDPx9eBs+9)=*n~_n?IXVaMRJU|Pu~wROGrbM$$u=^2QRcRHQ0{Wl zevO=xVjJS|((2ks+29P46l59q?VcKAsVuO(xcX3N09P!Cl)WI^J^0i`_gFMR1}OmA zH>P((LeBZ$q?^75n-;kpPk(<7+579X2LM!Sh#W0f&~ z4H~pZHVt2`?ksfO{cIR*kXNVAK!HM)42@SLQJg?9q zN@QD1CNqVTCI0(m5Hsa{!>C|2RrK!8z-(;GVmiGf7J23-9E1hW2M#Ir=IC559q(^e{cYb`7-*{laNYxrF~7~mh_Qd1O{&<~!-)d>nX9FDH@ zrQnbdrk`2OB`&Fcb&*#u7;V_Alq)f-D&H*!j=6HFv`_bw$ku2iRd0P`Rq(xnYTt)f z-t@yA7e6+MWHdhVhBaihPKHL((S-gqq9s*1UK#p9SrV$x!yXrFG z_I7q8e}Ch~p~c0;zP`StC6*aAf;=7q0D($JFx4ikqb1h0nZ{@X@FJH=}qL}8TEt%Bb-k$fRGZiKe zrs4B}_h9hUf}=RoDUsCiA&rk6vslCuYDN~Mvcom10DA~>$vvUp!%y?=)KpipfK)7a z$4)+%on2<2_}{Olj0dN4!`EjA?glZ7XBS(7gadc2!qH9r8lRmRl&3lpyj4^yOq6;t zGM-c_tu%?qfdTBU42|fVta+KqRrcgk7-qUTono^ZcIlRp3u=(djmZZ2soP~cYbp&! zNH28tbO8cvUM<3Zh3{*+uss)gNVe+5@U48koHb>0a>T|n5L;3-Oeu|MB#$dJZCt)k zVG`RmzF^8Yn^`)Pr?f;=*UY=QV(UJ;c&Dzgu`nO=_`SaZn0JTL`8W7ApXngg*ItPl zx9ibyFLZuEnTT&2nEjBD;*6R|O-)tlMQ@)j{8G8gfMJ7l-QxWGbKw@u&&uzI_c2|T z;7H`b+R%IJYeMJK0RexGjWt>fG+9s`X@yRTKdo&~O->%Tb9}*D6)x=w3oEI1U^F?M zAbaq1Oc^5CSc8*DhF^o*E6V|b$8r7JAHS7YOi91d_3SM(GQu20XqI=B?BTm?CrL%XQCgP9~0d?ri) z-}cSOcyu~ycb4y;m#696xvuOTR%kzN2^++&FDPmnJ0Gn((WZ4k|AVHL5*R9N%bHdt&;H78?r=VbkNtRY`;kyD7u6c) z9pxQQc1K9DG@btRo$W1kTKVXvsH?8iDh;m-5}rJXLAWe$XMHXEg4{N4A3w32RYuPx zVwf)$YT1$Ftx+e#jgwpUu{I23JQ&FMDJEP#KvmbNbj|vRSMP}2cJi&E<|%$72;&!z}NL4_hI7 z&uggk4vC)zTe_>kL8&%QnQhq4m%K4fxnI4&UK$=AZjRwL1xi1P=e)eUSb{nO4;?tr zzDCd0Jd)7==*<`Qx%eLOQ&PR{!fX(eWO>(IU1^cf<7uS;?(LUYkgq2y8hR?AJAzq3 z%xFw^+S>cTmY|ajhYqp06w}iWm2vB{5{%nW zAdCdHZACCFh)v6}c6L5vb|CAik_F!$6sA`AvU{S3^UCutk3v zE&lDcarWkldq?oAIdPqwFB}F8D`H&SA^w~SQm8a}J3cN*;q2SD4}Ybl#db6~Tflsd zxws*zMa>K|ynczG#K#ka3^xQE6d-WQZ}r4FeP|cd8$q(^tZ=;TZgDYf zYZc;M+l48uJYqfX;*`Iu@^~vRBwth88BB}5rz5VTCal$B3)K24>TcoaC7}?S>i9NJ zOG{MXA2Tx%OcDp$gpC2}_$1CGv-&A4XMH~JC&`Xrwp&bA3;?j( z!W{1afZzmN+llUgcj14((Su=EusJad0CDN-Zl`}ioVJjVQuzm4V zWY)_b(me++GRo6);0*zzQc2%>vxSgqZT;6{EoZiNW$57qq$R`C_IKW?`a5eBhp0pO zUom5I%NrVqH(fEv^ywcVofc(|YTLQc>ueZb_rL{U%fFI`;U4(k0$qDnzKLdqN~jKe zQtXF_*#Vk5Cy4CpqH~GoXtQ-Sdy0!?1J0fl0bGFRT`yg{$kVl#+Mi8oG6 zDAF3gRoc9|p(sk`Q(RZu(-d+EZlPBPFfF-YiarS-(3Ip z;wtgMRo`qCF(x{`2M3yzyQ&n$Sq??kF$$RLOzAtG`0mMYg01a!R^Ofd$Hn5C%NpG@ zkd3k5?{{8X{$3x@?^)bUJ1+(3A^F}oC85X^9xFe7x^{eg{Da?@PKN%2s~aE8YRcC> zw%jIbRkPVXL?_)gI|Jce03{NQe0nap{crp}yBu$S7Rk)aYyzzJou8XCie5qI5*UTO#%%z& z8?0!&NgPgHoT#9)NM*hLN%4R2`L+ZC zsq6td&T_~rQUIWYu;LC!*j@;{@JvJb zjz21;D%UZ#RC1|8h4X2eU(qpE8I_sa3J;Na`!btI3Xucv2OaGyP5=0S(K0IawUeK_^kM8h$| zTmr{U-$p0T)P`5epUx%RURx0Wx1eAmU{&~x{J`qE+FIH1+LDrz!N7+~u+?%{@k&^U zd3Q@0nU6Ix(vlGiDR)E5q^700^2ZLi0J=+e73QGm94ZfWC@OEfHgLTpvd)#ejB*EH zCyv{Uz?4(xZ@5+U&U}fkXYALP*8ePm>+;e4JU%`$^ozC11+~oglfM`GW*3IE?f{#k zS}UcYHP+l_dNW4XMkmwqKwD<%&9Q^rWj_`v+rk?y6EuvU1D7L4c|8~2Sdzs4eIGCIF{ud2V|eDEtO?%S$X6hUq(BhFpC z__|SCTzql9skzyt$T6Ab3h4E5idjzFS~k0j;>xGQ83sxYiXP6}81iGC_|1BS2lwDl zLxb!oVn<3#Nl{c0E#ar-x27h;v+oGQK1#cKC1b7ZWy*b;I+8+xOfD5V0 zkR$F>n+G~7tOsm(^${*=rw-AiTyGViEuVBJetg}{*Ok4Sbx8>PNk8_rbn~xW>m?Hl zk`MnN$6WY3b9m0+UB%_b)(G-QD#J8#;jW1ahaA!KkpL&I_@N_`V>R#yBH1W zI-+He%G=_Vq-ANRSgY^?t7ABM-xT&}tXqWl<53B(Jr^f=&$Q>yzHlDBi2zN*t#@O2 zQ^X{^$r&|e*|Z&7GBz;3aJliqcAQ$WC#uacFGy@Mad>X6!8iMIDp9jT)%PSMo`f4Jjzfbt+Bq|p9uZ9&9Slx zVwM2Zx8*=^y0uC`f4Nghx?4G^Ohqc`%86s;GC3=ufKD{w#`PE^VD9_Se>GQL`W}lA zOyO`iu|^8HVOPSTjU;~>0nw_iDc4RU5_@}le;Y6{G&EFKS5F;Tm^uoYg0~xSd++%V z#!Xp|9&xXnSX*05clM#tjMLx#$>r+Q0)V)kCtL(UzO%S^sOy{DE4!-YXuIygM-wiQ42i= zMb6CeY%)9t{}YlS$y3l*4<9~+I3FFw+h=rk+H_QIPCX&>sjG9jOtgf8k#&JXSXkI6 zBFXVAXmW-FLO#y0jk~&mL14MkUMUcl8psw*?DwUyrKKe}AJj69Xq%3b z9;gJins&m52w0DVAMcGbR53}>jvZP(!=(&%baX`24f^ZZ+S*cFA>lM+#H_5WiX1KN zGp<$LfTKzS$>nmXL)`J@BF8^Ma%yT$byOl+BqiQ^`Urq5A*cpiaQoB5)6db#=y;AB zBst}@Je+>~FK4*RXI}ggm6q#)daym^`d|8HdwL#j+qYc?zPn0M7-mw^D3joU7Gt9P z@y1do2`Om&$2;#Z4x0eH$oKx3s#C}j%nD)V#CxC{K2QcRo3tL&tz&x9m+=?VmPA0} z0jzkW+$;Hz#6sBrf5?5$senGo^#1rxiG9Rr;Hm_;Ck)@%9Yhd@Fi<`lEb@O03&t}{ VQ|wFkD@rg4U|~wYmz%i9{Re2sKK1|r diff --git a/_auto_images/QDoubleSlider.png b/_auto_images/QDoubleSlider.png index 9f4666a2bcdbc8f54dc70e3ace5dd444c36b6669..17ed257a393811b79396382d29484dba977f9ea7 100644 GIT binary patch literal 2338 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 C_%ZhY literal 2266 zcmb7GX;hO}8on_{0|?1XMR8;+4k}h941<7%kQ4=q$fBbW5R!IUL@@$UWD8pbh89^Y zQ5e|^xIr;3TLL6TL_}nhrh!Q$ffzMH3?bMMLSpEp=gc|tV}8usbH3$#=YIEn-uph! z^WJYmgZ(YcwwVC{ECN0|d>jDeTlgMovJT$Y|M=7$K1>rn3%>-w#!YJ%0#sCO1;C^* z;P9s>QmT~Vk$CH9yN7D^i^sH=w;fDrk(<$XeS9L{7Hx1CKeS@SI==g(<0ogHBdrdH z*fgvdq$;(C*00PX@Q8i36oPa#0vx?CIpC$bYzAlvK@^AI-TKPJ0PFKqzJ&8>Us z%JZ=u5eOV&X3iuzyQxB@A;f7TTFQ9DUgU}E38=d@oJW0D!m4R*tNX5sJt;bL=z&MJ zbw}PX@I$RaYFTu6#clp<;!>rdUo-7iIpWuFtXVLpN&DvCGhN@v73V5O&$KxPlsf8k z^4eXDL5*T^IzuZS85s$_v&nZ{C=?ov#@^oE@$q9l;>^_#TA63Dj7?_de}mE87bBYL z-EGj*OLicIYj8QbwK-%b!wO3-^lJ$5)-_J6cuQlboL=p87O%Toq|k_zN&kF2R$Gs# zdzFhL3O~d>uW=k4D#v0l7~b;BtDeQHzntC?u&9}&Fk4zKP^ph;RV9)?51au=_FE6k3#aDy=_8IN%?bmCozHP@5yG)a_j}M`g<>lov z^>R5SvnyF8u}+oeW9%iI)V3GO&WIM>I1apaoI*T1|3Kv5Fg`dqSdB}T%;>Z9O4iWO zP;+y$$hOWf7f(k516}8TjPHi`_O>e-i0>3NICWo=kEVEedwZkh2}Wi048qA&iVpSD zjV~qK&qz*ArqlJGY!OK$60sPM$6HA4xbqG_0M0&GokpJyN@S!LeTfg3|$;?c1&3o+tIAl#=R13M!=UNtZ7>HmSQofmVt+=bnOr_XKc(&4Vp z=Jxa)-N}&2WTfVk!}TpB#qx5B>rFPxoOl4P{=n%Ln?0?dr_0gTQ%t3I|fWyeN>kV*X_#vTAO$bi3k z#eNL}fk2m(wPUKJxVYY_qPCU&71DBdBr~QhyoGd{LcwMt6$*vFzkiWm!}wXKsw=PU z|6&#*@WkVz!ovr%^hemWwY739MLo-uXz6>&-ZW#6e>8;nFQU?;Uxk>7-@}`mi0xQN zy`!5pON4T-&a$oMxYA%vIc&Dc*swk%3p^AI4k*LRiUwpI9UWIZTZ$#@MLp z;20x|nM=1BsI08y8CMiS;mt4SLH|%6zMx(#7Gns8A7?DgH{|5y<+=2lda!nJ&pChG5D28qx^zFS#cw`3Azt`pe7N z7foBHsP5K9e(L6Y96KLdK(Wmx%ygTFZkM79HED27F(>ts%T~*-mCs#LR9xstq`OJ7 zr0nB=oCmiyiMZl8LdHt_)62Eq8KO8=^)^bN#Wwm7sG=Nga{=F5B0X<@JSQzxa z-!-^{uy50VdSYUt!M~&+T-(fiAQFiRWS+S_Nhl}lHEBr?)dvO!DwFgJ3kyxt=Q$`$oVZ&soA`+Pf*I!kjAmA6vt29fyD2?M7owwIt7QYHetIq&C^*Q$8;Ja}2FMyk6)lLkLazYlD(ts9Q*lP+9PA+lGU)=b;Ia>N;n9UC2m{0t#{ zNK{F<8jWUEhtKbm_T^&;%QHEU;?SC#qM*{NV2~b;_zr(or_(_To1c%f^u^(DG@I3X ztRtnbhOoTC`nOOo(9y15y(%@9z=#GY*8Pp=Dx!sn2Q3=3>J+c7=B<16zw$#^otVi(b#XX0zH5#OI|rnQZZW#zHkTZqn%c#m-Rtc9ga-N5H)3xgLNxiXktYJqYMlyv z9#F_@BX}octr^`6hB>)$KK7z_2&qqKHUqRCaa>2l7tiec-oX?iAP&v2oL&~~@UqXv zd-deoMHdq0r<&S=@7{rvzofsg1~VZWO>3gVmpfstDpxr*a)LQ_BjwdCXCa~qn&gR- z-k*-OzAL#D$wV6LArEiJM_oV`s-_AaDgK8h{eN}z|33L40i?ZKf3SUnWh^`|fB@g% K!}onYzw#TM%5%5? diff --git a/_auto_images/QEnumComboBox.png b/_auto_images/QEnumComboBox.png index badf4c078de93ca3926fe5d928bd97141b1aca89..53ff344a0d9b1057aa72287c58d342a803d6b29a 100644 GIT binary patch literal 4408 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 literal 3019 zcmcIm_gj<67G~8I7X@T3G?86c)JGJMg&?RwF)F$SkQPd)N-#j^5G5qYMG#Qr#u7{r z&_#j?QUnu1f`qd45|Jj5vMeAHAc&OE0(atHaDUl(o^NKpIcMH8r_Gr(2fItkN?J+^ z3JS`XZDEcI3R}N`xxcGXl?> z2l{kt=R{qoimVXG+isFGv$$#aBlN{JHMR z!RiYJ!XtkwyE(jZHt^L_st-C(D?8!nqPtxhv{85Uy$9v; z+S7Rxo{zLw;-T=K-q!k3NtLp+-n;TxyBWN}j&*!+BN5Qo`>0$F5X6MQz76|F>>%INU@7`EJugE`irNF`wes(a~|k zlx&D7*|z0}!oU9r!ivVm#`uU&2r`x2K5hp0tU$q!?4?LcHuC&swK=gr@mGZYPQs3uwL@ zTH4zBL|aIK^D-)#8EhSzYdQs8w_SLb+ z_7^W*I(6z)7+1DbF46>eZZ?6u+?na=-WV^Kcig0b8agb@cv8m<{yV&9{J|P>q=dD3 z_-~K*-&hT%8^7l7jLlj7=mreC)oT)t zUgSg$_GfwYyX~l;%Ran3p9ZV9>=_&!6p6UIXS`4I+e4+IgiSA)SS$vnSK z(p<2o_UDf=cvnUd?Zjng$e&bjWKQl8EvD6PTwRLKvmWk;xD@9hB zT3QbB`N)siOa=pPZ=X%2)wqm!BM{Pgp7niOqb!b8h`VrOR`}lj%;J+&Bs+Q%h*BqR zRa8lBQPhn$fj|!F2?PRh7_og^MHjl>plXe*zI6>24;2kDf=^jlvDxfio0Y`GMEu&4 zB{n*AsHdj_Gt7LnT^>>V76DdNtfEvTxW-CH`TEv&zFITpu1C&yT7V$pimavjFB*02 zjwktPBr6v`?Aun2lx3ZT$+I~hlCzgsS6BD=u>JlTSJ=kNM4lHXHs=)94qt?(1h|im zj^0z%J$UdS0fb$jXJ_2g)!6>aK&CHLMaL?7`qSHH-Gp^Er}_15sYD`i)V&sS{an3l zd2Vziexo*V>-qEN=WbP(mfFMU^mNhGUuk<@I((Td%nJ<-ec0$f)nB}aXk4>wODjwqBtSDox2ugZU@Mp7!}~xDO|`I2D$EP3@=cNp!AYN3snbj}Q7aV{~nn zt4^d+sp>xQ*K*Kk^le}!AHvEw(#QhX`S$$h@RQY{0;|A59zYj}_5x+yHunF zrJeNHDz*S;m6QAInOg-a!)oxuhp%0yW{)i`1HL;3<##x3Pez7<)YTZ-W4*n-OEbeh z_{Bb8;mOI#3%Xi>sq6^}!79ph%?aS;o)OPyM|*89^w?u(g@XQmX4FI%a5B=U^2_z_ zS}lTPmx#DN7}6~-5S44vS?jokn~h=bt4VE0#F4#mn=+|=j#UhB1dtJJg`s@@`n^r$ zC2R8KvKMVhTCd3t8XOWX|reG6U}6*(ym*cGX}a#Ee+ zBL}rdBwttJvHXbUDBc-qr-kTlgP)oueszJ7Wr=Ir3iRF=J=UUD*n*3TyLjC; zlLQgG7`W31u~cFE>sZFx?Q4ykc=WJW&pUA18a8`~IWypsARD=-D+E^TFZSeatOl#0 zF&IG&o)a}kcPaAl@PLhd8*eXtzvO|#t+hTroE0K}hAd}N%x9szpi(zh7JMI9G@BPA z)OEP|Lc4KY`2BVy8qvubdQqfZbrJ{{K~Xa_ zvynqSx>8U-67J$cRCSHq>wYvJO`)Pk!cXS$3LR-z9_$7jZj+8QXK0@4y#{*a1jG4a zglju2zdPDW1}-S)o38;!t&+Tq+ZE<_zs~NwalnGF^3iXYiKc+JPIjl5Ety}TP$($; z^!L*JXSA1nfg=+GN*BYfX;z9j#xHmwh^j&!dfXjzMk@niX4X3}Fwon};&bKdxg{QJ zZ@XbS866iC6ciW7W-=jK87Vd|AJM&#DI9iQ8@9nDvI+^wcJY~CsSa?bqKBBr^~8o? zYuO{(0qIISf$M`ebv$`MCD}$C{L5~KR_~9ySX1}h%sbN}8N92|JValpJ1O-O6V8x3 zA-$p@KW_b<_-Ns00gquA+Tc~P(fs0}jKCc-6f!aUB#tHmyE?$>d;6$))(xfO=AaoF-C`d<&AT>$^q&E>T(p032 z^penP=tX+FJAUKdG46P8yninPID3$jefHXWuDRx13BRkYMo+^{13?h|ZFPhm1d%R) zu?5u`@K@n;o+`LdyQ!OaKoBh}@s|WjP3MFlF45ZvMSb7&mC=B^Y({mI>y}-S53KaZ zNWW7BA&M(M!!H~R0e7s?BDJ+zS(`7J^XyuaK6mod zRoe$WCnGCM4ORz1{I2)jtE8r(gMqgTG1cR+AD3;t-7w@d}auJ;^}4 zzJ$@zww{FoTh(769|Ox@bK2w){92P@W6wQM$BZ2H-nD$<~q|V%F9_;St}|kXlZHN z+uL8tjuAZhWxbtS$DpPDyIA;Ax~@y1LyMc}l4MP3IgQZ zqU*Cjy_ISmw=V7*-)KFkr1P&isw*3s!|O%O9GGCj-3w{pS^&W7TRJ7v@Ts>h@I zTl3-e<8^_4etv~z+1cl0WwG`33V;1IvpL%?n&9w)s73PHBe? zJcRKG>FMcNppL!ry~IHZ-4!%JZtjkw#s>ye5he8} zp9A`}5x6Q>9d&g<;aFLoxFjKUkVbX|MMZWzuC?1qsu=h2O0OkDZ=rr?SS;@hfR&E? zzOA=6jE51Qos+{7Cm!LmHnzPW4WKC|)_gp1{$36nJ3C9<=;M07tsK{SX6PxhH9i50 z#SZ`I%ezOpW*5D?HZFj_LWC>Z>RV?$;h@!;dAK(hU1(vU#I8-~R<6P^0lQXrxL8m^ zv1Yw3)9kLJa4hZQUSn3}Ixd<84v#VD`<>4|tRiF(nUDz*>FAhmS|plPQg?8NO=Z`- zv$Jy?bt=c)nIUWBh%gPEc=nYqG5Xxp`nsFi!6Fg522J87bIRPBvos zrap0DZdmJ5z)}l0NgNaz3wzv?Be2*As4U%usoXV z^Ph0+P8)Y~q&7A-oH1o(-MAL;kfR-(Yq%%V>EPf)cfh(>vIM zqr$@1F4^NSH=;0&<*|#=Q85x$N zgAUr9xsB;waBqm>k{Ze8=?7Ql8)n52}{%P*MFS|J0Os8>lsZ-{x9z_Rg-loIZ3ps!zQ zgoJPR-Ls+gBJ^a_^S}U;C$#G8=}F@Asq}II5W;n9;uvFjZY$%lwW~z*_M=&(wf8}e*U~W%CL17S$nvObq?rEy}l}tS5zd2oT0+b z>LOQ0DlLzuI7mrJuU)%#?%X-R^&*}JJsMY-;{>VnI5Zs`2(#_U;r3%+{FHwVfa(AP ziRbSx!wjgB?-ugANL`cl{@!%#@J{+IkN4hyZCMtxva-|y8KAm*dHN3?JedEPA(91H zw6L&nZ*MO%Gt(UFZC>s6EDV&xDnNmRJ%FPST8^aTWVC#sKd7J1UvtXJHXbP)niv^z zFwf4;QU~9?5!OB%5gl!(_^>n8Yq2knl93-&TMecckI;dJMTSO(hM<_F9UmVfes44j z1mKgYAtpL-prQ!`a4K2ihWh$|t3pCUxubu~&CP*gWO=fgY*b=#E=vsk1bKRLyi8v3 z;v=2n^QGnGCw=qK1cxr$*4CCz`pw3mK7uF1%jf1+TAG^hfStm_wmNj+j)|fo2@aOl zDVh)-2Jm=7$VJEC+W`>pV#tn%TZ{b#m)L2U^ZFfQrqi{>aNulTtbK!+J|16L(Pbc$;fC+b;G{O$K3R+=k?m<3E1<2(Sm(RG5YA89k$}t}aO4=5?S_ zI*2L)tgYa~2jg1*>j8_2fXIMMA+pEe`01){B{732JF1l@s!^vW{RKvAqu3h`J?~Sb z9>uKl>RDP^`ubK&WTbY^g@#gO&L_mj&;87}Xk-jQ*$EfLe7w9ytKGj@UF}G})jQq9 zt*m4k3Wfe#%efWM{iD?E`M0SdO=*V*R=R8|x}G&=S>ok9!sd*(DGT^}?4_3-#9rTN za!>cXe`LHGO9?%l6ci(k;-m4Qy6pVI>f3Wcs>{id^M0B0JUl!uFkIsKd)78K(^FG) z6r{{1MFXEcecIXC$;{-hwNMB=@XXN8?Iq}6ILmYOW(=ze^E4Us)b&*Y$(P^&yiiye zW7&D$w9bK%k&)5SV~oIYi_N>|Lf3EHu&hCz6BhnzD@oY)hb?`RlO~yGgqYNc9}M}* z7aZLDo}p`tkB`sX+*~91GG9A4`KoVbNnv4BL_|b*csIebN1AbxiXeP^d@L=;kM_6h zqE1Ut#~0ynxUldU5OBi>uv*j za&0(r=x?jP!IZ3EO5+}v#AW`rfZbKV<5qAP(^9L(+JN1I!^2@g#mDU|;PKDX=_VA| zR+(Ccs2)_|h=D!X-`rTT-`|||^74YEX>p4|Py;Da@+tamwX&6UN~-xQ7gtvlDEL3H z%_@=Xl~q+0M#s#ez7T{58`W|KY?K77(x%cB2!>-5JLf1+3~qWv^v8R*ryST4$&iKqOvBOxen##thySu+2Q~IQoEg7idHmeDyUsIXOUv zw{H2(w!O~PLGQpmS1H;O*q-t;uy|wTq@+BA4?8F)oA%BB6zVY><`iQTaoP8vqzrP! z(qU(?mB2uxPq5w$*jWamc-y}g$ek~4JWwzXQWAawP6TMMU8()&HzQ)zrN(JKGM(Z&rK&5F?tJQHBMx{HYVbQTi4NihY}2ZhL)E z;dH+X{Gje!(nylnZ`BEsT%@dW9@ew4&_?LMH@;`e1t5_~{R;+xfpT42kA9}Nc6QP; zGWsZ3B$@hzaqW674P+>wGQ)OOaLLKZ&D{4*P0K4PK)NU^DP6X#bCyg|jahPGGLhL% z=_M>LEqUDJ-8YCLWDO$i~m~fE?z-cqiE^Y zbP$j;qgWqS-8*;M)C2mARF`U0)tDN~T2Po_vkPtUh6`;3UBzDL@*66^N2ewneLkjKRE$10>TQ!yN#nsp;nnWp-_y93iJxDfsq%?$5QErNqb zYL!;ef5LC41)bqWg>j^7!Fl2UwaK!{VRwFhQZ}^~)=+Ozp`O+XE&)?cr_KdIF3^&X72Z3+wn5 zsKG|dGsRl$v!htn!omVz<~-YGrV{(*IBIVPbGD|FlM^7_4!Jyl`9^Mw z(J31Nu7YSQY6II6&xeGB04}P;tpEX@4$9Ht#*9zV(*E^XuvllC_4}Q46v~E%Nr%_I z{mJ=*j!Cx<`WJRxCwavMn8UN|rMa64T@T3;qEuPTUz`Pr|5uiJmQxR=rBxLZXAltU zZ+3>OR7NX*I9)pzjp8S2-|>^3s-Yp{68TwV&ExSpEyUJ**E~hw*~EvP&6okc&u)y2 zjIm*1oKHOeZ7PEJ2hf7$o{LgDxmWq)h#d+mc#GbbBFp-*mp6$L^Q^Za#{Z3s*99E# zz@dHOMny}01$2?JGk#3nfF#0N2%cj#9`kv*ncSB@`~woxqJil${l1L|QF#P{J<{%s zMd8Z3LF<$WeiDcc48k+l)1AwV7fu=J-XU0Pcc zfKRWYik3{O$7?)Zh5_px3YU?W&vcQ7!D5&Oaeo&5ym5V^k#vWnVUpixHo@>Uvr1V- zg~t@_?!eAv;csLh%e-`?~P)|-J-Lk8O*p1Lux!|R2<1|uunmUmQZUV%B&}Ac2OnpZh z68{iiX50C)7m zp7*z>*?2`cFXG7+e>ql8S8;Z$7iL`d6UD@p29rQf6B916M-Ickw~sX62i4WoG_~6v zp-oYve%9gMz21phZ)`0F^ZW!gc>#oa>wJs+uRo^4&E3Y@TJ^HWpCBQYq~ziFTGnyw zoos6lDCqKKT8N4BRf14M$D3=JXD=Bgx2{l$wH3)=@mS2Ut2Gv~Mc zH6sHOF-J?@iBdsi1~e>Pd+^vEO6 z9r&L@CI!^V(cxOXYsD}^_X}`yuBgNN-VMd(Sp4%AgC%4}MrN!pXyu^MsHyMNI~eU; zP=%H?RIRP2hASS8a=beN9V{9enxRj_&af0sd9sa3-=}e9vw}c__B+;k%xi-p?0aQl ztiRvj-o1o$V9Gyy6$FY!Q9HDG9MlXcDXDOKzYIq(CLl`_R)KJh?$%F4g%g)@%GA>btMOf zJhfl{Wfk=LS6!F{VkkLNq#IdTSga*eM6H5zzkI>lO5Pr{y`}^~K_TL0~_+JFR6tyIt~qpIrI z-QEs)`SOtKd(|{asEF1&kYeDrs>;eD(@Mv5VEdLzfPM#355OhI8-gg5wJB!HaVySt z?}c{%+iS?0-ImzM9pKAzqr5A#lMh#90`dok!;vc*f3%NVu6+WkvSXzT3-bset}I z1N5T;(BF_)?VgB)M2D>;b+Fr92Ukrn`j*F!S!9Z4PHE}YonS`LEPzCaa+&h+>t_vO z5n1h^PM9&g{N`Bc?c*~Jn!unt*WKMM-@LrMEOGH-+BF+h1mZ=bm6Zq?NQtMqLckl) z0m)15knSdv0lar$U?5O%B3Zy{FL}z8C~d$2BK?H#Xll}dQbSMQZ!gU$1VKL-ZgDl- z0G;MAs^EqJX{%m15b-rNCTvZ9TXRj#AlEmNl9E76H)a|TeUz$5THk}Ev%V61+dr04_Cd%Vg_JDGzLdt2EG49|W{a|C89mt%1$sY7MX&jLvQbs{@Ic?&UYosSS*Knwf%c%S%5HOcvjDn#yi zK0=r8&rzR`TtxhnMCT{hq5tY4UGP$UM=9!XcXxOHgKm>b9#0+#N))4 zkeqzfBQX;-{X0zI_?m*kOm@FniG{WG=*UQI`TFm}fq{XcAstUmPN*ptl^z$d@->!c zyYZ;7$IA7Uma3|x*UyDar8kB@V&6A&@<&ESS{<=L^=4u$t}ZT;(Q%y?22~C{-QDP= zBUtWFDC8yhD{w(bO>bg{3uit4p>b(P?&tE&^0_7nA9u5NC>dXgoudh1m)e)*&8 z>ArtnEaSo2b@JlVQS%WbWYi$C?!}+&?aI;k-c*@{xVWsr)tuG63lJ(L;-9!TZ{D2! z%2kkJi*9Oa!mvs>{3yRED2Q1;;PgK(!Qsw+tq!h_7ST{pxSn1D%R}<5I(Wf;y8d9k z?G0SV&@d%Axtm2sT3S?8^mSMm2{Cb@af7WeGjI446BC@vq8c{>=XcVdrJ^fv#jXg8 z?dj~idiCmyQj5;)#|a_$^|dvv$ONPd-o97_Z2uouS^&XCvWEFL>2Dr^l1L< zGbnGlZCBAgLT6`ZYHDh1Y^;gzZ(TLD$l`T;jDpp8MRBpy+3AU*3<&S?B%XS}V{gky zT=6zrcq8-dbPqQ* zHKlkI%cC;Z9!NqKG8Y&=?Y)kjoi*h?+$if)=Z$-gV+OklESdlQTv%_fCbu^pBaxEt z!TqDmTFcE%3|2Ea9$rrAM;t1nYT)ZDH-S3Ztcq95CKMXgd6ZD(DQ7v)bM^G}XvrT~ zC@WuNrAfJQ;|2`YN7&n%a$Oa>dGn@>%*4U07h&lN0|RYrn^}$TQKdBw1_ii*haMds zjwvIN8!HV3yUoF5Sw~8Ui|Ju4>>o8$zx2uNrF7rH>LsV8ZTWmd$sg~uZiB^JFT!y& zycu2>P1;z^O}7%H4#RIv)xpb=iXcF!t2sSYkLffo#}jXe+UzEa8 zpYtjz;sqan3#y}C3UipMU3?G&LI3coX+}pz{%G`-f$8e#EG#WeH~J-lg`JXs@82L$$9lH=9YV={8jx8mZeQAq_6{POZ?;Ye`hS>~l|~tH@hlLeK~PNWT{wrlkL1#H zU?5Q?jE-(zZ!AXsaAl!04qk577WvOVbjwDHpLV4!H#fdO&~c=`)WK|XFxc$&NF*gW zIikj85mbsXdb46-!Gc@bc^Ld&bn`Ut#43cf9qo+^)@F69^$CqWKBpp|J(d`&P|;Q>f0 z@AdhIVbnDnpFe*#D_TIU<>ltkt#!rU0&84>z+Mc_C@4VI>%u}bZwUxEOxLfLK9Iy2D7@kw=8)C8mo;-bRe%mO$R6ndhkw{%?aPwO0NyJ2taPdkP+ zRYBXt#D8N<#G^ZF7W|Jp94=B;RtC$}-PJ`$N5{MJYcauum%DE2j$8A)ganfY@Az=h zyLUTMuw>AVJxIyBcMRNX8ym778;OsPo12@p6i(jR3xTa`5vz3-r2JxhW1IGx|BAXN`j5vN6^*P#bU96fq~u)jSUSAwY7(%xYOUi z*GD5(I{DIX-@N%!NdLx1%N^Fzw6wHwc`~SIM>ahn!EC#LXQIn$=pw>^HKd(vP4mAAz&k~I+EG^mPyv1(c{#FA6NJ8WgPt*zMG>n>E z;P!1wO3Lfp(fF}TyWo-U6B6p`WANDt#)xv8San|X@8Rd6u$BYm&fQ}4oeO|yKzRX< zgLJou{p>{by_HD8~P|HQSaC zygN;zGug~8*xZ0Qt12pblI~j1wS>~khKY%ZeH>hcuMXLWiQl{D%*MpTROPm+UD84f zsix{n)l^mOjbIHBSP$^^J3=GO^kC-;|F3*Ausqjh(DnOL6MT^HU`S}7SK6}I^qkX< zY@b88n=CimZGU*4PHArHf=i7$FTKN?^sbX#2omO4un5R|I7fXNilIfKiYGRy!-DaW z(Rfhq->eArUIcD%@bFY11Yt?)IlaBTg@uKur+ygayZ)y>VCU%NFS zQXm0T{f)1k(3avHwO_NPb{M{TYinzIdU`qC-%r4fK@u-nSX(O%)<{;?5UWQqC>!#) z9D<&mKkO>Q*6dLTEXXK~or9y%8LteW(Z=RehX@*t7BXq9NA1r4`!Cm=fZ)p%2uh@M z5e?`7oV88Q>t3L@4mjM-Zv97vol=D1)2A>drrgnWU4eLl7!3qPkx5-`GUuOc?vRS1 z_4W0A`0!!(dqH}UQ~y%}XR0O>8(Wk!F=VO@;+}4j-kR+W=}6n~I09N}cJ|+D9#WW~ zK_$}3$;s3-z=&We7ddeO3UIuyd2xphXxJAm_U|@0x+*Ix3knKWSNLz;%Ew~uQK&>J zx`p!FA|Ny8(}Kh_Mqy|f-z)+Uu^TB!YK$H!crp0>yQz3`D0nzz$i+v3x*RIA&-*@a z{K7a$&T<;sp%!geVy5)`ITL!A^JNej)N~oVH9vUkKC@>sym5I&MSaP-?K%8_4RJVs z3ky-TGxL)?ox6j1YS}Ez%)-e%`W+C|bk#+4Up%a}**V34bGKlG zy~+vay4(xoDcBfhW@Z2iK~a1D*?8fZRmTc{r%ANZ&-JoIAIM~@(wXvdu{Ui&4~YLx zBYWD_)dlbX9QpbAx%;r>9*_Ai5xV($Z53y7+}$;HU_y3NB_>U7V5dmT z_zc=s)RtRYTXV|$pdzx_V8hF>zsb0&%sCMDJpKYTqvq| zUSCC}qa~EWx_a;M@Nj3xDPHXc+Tyhq1kIKNfe6Zg20i(ifIHs9oe7o~AS%|Z6^_O~ za!%H`T3cG)fXVHCp$7!|wYT?u_aX*^Ve3eh@w~≀bv-C@E9+WdiFS0KhaC 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 literal 3631 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 literal 6112 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 Un0Ab`3Sb3YGP5?VMEnu^FQpsz_5c6? literal 3092 zcmbVOX*iVYAAU6_M5cw1HElGNN<#J{g)+7nJB94agl1%fWI3ob$(duc2 z+Khh}`0sxEMFqefw4rSf1PKc7d^}KEhB#QX80r6R8ImzWclNYr%C;_yAD5T+>Mf=Y z4l2KHdvQcK#&$agX|D42j#GR{k6c1d{uPlpS22Oii6d)aLE)Kp>XSS|BU zdu1d|x#K7L%l1<% zb#*u#?h>-XZZ68}A_U=%*1$Z)P~LnLAQ>9Jow#y z;BA^~G2n~w^z@XR+g|Q>#$qtMyLjGdKp%)Ut@v3Qfbi>d7^M2y_$?ryV_ z$wqm!K$)k-HRKZzG4!P7_a=w?D)a>Yp-h^On9;7{skcrG${KK zTt)fXP*sJQ?9IjF@hyiW4j--!S#T-0sRYI#%q=TwBPA-8+SJtaq;#$O%D%Jb z&QWKqcOyZrAAmNf{L8m`e34^`SPnpi7x$Jr)}gGe1!H#Y?2~u)+t)ETO&J~Zh;Go7 zj2ilgOcJ%)@}J|#o$coi^jw=WM4A_Y`Yq!XXp>A6vBax=fAT=z`GJS0DHHWoRVr#~ z-`h!#9zF8$@c}uCe6n*g_WhC9r7S@~!Ix(Fso$==?EdsAs+3hMxCio7@_86-SMWny z1j>Kz8$zJoaqLfbe&FX<;-E;q@HPwKU^o{-?MW_0Z^`%J; zha)Jam|qw=M_wI{*xu^WS{(vW6&Albo=jQJzUK(46QlRARXj5GdHlfn$G$2>3fF1F z#_!wP+e0*E8X0qFH7Ph>L@0!YDIsahzq4(Czbdhx#eBVBg3R})y7nf1Ify@B9 zb9#FErm0p6m8lXY3y;&`u8lo>_|RLxQB~iue{7-Vm4Zp$P3@+T=RBVK7bUKmW9EkG zn>^8aFD(&Fw3?;Wi5l34CoQ3S569xK=k9u_OCQ+!fM+=t*!0p={f7;C^jS*6Scgz$aM%Z6K18DH8L2R zQ{j!yaNSxW#}$Gq6PByNiw^r)_%t0f?!v-dxz8gbBR9^GE4|RFd&i2(8V>4df^4C@ z#q{zE*IOh5j7>}gk zD{E_GHDK+O6x=86WOPj+^ZF%bDXRt>99&#dQsSHyD=HGnTRu2L^m129ot>RMx$j6a z<&S$oQt1xTP`6#5PGbh*X6wmF8jY4`nk}kVzdlujTbBSeK5wgnFj{ zBtc9d#{0Hf_?7zcQ+o&J4Uy9=0RAxW7uriiwJfT)ht(`&Tf*uA{Rv zOa0z;{)PFbeMyfWTLw{Djb~zSyD6p0Mr@XIV1|G}hwtYx<~*zp zL%PWD^~tgqPu7RK&5$RxG4wzTw4Ru&fKnPdvYHCZ`*857X;`Ep2H z8XiYwN{Ea9(d^PuER)#m-@tJvP*2>{n8850Dcb83uR%3Y{1>#fW%z&dCT}L`a6?Ap z4CVV5PIaF^K*imECqDgCt5U3hLKJ6URF< zh4t#$ZKnfIQS5p^2f46Mm}hs5FNB~_C<$`TMq66~@QM>wSje_RKshI?heKIQOG`wZ zEl}Ne{oFqL03jivTKepAW5ddzPj>iv!T!-0F(+|Z*|IYAe~8wft5vcD27!Ak>glHoBh!i|PZG5Jh!3CEy7aAUHXmfrg3-u!s z*xy}~{Aybyc4o_EDL9~w<|^Qjj-WF9Q_@E%eR`rBAdY9*8$IJ3fQ1!Tgz%F1B& zFC*3%pkY-lzu@4?ii*YTfaV}U-9+1qbh`iQQ)vxAHtrrClIETmOjS{l4@h6-4<6`8 z=MVDT~S+U8o^?;SJp+=X6w6tr02f8ygR_ zvx#0NdC6bl&|5KeF!7__A5QKX7vy~udmAu_e}9L(y!`2u>*vLnIAMXb6Bc0TVkUNG zJ<$t=NV%SCfkI6r--ay)1+I9IsSHO+ujwv|Dabgd1812Y8_E3)2|_IVBW+ z|1{#}M6kNm@^*wnAHjvbB8sw*e+PrOt{?{A4^uhmL{8V;jCwea`l o`{hG`)c=DV{m(k~Uk`5X>m8CWDL;=x0rQ#p#}B0Q>lp4F+w<&eP&sZR#Ejx)gvVo7gPL6X6S3V3%LgR zPP4Y;6`u*%$jaBoTLW!VJ~D)=7m?*jM0LO8^R*K8@;1Tsu7aI|+=pf5K zZzki1QFJMMf`Wp+H~IRXX~x7T^8_;|Gwx*a>gQ-M|G$GdTvCI9pS$e#j=z8M0VC*% zfHr!x^z;aBR&#JWIiX%!v<$+?udQuPem}KL2&}nsihgt(<5qcE?sYv=aHJ^%c~;+A z@cRXS`SpHRvB74sdNUz~%=(Wc887=`!>7(>yjWnb^umPoLO6 zDYYt_-d{R$C|07&ixrJZ`W8un2d! z!HI)E#*cGzIq86C>;E(QIp+s^DLONxBYPJ%Z!CAWCI`gf~DW z1qG=!4RC<-jjIk1gX3?0?(1{v6F}V&`NkKLA(Y0^7qv0SVPkH7aCtPMbushS<=@Y{ z!=NGiD_uP)^ja5{d5(x?*HmLOYipRI;#SjHomG8t^eYS6bjzWb6ZD<~ z8Plz~xw-JWoW$SR+3|98gqdXrq7&<-S=Us9T}ai;hp_rq-^WJy+WXasevp#b)7gWA z15l#qgT{N`8#{IZnl2^U1$0_nZ1?x~H@gi=IN^-J!V(gW?}OcfgM)p1w)33gyxI_0 z-&x+Y?-+5r3LTj5%>IO_I-_QDb2H3uE+;4F+vw>2-Y_ z<4sXZQZ^;c{<$_Ew_(mp!+EW}&t@#WuMpiMYD5}pmD3p)^u9mDv{(g_M@dPUcpg66 z=EJ(Vj65;{laahAEMyh4xd#>&5<>rarpvcUOPMt3U3p#z^Gih98nNGxzSz*_CGms! z&^gTFng*SWHd{&ytw$FYR5~G4R8(CzBNl?FkWixRYN=KVn1}iaDXCJG+xg)S6#C;w zl|7@;5&_il@81(c)g^Ik(%akHmEXt4%-^XNZ&cFz7;lZC73H;&J<+;?!dY}UE$DFORhVFb*?|z*ST?Jju=F_9&PyjlWl>A*xmrLr> z{q38j=F`C+(gnuL@qhpH_diwt^K-aRR7B)%ftc~&Ef_Z6&0b- zF}v^kV*GzC#q2#Hj}>w;$r>UV|9L}fy_lj{SlgUN7AgaU9xQ~6Flrti9*T&FkS_DK zqH1evOX4oJP6_iwA`!wv)5F5T^4hWULv!=^#;>%D)z#JU@$soC>*PlwqM}}L0RfU9 zbGyq$Nc4#$GpDt+G2XHf6TU(zVA4}039rSV4Th`%o zHH{)K&kjC+*4;9}w*DJfESEwc-oy0d_j3GlyB|AGMMnoa?kY^l!Ng?vL)dmra@>!J z4bwDu^@OLab$#xDvq_dVTafpPI6?Qr;^A|##1ti|QRhFiEgs7;d#alK$+YadIO49C z=o8GS^V^E5Dr+mN+?*V6VjxhtuC6XKGc$>b-hbg;(B4w#5{0A_?s73=*&w7CdHAKQ zjMobu5h2e%J~0s+7abjaaelN>D>il9zW}nXNP2x0=VSBh*r&U>Svqep_vK6b`}diR z9RPhmp)W5lo#M{_BPC;lga%^+r?Ck9Ls#8o1u{=v{ZfffE za8Qz!m9@uE*WX{lp0KrbaOJ6h)w(VqEsy6ffLAB&dLj^;L7k(VZnmdG1u|;J3TkRs z1ENg~*W9*lv=@%012l*{6^Fxp{R+=D%+1awQ9M6Czf#NE?Nkc-j>1CR*4Ni}=CMsR zHTn#wi;HNfN8#Zx4#w&E`E7>^ESB{Ga$K4rr^@8D$swmeWn5#KeE07?L3cm`A9dq! zYG-AHogMpD&+HMAfq?-q4}eFh8@~=B@%4d`$;QSTI({&A{+;j`Cnqi*ei@mGn5ot` zZ_Mf^5n`AYj}c8c5{cB+{oI?*>K4Qc8m^#sd%czYes!;B%;px3Ja=F;izT7%s@>Vf zzwy&2b_BN;-sI;_m8v?@P-S)!0n{0Y!M!(1) zYNIHEJ3B9rwI!N=T#D(+zso(rnL7Cq($_9TsYq9SXQ`9je-i+b9NV+_t8+mIoS1}! z01AK~9UYxvo*bYSH>jys{*I1~LFKU9$!>qTySwWjG!4KG@hY@D>ws`p7PPgsq0jsI zvh;hMkOvg&c{w@yM=pl+io8sBcsu>XXUqh+@k?V_Y8PM$H&<6#7|gLVIt+>YSX-M) zDVmGH7@kP&@S|Ma-FKHied_Ft_4VE9bgWlUEQ+{4{nz&@JLHZ33^K(3(> zeJu3sHE}hCtKy_D=dQ_Z^D4PjUszzu1j--F-aZYY>Cw;oIo)6Nnpp~ z#@8a5!eM}CbnYY{Dl2X-@`2?T-(tHlbz2#^$s z!9O9rZ8(FdsP_?`O(Vv4#KpxKp*+%kuONKX`DQFS*m=K}+2d$cnzjl7ew519+1hwg z@dc5n{`WHEY_f!mLc`O~uhY@gP77TFn522rV{Hcq&c)`#)A@k=R7-$#t8wasgA_O( z*$HZ+Z9q#W5Oen>&o)FYeZu7>GMKRco0n~%?^PB|wq$r+@p4I&Pe4959NnY&hf~sAA(qP;aGl_r%xEcjnv?9b8Lzo^n zHcGT18eR^=0?AY5UO@p%cND48)6>&ZTUTE{NC>Z=^v1Z2p}1Pnxr{Gw;Yz z+!}*Drj_BSshOx-z8ZCx^u_ID zz<2j&Bz%@qQ!8FmDBd816Y+Qu&CzBT&Q*kliyRB;MlZ0(m zG$%g&+M$yupT~sM(B#{neANSL`xgAL;A;H8&Hum0h4<|dIUDDIha9PqDwagqXOXwe zA_n}hi?>RZNg4~@bX9P&J8_KBYoWKZ;m@-sL}x~q$3-{(mI?hFDdB2QV_Z)bNGNe+ l=D&8$X8roq^ENy220H%)KX{dY12}(y40PbyjhYV={|9grp;!O_ literal 3356 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 N^t6mLOEm1m{|8`df)D@z diff --git a/_auto_images/QQuantity.png b/_auto_images/QQuantity.png new file mode 100644 index 0000000000000000000000000000000000000000..8e5bcd966940d1b2201d1158f4b14c59f2a7f42d GIT binary patch literal 3720 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 literal 3084 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 diff --git a/_auto_images/QSearchableListWidget.png b/_auto_images/QSearchableListWidget.png index 81182a402613636e2d34f4e285f3078c6be771b3..27af881776730bfdbb2039d3508d3c181eef1c92 100644 GIT binary patch literal 11059 zcmeHt2~bn%mVa!!o3tpzM#Y82XbUQ0S`Z^3L_r&rO{EoCB-nrmDq94E5TX)r2Ne-n zGGXgsg(}-y%d@!fFI! zJ>ua0eZO8z80{pVi=OG6l?ZeXFY1_d4r_Mbhg!I7ejRtba7P)+>)JN66*{h$znoy3 zvK<}@-Bw@TbYuC!7dHj(b$c}9&0IQ>ep8MLf`hJDHan|oo1AwOhGzdv^MUmt^5KkV zLJ>KEDF`MihFz)Wr$$z&RuB0(I*bX1@K)(32R$}KANme~a5`fq$NwIIxTLMXLm*I# zy5$gv<*5G)FIO8DkIW=2CCY8W?T-7hd-MUF}cgkhA+h7}P@6)H}jcDPr!Zr39- z^`ozvE@}F|+&IxCiQ3a*;3WGEqWHVJtE);@a3A$-h{e%=c{Z*cYdmoH_` z#L7p=u_f1G-xr@QHVU{@O7DGN{AMxy=pp@4MP}~0RfxlGy6F862jmfZm41m(qV>}o zNOE#*8|!4|b$Rr}-9A09Q_|MHUxq;Jl{B}sgx6!)GPl&}@Z+}>eFS3v-u%VzGJJo& z`j6N5mriY1g!pW|?7FuM0%2+O^{qdB>R;?-xIF)RBP2Siaw&fm)SfA!Tp5Abu%5jL zvHqLTz?7PgcQ;CUapK-L;_LAq2*hsukJsPZ*5U&?{S?ori+1eoPBN!VZ>glilBFuQ z%GE&Oe%78RbJmfDOZr&l656^)-Wa7d?GfbC37_5%%f5cVXtR>;UfE^!20Vp|cjez9 zE-@c3lI>iyM6f32*%W5&!{=}%m-_JcV|@+=Il;bqGuN#WyH+7cKOqpSS4*@uMPbju ze&<*0b3FQRt~KRk02IR1ddZXVbem+%7Nz`kr3$Zp^(bB?i=O^_Jx=_|lxO4*B`beD-vzFEvPc`SOf677A4K)~V!5RaMnK_9f!i z4JiHlUi|6h-7w*G1$C|18mBQpweRhex;dXdWu9qx0>6z|tK;$M*}+gc{N?I1p$kd^ zv1xK+URQ`P?PP%wveL!3>E)47`bO!y%N=~W^1Sf5?d0jFsyaG4P}y?)2w3_@2T(lt z8BKA~n)|phGI*{UufiQgAd1&tThG?l*EdGu=Rd_*T8~;-SPWfwhjSZ|z{V_9Hr8WP z0|#PzdU~#^hU})?IrRL-P3ggyxb4;VeTYQZ)fLc1+O%m?jAPKy>_o5Pc8A%U_=TRn z%BbX|*ODj%;^%Ld4Plb~{rz`gv4bHsMV{{NmEzfjDJB{Im`U$wZ?`)lJ>I%8lLo2e zB0=Ch?gs?IxbaR=PtkAXH*#}xsgi|3GzCg6=j(C4^PLXm@R1`E^~UmHsDZjf;UG>j z_od-!NACH8u_B=nlCjW_pmX$5Ia`^ID|)m`UKAiLqa4FC2avUrNhQnXIC9Gz;pwtVCE0&XVTT%x`R;k5at z7CYG@{sHL-9^W;Xnv|6E;>C+Uy_e1q&leUJqDpz41;WB(_Vyi(jS5Eja|7{TuQ)t& za~bLVwdE{g3pHr?Rc}S4AY>#NCvr!gg38f8U91 zx^VvdXqh~&FmP%BRVp7c9@<@Yl{zXd4%@f8Mnr-xNr{Z=8wZ+}5PLYP(nT+^t|$iz z*KedHvFz)omQ#rQ^o@!0*n29Z=?2(E`uuQ;WCkzstp%T6bao|Vj}OXj~kja2*b zIwAgBXy`3h7zshY7#JA9jz_6m)iIekJQP!X#b1dyLCHckWz`i&nDgSuZcE=SM}lr%X&LNv z#IpexjvYG&%f|oAp%Vw|5`|_C4(g7tBS|3(qeVaw(P`WBb9U~ z`(yB)9v-h#QtTNaq<#DLZH>0e^E^pa@a!s*)*{nD;9y}&83z^iqKcG|FI zWo0$CZcPJJMHwAA((uMMOHS3W(6#!3qT|KxN_DCd*3$vm9d|ZuuF@*Rx8r=C=825; z!gQ73@sa>epj%n^GRYiO!WyI~p1jbId%ojz&BGnVs^7xd_rcj!;bZ4=1{b()xay*p zuU=IaouCKJwC9{9G$;ABo(u>>87_>MMMOk!D!gd@tD5Byd$&EI^%xQcY79-(tdbl~ zoM>xkn5feqt4Y+y5;F=4gs^1n-1GL%&d$(w4Npz*#L*n9J>Al?oeEeA%VxE++t6>g z$=Oib7i6*plQ_c6+a< z{OnqFA7$j`Hkg{nX>V>mcH+ctvUmYnG5Y@fTgv+Wu#43(7*&e$Vnp$rf<-<<$SZJl zb)`ot?YTG(h=``F^UOz6#y_m{a-oi%aC8i*P!8z(;6KJO$j}Fpp2Eaol8eSmWnpFZ zjcrV^Nv|vV7*6Dc$FB1#+<}dTKT^eSe=Q%nw^a{2%$D`Q{ zLtkNZBKu4OfWI*k7OK)R?Zn$BuU>7T9JaBsIez^3v12;dI=+YR+7M^&%A*Y?)y89) zuza!RFB*rqC9&FWVj)993L4Q#QRvONyg-)J;2Rku3EX$HO1hrY4B8h*FvwVxBt4ZCJGW7}MuRLo>bo{QTVA-J#-aMJX5bPTJVCHaF|| z^t|8U{2{pAoPYg}^$YVghI`^9W*|4vX@8@DH)o?N`&QaG_QVyH1WQpI3CvwC|qlPTc^Fo?j0 zhT2!#Pf4+Bu-pqQ*?A;ixj^ysKD0qt}n^D zI)f}XYG=NWGp_W-@GXVmNG`d z_0>N%rsf_3a1EOW-88;tKcSoi$Yz5l%>YDzyXXSE0U!uN<$86A%T&cbW3x`z#tjS% z02&u9Ojd((fn6MFO~-8B44XRAl3HEY*Wd4V;X<~^3y=@6K^6@}<@>WCIGBWezh!uS zo1T`oT~kwY>sCF{2@**Js>K)?78V9Vq1Az4!Ak`>L9BkDiKc8ciMX{6yPY!L<{Sy% z(&^uEUUt>CkGBE;&cTVx%gd?$kLk~!_rHkue4U<-(a;cfj)e$facd9=s#SD!GzgE- zoS;82h|{cMG|OU!0Ha%5N0HtJ%?#(9ZRMx&QKcsXI#(Laj+e>n>*-k1Bt;AcA2R&I*|TREqERn5tymM4z@Lcv zAghKed!0zU8JBOle91p5Jo!bP<5w_AI>&4MmVX}&zo$qpzlatfZJeyx1!_cRXB2P6u zIRLdSkFJT;R@bM2JcVUK8J#?N($>}%YK&@aAewIM@9*FE%dIw$OlznnQZ2i0C)0;9 zm_*#=#ZfXcRf`(BpeN+PDFD-a0IaT}K>5QOa)L%uQAQi?uGaTI2kV18#pkkM&5-Eq zygbEKtNa531_uYp3lkM+3e-H`mInm^a#}ZCbp`mXADBM4L^f%ghD};9pXGM*#*NJ8 zB-5XY=4!pf6OrVa<3#?){{|6JMju_Y)UA?gRCIlANbhl49fVlO>R}tU5c~!dJ=~>& zx}_2b#^hQTDpD7?sk`jy9A6Xekp0=wC-T1pL+6)WTLBcmm1Z7C{z~R?`D3Z*{dI*{ z^V1mtphp&KMtFOyAb@DD@XtL%GuZ>E1=|nfw?72BU-nH?;H$vXq{crA--sjv)>0Z00mI-M35@5^}{>r?q0k z!^52`A`*Qv>2!nWLo@Uz!pv1 zW*3ivJpwXMfA*~JlNm-CG+b$zEP3K4K4DMbWRvv_S&LHN)|P)^=u>HF>AidRu3Wj2 z9x{_co-I?gRMrok9sl&)48vHM1OhXE`14~p4XBo2iAX?X-j9x6si>IlK$~o~!PEO6 z*n>>O`tgCUdxHSRP%FFV_X94ww2WJp9~gPil{&!@hW9&K4}%qb?W zOSnfwU5ZxH^>wLB&=m^Cn93}8=gEPa;^}1EjMyujP82}T=Lz_0zaBv7M{I2ar)sfo z^10dBAQmMv>15JCtlPVH@9Ji-ix9<%o&O}~7n=i{2?|RxTY=-y2yO(zlowgp0hSts zNBK>~v5q_pHurzv5dE11=;e!`TR^h$M>|0JW=~0~zk!rWvw<0(#Vi;e9tOn>Rzcg+ zvn}HkE7KLa2Nyi+&HD^J4GI{n8=v3d6}d)Rjren-CFVrN=b2VKlgab~cc2#KrZbl~ z7VHLGho+2?#)yph=JX)1nGw7sC?G%p<(ws1x!mX?_iY6%k!QhZ?su}Q`qW~8c}|su zgE2S0D(4!>4iSz5{zz4CmqaXBqkTF-I3|m@RB{}E$<9viM2h^729Nq8IaytJ>Ep4K zR= zKM!i&FSl0vuv}x5K`84tN-7hq)s2y$#10@Ir>3UTXtezN-IT-D)`T&-fG?ICaqqKJ z1s`B>zdK3j>qa7xs5e<)FhMrZV#QViO|7lecRiOE%NQZ&=H?XC%#r8|z%BsEfO|l( zQ-e$@*30qW!AdYo0X#M>cy4lPdJE)&5=Ga1JXtgo7#IlW1D(T*>IK^huhA6l;x$4X zOE?Qf2Pq^=_!$RSj4B1}&%!&CdT(Phnf}`_7)Eb|zOOUlh8dP~(b;ob zqGe1>3^hg`(2KNx4G*qFdCUK7>s{*JfpJf@Z>_H%Z!l36^<&5&*ohI!`nx=uUdpIk zT(AGLTU`S8=1Ps@E@OG%0W>r;K;o^vCNB@2Yjr=bih`12ue{-`Q-4)7i*Y&5Tn$15 ze(Hgnt7gOsrXp(1R!zJj$?=>1 z(r~sljRZtXSe)Fo2Xsy}QtUgtW@dW2sig&~Sr^=TuthjZPfriJf60<1Y8G)j&$VS( zB^*p{WT_ijf{JRg_e3CO_pD(v66OQX)I!h^B0l*^Y!!}LA}hviPENEjhAqWW1lw;b$BsIt!XEvIiW7>xNP=eB2frpqrJU-d;J^~d%^+lauRrW zmWQMvGNh@g=~sJu{Wkq?5SK2m+Lzzj)I^c;>qcNnsGY!!JfQy2^;e{s$WnChkQrXj zA_uFZ1K%W0NR>pvdOv>L4Gra%aPE(&L>-np9<9t{?wK+NHiYO2B-8Vwps?ZSn*D(F zT`c9IF%XJCdtg5=EX+>GDsEpW$AtKR8n(7-mQJ9G#(s0ct++$~Su z?Z+MOE;EbSP6x+OachnCsZt7@22gGaqAcdJVAyp0T$RlYT>11+BW?tPL|nq$LW}yF zK+}TPU`MiA!7#8?sbuk-l%r_@_V)G=S-=5mZ3=QtfuWTIkO-6oSlc?WNJub&cd{T8 z!-^K!kbp42 zgn~McOo6=>PIO^xBRIFN`IbB*B-Dr{@AGhT3N%PZLAx;$IL-#y4He4$@@2PQ2dkPt zGc(ibNF2S1DY}?ORe{oZf+j@@lUbmG0HjtJ<@4T+%opmA=BI(X6G6#A0-UtN`4@>g zp(5Eb(eCi!dbe4yX!2-odyYm_Lyb@|3$9Q;|XGIB~E>!yJIs*>F z({uaw?Q&@7Vm90~olzDPv~uN2E5kXL4R>dyx~%z_&CC>j5n}K0``w11e7HB~=jRP$ zK0)ps7Z>NN4QT!h7S6QT7rc81PzSV$^WqdjlYz6O~GiCE$eHrYdhpvPS^FgMxw}qv}+zfQ!tEw5>6`^Hvf? zkEBA(+4u1-U0w_^4-#FIpsOv^X#v7}3PeOX{HJ(}H0%i?7KQ;lKA#VHS*mT;fHuh& zfhc;wEb=5Y~kPdud}DBcJ|qyNZ*`0VM&6^XaZC7Vt4d4@O8V+uN9L z%1htYDYcJp|FDmqs{fCDtn|kLa;2Wo*CLu!!DMC?#<38(96oGsF9d}TYoJRR4^>@o zf{4XUKQ;^8C2+0I&Yi(98X&_!Mw*QQ*@2T8zAU5iQBLYHgW+3-{{rdHM z!thWsbvp*5y5qO^1GVwODK2dL?Ebfg6$X^?_X<{h;_xF{vF5--tv6R`2K7hV_%cI= zBrbei9#k?^5IB&fXecamwJ4Gx4@~&IO=g+t+JAGP+#0}R05xMID0vP9!^p>UIz1x; z(oTKgJxG7#(9<-58pRu|>!5haHn4xx!F=jIKL4JzmsTL$4VB2F%}s$>9ZYT<0_Fox zknTvIhXInURk^Ns9F$9YrEC##1*062e?ofax2%IRWcLfDF zay7IcZrO|m4`$O}{d3r?)N^LNeY+#7G9l#6ALf$sySapoUz{b)w?ZG5k{VxFNM}tD z0J+ATd_bj2q?r`(AL+C-RR`}_jbQ{sLJn$o^Oh~NsXF~GvP8tu2A~A8l?Dkj%{GvP zKY*!?MZ)g4xw(9!ZGs6%Q2RCTTf{5iY?ex+{ea7!Q*?3vhZcTqZ>Sxsue^uRXxX zp()WCHjdZ2R)V|1T`zg34S4o0J3IU3%P-T;0Q3M7a_AMSRvovo!4qnAXn8z98*pV5 zRD_bQmM1$ORq7mR&;s}J$Cv_}dybU}GIxcd;$T`Z%y0jbV{`b@KYzyEoi_9$et2Z0 zx~eKfP|%e)q4*t$05HwJ+c*{{MaoyG#h3Q zXo@^;A>--Or-BK4Pug><9DIF$=BJ_Qp7NU`BO~c_e!C(*c%tz*xGKXZvzfPH- zONVr1{|X)~F$8+Ugz@6bi_w%V)-Nb1J$-#I`bTpLO9!Z}3Ab=@#-kUdX1b0IL{|th5QoPHSVJRpMAUZco z84~KT{N4z58@MSM5)HH-Tyg=OPT~{>o^5%fdsPI%;CG6(G1mBt-C1S3yDh{CD_Z?#iLCk*vB%>O=smP`$KS6CPfle2iNmtk)& z27pW9z?6~zkk$>dPpM#!wM@<$gEJ7ME(ss(BYgy!)Hcj@|xkiDwrVblRl-h;;(qA-yZ?`_Zj}Z4u5_m?BDh9uTu}-YqMd-B;(@;Pj-DA zFF9G1nd$rWv8yAdK=vgZkZa!G^I#tO*Pj0R(~}|pVlRs&vYM*7TWUjyEPy=3!2_22 J(~O+1{09#njadKy literal 10743 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 YL;U$NUV~pMC{^V2Ny8KAxF4_oFGq{5vH$=8 diff --git a/faq/index.html b/faq/index.html index ea6dc27..c7f32dc 100644 --- a/faq/index.html +++ b/faq/index.html @@ -467,6 +467,8 @@ + + @@ -637,6 +639,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/index.html b/index.html index 3f25e06..3abaa6a 100644 --- a/index.html +++ b/index.html @@ -481,6 +481,8 @@ + + @@ -651,6 +653,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/objects.inv b/objects.inv index ca373baada342ecfd56c081e8caa40d5a47954af..8a28ff0943ecfc1362e6cd960480b881c7fbdd32 100644 GIT binary patch delta 1158 zcmV;11bO?D3GxY$dw-fsZ`(K!$M5?o0&K5UvDdvdPTB;B(KybwM}n3nG7*ZDIiw%o zeusJ_Mrt`RO{#|&;$wb)&TvGNbkNmcRyK21NX%HS3t+fYmT%coluJo}Hk(lGys5l- zsax>;xis3Tf{dg#7xnJnC#P~Nw7U4`!t;a`fL{(Gzx@5_;(zmB*oi-BWks%4=065O zeXjvq1p5eEdwT}LKZM$P-5<3@Z=Xw!c#1JEif?CVe^sL5jZug=9D7BP!6&rj{^|yBd;-^c~U(B#x2|4iTM&C9hE| zB>2wSa5;Y4IWYn zNS!|?gBz&y8j_|CEfABW(@O$Z&b(Y#q*1u$NU!F^nKh&nxl1|K-E~$Xx(z`ykiu`? znB)tP+3dP4-ZdrP22))O#=A3aY)|0&$xMXa7=K0KZj}`h1G_-SQasi5L zcGo^!X-BWg16L)?n?6|qxv01t6zK>>V`#i#3lA3b>**MpA^wHSoa)s{O8emhqBYgW z7JrxyaC+$WmD*d>rr}}|@=H?1x1t(e@uctG8UMZ@y-yb^A)Nv=O*(upklKSLf79XTe(wNt3w1h;pIo|R zE~Fm+`uxGK99LG@T{fHbPX(Rb6*gNIDt`{)d&7@&1zz=J`nth*;EI<@SU0@NoPq2@ z9gqBh@8uxqG=30>`X4dlj`QdXcRKOdIqY^fj#`dvWT z-U6~_Kf>DTjCFT|`@5V4Hss!nJfGX0gnMrD<&a|$MSsb+ zTYM0uD8>@|DVj@$apb0Y4fs{cc9)7Hh%V{#lA95fXkEG-bM{)j@gv&mj+ZvL)SI9g zq(ec|J7Wmkh$_!@(o*xdMW8+iwV`vL*>oB zZo$i^+GwXLGLqU{wA=q4ohq%+>f-Z-=LstSKOIGW`uNYqzkeUF6Mxjoic+h>fAxZP zy?SgB>;r7)h3y6=+i5j zPmz{893rJ(qXTz%tO0aQ1}=ii5Cp61S^~=yi}bXNjep&)lZGg%&BD773f7(d&dW5; zs)7ZbC(F}mtgV%OfUY?iFq?~7ae38^qkoyc&3NdBlEh#;M@&o>QH}vEN={D8#Mr%! zhejY0^j=F*ZnMceN{7pA^e3UJY;b>t5e;Z(b4!?qZ422%b{+BwWR8+e4iVjjC2vtI zB>3C(OMhWDIVjM5@0Y0Pl>3Um4wZE9KCn#TcMXsYPgfw7Yw)mX`EQGCD7e7ufQMWH zQkPHJ;07A~3|Ui$Hi${q=_P?HXZEiv@+e$$q@_7=<{9#d+~u6=?sZlsx=ledkis9{ znB)tP#q2s3??TD9!Bkhh@$QU+?HOD@nVHaQ!++aTG498fx>@Lj-Vk58hV6^9Ybs8B z>5@vNGltfYuj`edww-l~gm0UKgJ32Bf!|xtv(@>VJBg+x?tU{{&0UO{kRIoucfk<2DVLna%cMZdqH!^s@9XcVI=+kXFZ6CL^ggRzSRNIt2Ot&3 h@s))_F!t|w{i6LB9CvNy|1x_%oy`6E{{xU?^=!9t8c+ZL diff --git a/search/search_index.json b/search/search_index.json index f893c39..9186b07 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"superqt \"missing\" widgets and components for PyQt/PySide This repository aims to provide high-quality community-contributed Qt widgets and components for PyQt & PySide that are not provided in the native QtWidgets module. Components are tested on: macOS, Windows, & Linux Python 3.7 and above PyQt5 (5.11 and above) & PyQt6 PySide2 (5.11 and above) & PySide6 Installation pip install superqt conda install -c conda-forge superqt Usage See the Widgets and Utilities pages for features offered by superqt.","title":"superqt"},{"location":"#superqt","text":"","title":"superqt"},{"location":"#missing-widgets-and-components-for-pyqtpyside","text":"This repository aims to provide high-quality community-contributed Qt widgets and components for PyQt & PySide that are not provided in the native QtWidgets module. Components are tested on: macOS, Windows, & Linux Python 3.7 and above PyQt5 (5.11 and above) & PyQt6 PySide2 (5.11 and above) & PySide6","title":"\"missing\" widgets and components for PyQt/PySide"},{"location":"#installation","text":"pip install superqt conda install -c conda-forge superqt","title":"Installation"},{"location":"#usage","text":"See the Widgets and Utilities pages for features offered by superqt.","title":"Usage"},{"location":"faq/","text":"FAQ Sliders not dragging properly on MacOS 12+ Details On MacOS Monterey, with Qt5, there is a bug that causes all sliders (including native Qt sliders) to not respond properly to drag events. See: https://bugreports.qt.io/browse/QTBUG-98093 https://github.com/napari/superqt/issues/74 Superqt includes a workaround for this issue, but it is not perfect, and it requires using a custom stylesheet (which may interfere with your own styles). Note that you may not see this issue if you're already using custom stylesheets. To opt in to the workaround, do any of the following: set the environment variable USE_MAC_SLIDER_PATCH=1 before importing superqt (note: this is safe to use even if you're targeting more than just MacOS 12, it will only be applied when needed) call the applyMacStylePatch() method on any of the superqt slider subclasses (note, this will override your slider styles) apply the stylesheet manually: from superqt.sliders import MONTEREY_SLIDER_STYLES_FIX slider . setStyleSheet ( MONTEREY_SLIDER_STYLES_FIX )","title":"FAQ"},{"location":"faq/#faq","text":"","title":"FAQ"},{"location":"faq/#sliders-not-dragging-properly-on-macos-12","text":"Details On MacOS Monterey, with Qt5, there is a bug that causes all sliders (including native Qt sliders) to not respond properly to drag events. See: https://bugreports.qt.io/browse/QTBUG-98093 https://github.com/napari/superqt/issues/74 Superqt includes a workaround for this issue, but it is not perfect, and it requires using a custom stylesheet (which may interfere with your own styles). Note that you may not see this issue if you're already using custom stylesheets. To opt in to the workaround, do any of the following: set the environment variable USE_MAC_SLIDER_PATCH=1 before importing superqt (note: this is safe to use even if you're targeting more than just MacOS 12, it will only be applied when needed) call the applyMacStylePatch() method on any of the superqt slider subclasses (note, this will override your slider styles) apply the stylesheet manually: from superqt.sliders import MONTEREY_SLIDER_STYLES_FIX slider . setStyleSheet ( MONTEREY_SLIDER_STYLES_FIX )","title":"Sliders not dragging properly on MacOS 12+"},{"location":"utilities/","text":"Utilities Font Icons Object Description addFont Add an OTF/TTF file at to the font registry. font Create QFont for a given font-icon font family key icon Create a QIcon for font-con glyph key setTextIcon Set text on a QWidget to a specific font & glyph. IconFont Helper class that provides a standard way to create an IconFont . IconOpts Options for rendering an icon Animation Base class for adding animations to a font-icon. Threading tools Object Description ensure_main_thread Decorator that ensures a function is called in the main QApplication thread. ensure_object_thread Decorator that ensures a QObject method is called in the object's thread. FunctionWorker QRunnable with signals that wraps a simple long-running function. GeneratorWorker QRunnable with signals that wraps a long-running generator. create_worker Create a worker to run a target function in another thread. thread_worker Decorator for create_worker , turn a function into a worker. Miscellaneous Object Description QMessageHandler A context manager to intercept messages from Qt. CodeSyntaxHighlight A QSyntaxHighlighter for code syntax highlighting.","title":"Utilities"},{"location":"utilities/#utilities","text":"","title":"Utilities"},{"location":"utilities/#font-icons","text":"Object Description addFont Add an OTF/TTF file at to the font registry. font Create QFont for a given font-icon font family key icon Create a QIcon for font-con glyph key setTextIcon Set text on a QWidget to a specific font & glyph. IconFont Helper class that provides a standard way to create an IconFont . IconOpts Options for rendering an icon Animation Base class for adding animations to a font-icon.","title":"Font Icons"},{"location":"utilities/#threading-tools","text":"Object Description ensure_main_thread Decorator that ensures a function is called in the main QApplication thread. ensure_object_thread Decorator that ensures a QObject method is called in the object's thread. FunctionWorker QRunnable with signals that wraps a simple long-running function. GeneratorWorker QRunnable with signals that wraps a long-running generator. create_worker Create a worker to run a target function in another thread. thread_worker Decorator for create_worker , turn a function into a worker.","title":"Threading tools"},{"location":"utilities/#miscellaneous","text":"Object Description QMessageHandler A context manager to intercept messages from Qt. CodeSyntaxHighlight A QSyntaxHighlighter for code syntax highlighting.","title":"Miscellaneous"},{"location":"utilities/code_syntax_highlight/","text":"CodeSyntaxHighlight A code highlighter subclass of QSyntaxHighlighter that can be used to highlight code in a QTextEdit. Code lexer and available styles are from pygments python library List of available languages are available here . List of available styles are available here . Example from qtpy.QtGui import QColor , QPalette from qtpy.QtWidgets import QApplication , QTextEdit from superqt.utils import CodeSyntaxHighlight app = QApplication ([]) text_area = QTextEdit () highlight = CodeSyntaxHighlight ( text_area . document (), \"python\" , \"monokai\" ) palette = text_area . palette () palette . setColor ( QPalette . Base , QColor ( highlight . background_color )) text_area . setPalette ( palette ) text_area . setText ( \"\"\"from argparse import ArgumentParser def main(): parser = ArgumentParser() parser.add_argument(\"name\", help=\"Your name\") args = parser.parse_args() print(f\"Hello {args.name}\") if __name__ == \"__main__\": main() \"\"\" ) text_area . show () text_area . resize ( 400 , 200 ) app . exec_ () Qt Class QSyntaxHighlighter Methods background_color () property","title":"CodeSyntaxHighlight"},{"location":"utilities/code_syntax_highlight/#codesyntaxhighlight","text":"A code highlighter subclass of QSyntaxHighlighter that can be used to highlight code in a QTextEdit. Code lexer and available styles are from pygments python library List of available languages are available here . List of available styles are available here .","title":"CodeSyntaxHighlight"},{"location":"utilities/code_syntax_highlight/#example","text":"from qtpy.QtGui import QColor , QPalette from qtpy.QtWidgets import QApplication , QTextEdit from superqt.utils import CodeSyntaxHighlight app = QApplication ([]) text_area = QTextEdit () highlight = CodeSyntaxHighlight ( text_area . document (), \"python\" , \"monokai\" ) palette = text_area . palette () palette . setColor ( QPalette . Base , QColor ( highlight . background_color )) text_area . setPalette ( palette ) text_area . setText ( \"\"\"from argparse import ArgumentParser def main(): parser = ArgumentParser() parser.add_argument(\"name\", help=\"Your name\") args = parser.parse_args() print(f\"Hello {args.name}\") if __name__ == \"__main__\": main() \"\"\" ) text_area . show () text_area . resize ( 400 , 200 ) app . exec_ ()","title":"Example"},{"location":"utilities/code_syntax_highlight/#qt-class","text":"QSyntaxHighlighter","title":"Qt Class"},{"location":"utilities/code_syntax_highlight/#methods","text":"","title":"Methods"},{"location":"utilities/code_syntax_highlight/#superqt.utils._code_syntax_highlight.CodeSyntaxHighlight.background_color","text":"","title":"background_color()"},{"location":"utilities/fonticon/","text":"Font icons The superqt.fonticon module provides a set of utilities for working with font icons such as Font Awesome or Material Design Icons . Basic Example from fonticon_fa5 import FA5S from qtpy.QtCore import QSize from qtpy.QtWidgets import QApplication , QPushButton from superqt.fonticon import icon , pulse app = QApplication ([]) btn2 = QPushButton () btn2 . setIcon ( icon ( FA5S . smile , color = \"blue\" )) btn2 . setIconSize ( QSize ( 225 , 225 )) btn2 . show () app . exec () Font Icon plugins Ready-made fonticon packs are available as plugins: Font Awesome 5 pip install fonticon-fontawesome5 Font Awesome 6 pip install fonticon-fontawesome6 Material Design Icons pip install fonticon-materialdesignicons6 See also https://github.com/tlambert03/fonticon-bootstrapicons https://github.com/tlambert03/fonticon-linearicons https://github.com/tlambert03/fonticon-feather superqt.fonticon is a pluggable system, and font icon packs may use the \"superqt.fonticon\" entry point to register themselves with superqt. See fonticon-cookiecutter for a template, or look through the following repos for examples: https://github.com/tlambert03/fonticon-fontawesome6 https://github.com/tlambert03/fonticon-fontawesome5 https://github.com/tlambert03/fonticon-materialdesignicons6 API superqt . fonticon . icon ( glyph_key , scale_factor = DEFAULT_SCALING_FACTOR , color = None , opacity = 1 , animation = None , transform = None , states = {}) Create a QIcon for glyph_key , with a number of optional settings The glyph_key (e.g. 'fa5s.smile') represents a Font-family & style, and a glpyh. In most cases, the key should be provided by a plugin in the environment, like: fonticon-fontawesome5 ('fa5s' & 'fa5r' prefixes) fonticon-materialdesignicons6 ('mdi6' prefix) ...but fonts can also be added manually using addFont . Parameters: Name Type Description Default glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required scale_factor float , optional Scale factor (fraction of widget height), When widget icon is painted on widget, it will use font.setPixelSize(round(wdg.height() * scale_factor)) . by default 0.875. DEFAULT_SCALING_FACTOR color ValidColor , optional Color for the font, by default None. (e.g. The default QColor ) Valid color types include QColor , int , str , Qt.GlobalColor , tuple (of integer: RGB[A]) (anything that can be passed to QColor ). None opacity float , optional Opacity of icon, by default 1 1 animation Animation , optional Animation for the icon. A subclass of superqt.fonticon.Animation, that provides a concrete animate method. (see \"spin\" and \"pulse\" for examples). by default None. None transform QTransform , optional A QTransform to apply when painting the icon, by default None None states dict , optional Provide additional styling for the icon in different states. states must be a mapping of string to dict, where: the key represents a QIcon.State (\"on\", \"off\"), a QIcon.Mode (\"normal\", \"active\", \"selected\", \"disabled\"), or any combination of a state & mode separated by an underscore (e.g. \"off_active\", \"selected_on\", etc...). the value is a dict with all of the same key/value meanings listed above as parameters to this function (e.g. glyph_key , color , scale_factor , animation , etc...) Missing keys in the state dicts will be taken from the default options, provided by the paramters above. {} Returns: Type Description QFontIcon A subclass of QIcon. Can be used wherever QIcons are used, such as widget.setIcon() Examples: simple example (using the string 'fa5s.smile' assumes the fonticon-fontawesome5 plugin is installed) >>> btn = QPushButton () >>> btn . setIcon ( icon ( 'fa5s.smile' )) can also directly import from fonticon_fa5 >>> from fonticon_fa5 import FA5S >>> btn . setIcon ( icon ( FA5S . smile )) with animation >>> btn2 = QPushButton () >>> btn2 . setIcon ( icon ( FA5S . spinner , animation = pulse ( btn2 ))) complicated example >>> btn = QPushButton () >>> btn . setIcon ( ... icon ( ... FA5S . ambulance , ... color = \"blue\" , ... states = { ... \"active\" : { ... \"glyph\" : FA5S . bath , ... \"color\" : \"red\" , ... \"scale_factor\" : 0.5 , ... \"animation\" : pulse ( btn ), ... }, ... \"disabled\" : { ... \"color\" : \"green\" , ... \"scale_factor\" : 0.8 , ... \"animation\" : spin ( btn ) ... }, ... }, ... ) ... ) >>> btn . setIconSize ( QSize ( 256 , 256 )) >>> btn . show () superqt . fonticon . setTextIcon ( widget , glyph_key , size = None ) Set text on a widget to a specific font & glyph. This is an alternative to setting a QIcon with a pixmap. It may be easier to combine with dynamic stylesheets. Parameters: Name Type Description Default widget QWidget A widget supporting a setText method. required glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required size int , optional Size for QFont. passed to setPixelSize , by default None None superqt . fonticon . font ( font_prefix , size = None ) Create QFont for font_prefix Parameters: Name Type Description Default font_prefix str Font_prefix, such as 'fa5s' or 'mdi6', representing a font-family and style. required size int , optional Size for QFont. passed to setPixelSize , by default None None Returns: Type Description QFont QFont instance that can be used to add fonticons to widgets. superqt.fonticon.IconOpts dataclass Options for rendering an icon. Parameters: Name Type Description Default glyph_key str , optional The key of the glyph to use, e.g. 'fa5s.smile' , by default None _Unset scale_factor float , optional The scale factor to use, by default None _Unset color ValidColor , optional The color to use, by default None . Colors may be specified as a string, QColor , Qt.GlobalColor , or a 3 or 4-tuple of integers. _Unset opacity float , optional The opacity to use, by default None _Unset animation Animation , optional The animation to use, by default None _Unset superqt . fonticon . addFont ( filepath , prefix , charmap = None ) Add OTF/TTF file at filepath to the registry under prefix . If you'd like to later use a fontkey in the form of prefix.some-name , then charmap must be provided and provide a mapping for all of the glyph names to their unicode numbers. If a charmap is not provided, glyphs must be directly accessed with their unicode as something like key.\uffff . Note in most cases, users will not need this. Instead, they should install a font plugin, like: fonticon-fontawesome5 fonticon-materialdesignicons6 Parameters: Name Type Description Default filepath str Path to an OTF or TTF file containing the fonts required prefix str A prefix that will represent this font file when used for lookup. For example, 'fa5s' for 'Font-Awesome 5 Solid'. required charmap Dict [ str , str ], optional optional mapping for all of the glyph names to their unicode numbers. See note above. None Returns: Type Description Tuple [ str , str ], optional font-family and font-style for the file just registered, or None if something goes wrong. Animations the animation parameter to icon() accepts a subclass of Animation that will be superqt.fonticon.Animation Bases: ABC Base icon animation class. animate ( painter ) abstractmethod Setup and start the timer for the animation. superqt.fonticon.pulse Bases: spin Animation that spins an icon in slower, discrete steps. superqt.fonticon.spin Bases: Animation Animation that smoothly spins an icon.","title":"Font icons"},{"location":"utilities/fonticon/#font-icons","text":"The superqt.fonticon module provides a set of utilities for working with font icons such as Font Awesome or Material Design Icons .","title":"Font icons"},{"location":"utilities/fonticon/#basic-example","text":"from fonticon_fa5 import FA5S from qtpy.QtCore import QSize from qtpy.QtWidgets import QApplication , QPushButton from superqt.fonticon import icon , pulse app = QApplication ([]) btn2 = QPushButton () btn2 . setIcon ( icon ( FA5S . smile , color = \"blue\" )) btn2 . setIconSize ( QSize ( 225 , 225 )) btn2 . show () app . exec ()","title":"Basic Example"},{"location":"utilities/fonticon/#font-icon-plugins","text":"Ready-made fonticon packs are available as plugins:","title":"Font Icon plugins"},{"location":"utilities/fonticon/#font-awesome-5","text":"pip install fonticon-fontawesome5","title":"Font Awesome 5"},{"location":"utilities/fonticon/#font-awesome-6","text":"pip install fonticon-fontawesome6","title":"Font Awesome 6"},{"location":"utilities/fonticon/#material-design-icons","text":"pip install fonticon-materialdesignicons6","title":"Material Design Icons"},{"location":"utilities/fonticon/#see-also","text":"https://github.com/tlambert03/fonticon-bootstrapicons https://github.com/tlambert03/fonticon-linearicons https://github.com/tlambert03/fonticon-feather superqt.fonticon is a pluggable system, and font icon packs may use the \"superqt.fonticon\" entry point to register themselves with superqt. See fonticon-cookiecutter for a template, or look through the following repos for examples: https://github.com/tlambert03/fonticon-fontawesome6 https://github.com/tlambert03/fonticon-fontawesome5 https://github.com/tlambert03/fonticon-materialdesignicons6","title":"See also"},{"location":"utilities/fonticon/#api","text":"","title":"API"},{"location":"utilities/fonticon/#superqt.fonticon.icon","text":"Create a QIcon for glyph_key , with a number of optional settings The glyph_key (e.g. 'fa5s.smile') represents a Font-family & style, and a glpyh. In most cases, the key should be provided by a plugin in the environment, like: fonticon-fontawesome5 ('fa5s' & 'fa5r' prefixes) fonticon-materialdesignicons6 ('mdi6' prefix) ...but fonts can also be added manually using addFont . Parameters: Name Type Description Default glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required scale_factor float , optional Scale factor (fraction of widget height), When widget icon is painted on widget, it will use font.setPixelSize(round(wdg.height() * scale_factor)) . by default 0.875. DEFAULT_SCALING_FACTOR color ValidColor , optional Color for the font, by default None. (e.g. The default QColor ) Valid color types include QColor , int , str , Qt.GlobalColor , tuple (of integer: RGB[A]) (anything that can be passed to QColor ). None opacity float , optional Opacity of icon, by default 1 1 animation Animation , optional Animation for the icon. A subclass of superqt.fonticon.Animation, that provides a concrete animate method. (see \"spin\" and \"pulse\" for examples). by default None. None transform QTransform , optional A QTransform to apply when painting the icon, by default None None states dict , optional Provide additional styling for the icon in different states. states must be a mapping of string to dict, where: the key represents a QIcon.State (\"on\", \"off\"), a QIcon.Mode (\"normal\", \"active\", \"selected\", \"disabled\"), or any combination of a state & mode separated by an underscore (e.g. \"off_active\", \"selected_on\", etc...). the value is a dict with all of the same key/value meanings listed above as parameters to this function (e.g. glyph_key , color , scale_factor , animation , etc...) Missing keys in the state dicts will be taken from the default options, provided by the paramters above. {} Returns: Type Description QFontIcon A subclass of QIcon. Can be used wherever QIcons are used, such as widget.setIcon() Examples: simple example (using the string 'fa5s.smile' assumes the fonticon-fontawesome5 plugin is installed) >>> btn = QPushButton () >>> btn . setIcon ( icon ( 'fa5s.smile' )) can also directly import from fonticon_fa5 >>> from fonticon_fa5 import FA5S >>> btn . setIcon ( icon ( FA5S . smile )) with animation >>> btn2 = QPushButton () >>> btn2 . setIcon ( icon ( FA5S . spinner , animation = pulse ( btn2 ))) complicated example >>> btn = QPushButton () >>> btn . setIcon ( ... icon ( ... FA5S . ambulance , ... color = \"blue\" , ... states = { ... \"active\" : { ... \"glyph\" : FA5S . bath , ... \"color\" : \"red\" , ... \"scale_factor\" : 0.5 , ... \"animation\" : pulse ( btn ), ... }, ... \"disabled\" : { ... \"color\" : \"green\" , ... \"scale_factor\" : 0.8 , ... \"animation\" : spin ( btn ) ... }, ... }, ... ) ... ) >>> btn . setIconSize ( QSize ( 256 , 256 )) >>> btn . show ()","title":"icon()"},{"location":"utilities/fonticon/#superqt.fonticon.setTextIcon","text":"Set text on a widget to a specific font & glyph. This is an alternative to setting a QIcon with a pixmap. It may be easier to combine with dynamic stylesheets. Parameters: Name Type Description Default widget QWidget A widget supporting a setText method. required glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required size int , optional Size for QFont. passed to setPixelSize , by default None None","title":"setTextIcon()"},{"location":"utilities/fonticon/#superqt.fonticon.font","text":"Create QFont for font_prefix Parameters: Name Type Description Default font_prefix str Font_prefix, such as 'fa5s' or 'mdi6', representing a font-family and style. required size int , optional Size for QFont. passed to setPixelSize , by default None None Returns: Type Description QFont QFont instance that can be used to add fonticons to widgets.","title":"font()"},{"location":"utilities/fonticon/#superqt.fonticon.IconOpts","text":"Options for rendering an icon. Parameters: Name Type Description Default glyph_key str , optional The key of the glyph to use, e.g. 'fa5s.smile' , by default None _Unset scale_factor float , optional The scale factor to use, by default None _Unset color ValidColor , optional The color to use, by default None . Colors may be specified as a string, QColor , Qt.GlobalColor , or a 3 or 4-tuple of integers. _Unset opacity float , optional The opacity to use, by default None _Unset animation Animation , optional The animation to use, by default None _Unset","title":"IconOpts"},{"location":"utilities/fonticon/#superqt.fonticon.addFont","text":"Add OTF/TTF file at filepath to the registry under prefix . If you'd like to later use a fontkey in the form of prefix.some-name , then charmap must be provided and provide a mapping for all of the glyph names to their unicode numbers. If a charmap is not provided, glyphs must be directly accessed with their unicode as something like key.\uffff . Note in most cases, users will not need this. Instead, they should install a font plugin, like: fonticon-fontawesome5 fonticon-materialdesignicons6 Parameters: Name Type Description Default filepath str Path to an OTF or TTF file containing the fonts required prefix str A prefix that will represent this font file when used for lookup. For example, 'fa5s' for 'Font-Awesome 5 Solid'. required charmap Dict [ str , str ], optional optional mapping for all of the glyph names to their unicode numbers. See note above. None Returns: Type Description Tuple [ str , str ], optional font-family and font-style for the file just registered, or None if something goes wrong.","title":"addFont()"},{"location":"utilities/fonticon/#animations","text":"the animation parameter to icon() accepts a subclass of Animation that will be","title":"Animations"},{"location":"utilities/fonticon/#superqt.fonticon.Animation","text":"Bases: ABC Base icon animation class.","title":"Animation"},{"location":"utilities/fonticon/#superqt.fonticon._animations.Animation.animate","text":"Setup and start the timer for the animation.","title":"animate()"},{"location":"utilities/fonticon/#superqt.fonticon.pulse","text":"Bases: spin Animation that spins an icon in slower, discrete steps.","title":"pulse"},{"location":"utilities/fonticon/#superqt.fonticon.spin","text":"Bases: Animation Animation that smoothly spins an icon.","title":"spin"},{"location":"utilities/qmessagehandler/","text":"QMessageHandler superqt.utils.QMessageHandler A context manager to intercept messages from Qt. Parameters: Name Type Description Default logger logging . Logger , optional If provided, intercepted messages will be logged with logger at the corresponding python log level, by default None None Attributes: Name Type Description records list of tuple Captured messages. This is a 3-tuple of: (log_level: int, message: str, context: dict) Examples: >>> handler = QMessageHandler () >>> handler . install () # now all Qt output will be available at mh.records >>> with QMessageHandler () as handler : # temporarily install ... ... >>> logger = logging . getLogger ( __name__ ) >>> with QMessageHandler ( logger ): # re-reoute Qt messages to a python logger. ... ... __enter__ () Enter a context with this handler installed install () Install this handler (override the current QtMessageHandler). uninstall () Uninstall this handler, restoring the previous handler.","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#qmessagehandler","text":"","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#superqt.utils.QMessageHandler","text":"A context manager to intercept messages from Qt. Parameters: Name Type Description Default logger logging . Logger , optional If provided, intercepted messages will be logged with logger at the corresponding python log level, by default None None Attributes: Name Type Description records list of tuple Captured messages. This is a 3-tuple of: (log_level: int, message: str, context: dict) Examples: >>> handler = QMessageHandler () >>> handler . install () # now all Qt output will be available at mh.records >>> with QMessageHandler () as handler : # temporarily install ... ... >>> logger = logging . getLogger ( __name__ ) >>> with QMessageHandler ( logger ): # re-reoute Qt messages to a python logger. ... ...","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.__enter__","text":"Enter a context with this handler installed","title":"__enter__()"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.install","text":"Install this handler (override the current QtMessageHandler).","title":"install()"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.uninstall","text":"Uninstall this handler, restoring the previous handler.","title":"uninstall()"},{"location":"utilities/thread_decorators/","text":"Threading decorators superqt provides two decorators that help to ensure that given function is running in the desired thread: ensure_main_thread ensure_main_thread ensures that the decorated function/method runs in the main thread ensure_object_thread ensure_object_thread ensures that a decorated bound method of a QObject runs in the thread in which the instance lives ( see qt documentation for details ). Usage By default, functions are executed asynchronously (they return immediately with an instance of concurrent.futures.Future ). To block and wait for the result, see Synchronous mode from qtpy.QtCore import QObject from superqt import ensure_main_thread , ensure_object_thread @ensure_main_thread def sample_function (): print ( \"This function will run in main thread\" ) class SampleObject ( QObject ): def __init__ ( self ): super () . __init__ () self . _value = 1 @ensure_main_thread def sample_method1 ( self ): print ( \"This method will run in main thread\" ) @ensure_object_thread def sample_method3 ( self ): import time print ( \"sleeping\" ) time . sleep ( 1 ) print ( \"This method will run in object thread\" ) @property def value ( self ): print ( \"return value\" ) return self . _value @value . setter @ensure_object_thread def value ( self , value ): print ( \"this setter will run in object thread\" ) self . _value = value As can be seen in this example these decorators can also be used for setters. These decorators should not be used as replacement of Qt Signals but rather to interact with Qt objects from non Qt code. Synchronous mode If you'd like for the program to block and wait for the result of your function call, use the await_return=True parameter, and optionally specify a timeout. Important Using synchronous mode may significantly impact performance. from superqt import ensure_main_thread @ensure_main_thread def sample_function1 (): return 1 @ensure_main_thread ( await_return = True ) def sample_function2 (): return 2 assert sample_function1 () is None assert sample_function2 () == 2 # optionally, specify a timeout @ensure_main_thread ( await_return = True , timeout = 10000 ) def sample_function (): return 1","title":"Threading decorators"},{"location":"utilities/thread_decorators/#threading-decorators","text":"superqt provides two decorators that help to ensure that given function is running in the desired thread:","title":"Threading decorators"},{"location":"utilities/thread_decorators/#ensure_main_thread","text":"ensure_main_thread ensures that the decorated function/method runs in the main thread","title":"ensure_main_thread"},{"location":"utilities/thread_decorators/#ensure_object_thread","text":"ensure_object_thread ensures that a decorated bound method of a QObject runs in the thread in which the instance lives ( see qt documentation for details ).","title":"ensure_object_thread"},{"location":"utilities/thread_decorators/#usage","text":"By default, functions are executed asynchronously (they return immediately with an instance of concurrent.futures.Future ). To block and wait for the result, see Synchronous mode from qtpy.QtCore import QObject from superqt import ensure_main_thread , ensure_object_thread @ensure_main_thread def sample_function (): print ( \"This function will run in main thread\" ) class SampleObject ( QObject ): def __init__ ( self ): super () . __init__ () self . _value = 1 @ensure_main_thread def sample_method1 ( self ): print ( \"This method will run in main thread\" ) @ensure_object_thread def sample_method3 ( self ): import time print ( \"sleeping\" ) time . sleep ( 1 ) print ( \"This method will run in object thread\" ) @property def value ( self ): print ( \"return value\" ) return self . _value @value . setter @ensure_object_thread def value ( self , value ): print ( \"this setter will run in object thread\" ) self . _value = value As can be seen in this example these decorators can also be used for setters. These decorators should not be used as replacement of Qt Signals but rather to interact with Qt objects from non Qt code.","title":"Usage"},{"location":"utilities/thread_decorators/#synchronous-mode","text":"If you'd like for the program to block and wait for the result of your function call, use the await_return=True parameter, and optionally specify a timeout. Important Using synchronous mode may significantly impact performance. from superqt import ensure_main_thread @ensure_main_thread def sample_function1 (): return 1 @ensure_main_thread ( await_return = True ) def sample_function2 (): return 2 assert sample_function1 () is None assert sample_function2 () == 2 # optionally, specify a timeout @ensure_main_thread ( await_return = True , timeout = 10000 ) def sample_function (): return 1","title":"Synchronous mode"},{"location":"utilities/threading/","text":"Thread workers The objects in this module provide utilities for running tasks in a separate thread. In general (with the exception of new_worker_qthread ), everything here wraps Qt's QRunnable API . The highest level object is the @thread_worker decorator. It was originally written for napari , and was later extracted into superqt . You may also be interested in reading the napari documentation on this feature, which provides a more in-depth/introductory usage guide. For additional control, you can create your own FunctionWorker or GeneratorWorker objects. superqt.utils.WorkerBase Bases: QRunnable , Generic [ _R ] Base class for creating a Worker that can run in another thread. Parameters: Name Type Description Default SignalsClass type , optional A QObject subclass that contains signals, by default WorkerBaseSignals WorkerBaseSignals Attributes: Name Type Description signals WorkerBaseSignals signal emitter object. To allow identify which worker thread emitted signal. __getattr__ ( name ) Pass through attr requests to signals to simplify connection API. The goal is to enable worker.yielded.connect instead of worker.signals.yielded.connect . Because multiple inheritance of Qt classes is not well supported in PyQt, we have to use composition here (signals are provided by QObjects, and QRunnable is not a QObject). So this passthrough allows us to connect to signals on the _signals object. abort_requested () property Whether the worker has been requested to stop. await_workers ( msecs = None ) classmethod Ask all workers to quit, and wait up to msec for quit. Attempts to clean up all running workers by calling worker.quit() method. Any workers in the WorkerBase._worker_set set will have this method. By default, this function will block indefinitely, until worker threads finish. If a timeout is provided, a RuntimeError will be raised if the workers do not gracefully exit in the time requests, but the threads will NOT be killed. It is (currently) left to the user to use their OS to force-quit rogue threads. Important If the user does not put any yields in their function, and the function is super long, it will just hang... For instance, there's no graceful way to kill this thread in python: @thread_worker def ZZZzzz (): time . sleep ( 10000000 ) This is why it's always advisable to use a generator that periodically yields for long-running computations in another thread. See this stack-overflow post for a good discussion on the difficulty of killing a rogue python thread: Parameters: Name Type Description Default msecs int , optional Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. If msecs is None (the default), the timeout is ignored (waits for the last thread to exit). None Raises: Type Description RuntimeError If a timeout is provided and workers do not quit successfully within the time allotted. is_running () property Whether the worker has been started quit () Send a request to abort the worker. Note It is entirely up to subclasses to honor this method by checking self.abort_requested periodically in their worker.work method, and exiting if True . run () Start the worker. The end-user should never need to call this function. But it cannot be made private or renamed, since it is called by Qt. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work This is the function that actually gets called when calling QThreadPool.start(worker) . It simply wraps the work() method, and emits a few signals. Subclasses should NOT override this method (except with good reason), and instead should implement work() . start () Start this worker in a thread and add it to the global threadpool. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work work () Main method to execute the worker. The end-user should never need to call this function. But subclasses must implement this method (See GeneratorFunction.work for an example implementation). Minimally, it should check self.abort_requested periodically and exit if True. Examples: class MyWorker ( WorkerBase ): def work ( self ): i = 0 while True : if self . abort_requested : self . aborted . emit () break i += 1 if i > max_iters : break time . sleep ( 0.5 ) superqt.utils.FunctionWorker Bases: WorkerBase [ _R ] QRunnable with signals that wraps a simple long-running function. Note FunctionWorker does not provide a way to stop a very long-running function (e.g. time.sleep(10000) ). So whenever possible, it is better to implement your long running function as a generator that yields periodically, and use the GeneratorWorker instead. Parameters: Name Type Description Default func Callable A function to call in another thread required *args will be passed to the function () **kwargs will be passed to the function {} Raises: Type Description TypeError If func is a generator function and not a regular function. superqt.utils.GeneratorWorker Bases: WorkerBase , Generic [ _Y , _S , _R ] QRunnable with signals that wraps a long-running generator. Provides a convenient way to run a generator function in another thread, while allowing 2-way communication between threads, using plain-python generator syntax in the original function. Parameters: Name Type Description Default func callable The function being run in another thread. May be a generator function. required SignalsClass type , optional A QObject subclass that contains signals, by default GeneratorWorkerSignals GeneratorWorkerSignals *args Will be passed to func on instantiation () **kwargs Will be passed to func on instantiation {} is_paused () property Whether the worker is currently paused. pause () Request to pause the worker. resume () Send a request to resume the worker. send ( value ) Send a value into the function (if a generator was used). toggle_pause () Request to pause the worker if playing or resume if paused. work () Core event loop that calls the original function. Enters a continual loop, yielding and returning from the original function. Checks for various events (quit, pause, resume, etc...). (To clarify: we are creating a rudimentary event loop here because there IS NO Qt event loop running in the other thread to hook into) Convenience functions superqt . utils . thread_worker ( function = None , start_thread = None , connect = None , worker_class = None , ignore_errors = False ) Decorator that runs a function in a separate thread when called. When called, the decorated function returns a WorkerBase . See create_worker for additional keyword arguments that can be used when calling the function. The returned worker will have these signals: started : emitted when the work is started finished : emitted when the work is finished returned : emitted with return value errored : emitted with error object on Exception It will also have a worker.start() method that can be used to start execution of the function in another thread. (useful if you need to connect callbacks to signals prior to execution) If the decorated function is a generator, the returned worker will also provide these signals: yielded : emitted with yielded values paused : emitted when a running job has successfully paused resumed : emitted when a paused job has successfully resumed aborted : emitted when a running job is successfully aborted And these methods: quit : ask the thread to quit toggle_paused : toggle the running state of the thread. send : send a value into the generator. (This requires that your decorator function uses the value = yield syntax) Parameters: Name Type Description Default function callable Function to call in another thread. For communication between threads may be a generator function. None start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None connect Dict [ str , Union [ Callable , Sequence ]] A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None worker_class Type [ WorkerBase ] The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False Returns: Type Description callable function that creates a worker, puts it in a new thread and returns the worker instance. Examples: @thread_worker def long_function ( start , end ): # do work, periodically yielding i = start while i <= end : time . sleep ( 0.1 ) yield i # do teardown return 'anything' # call the function to start running in another thread. worker = long_function () # connect signals here if desired... or they may be added using the # `connect` argument in the `@thread_worker` decorator... in which # case the worker will start immediately when long_function() is called worker . start () superqt . utils . create_worker ( func , * args , _start_thread = None , _connect = None , _worker_class = None , _ignore_errors = False , ** kwargs ) Convenience function to start a function in another thread. By default, uses FunctionWorker for functions and GeneratorWorker for generators, but a custom WorkerBase subclass may be provided. If so, it must be a subclass of WorkerBase , which defines a standard set of signals and a run method. Parameters: Name Type Description Default func Callable The function to call in another thread. required _start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None _connect Dict [ str , Union [ Callable , Sequence ]], optional A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None _worker_class type of The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None _ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False *args will be passed to func () **kwargs will be passed to func {} Returns: Name Type Description worker WorkerBase An instantiated worker. If _start_thread was False , the worker will have a .start() method that can be used to start the thread. Raises: Type Description TypeError If a worker_class is provided that is not a subclass of WorkerBase. TypeError If _connect is provided and is not a dict of {str: callable} Examples: def long_function ( duration ): import time time . sleep ( duration ) worker = create_worker ( long_function , 10 ) superqt . utils . new_worker_qthread ( Worker , * args , _start_thread = False , _connect = None , ** kwargs ) This is a convenience function to start a worker in a QThread . In most cases, the thread_worker decorator is sufficient and preferable. But this allows the user to completely customize the Worker object. However, they must then maintain control over the thread and clean up appropriately. It follows the pattern described here and in the qt thread docs see also: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ A QThread object is not a thread! It should be thought of as a class to manage a thread, not as the actual code or object that runs in that thread. The QThread object is created on the main thread and lives there. Worker objects which derive from QObject are the things that actually do the work. They can be moved to a QThread as is done here. Mostly ignorable detail While the signals/slots syntax of the worker looks very similar to standard \"single-threaded\" signals & slots, note that inter-thread signals and slots (automatically) use an event-based QueuedConnection, while intra-thread signals use a DirectConnection. See Signals and Slots Across Threads Parameters: Name Type Description Default Worker QObject QObject type that implements a work() method. The Worker should also emit a finished signal when the work is done. required _start_thread bool If True, thread will be started immediately, otherwise, thread must be manually started with thread.start(). False _connect dict Optional dictionary of {signal: function} to connect to the new worker. for instance: _connect = {'incremented': myfunc} will result in: worker.incremented.connect(myfunc) None *args will be passed to the Worker class on instantiation. () **kwargs will be passed to the Worker class on instantiation. {} Returns: Name Type Description worker WorkerBase The created worker. thread QThread The thread on which the worker is running. Examples: Create some QObject that has a long-running work method: class Worker ( QObject ): finished = Signal () increment = Signal ( int ) def __init__ ( self , argument ): super () . __init__ () self . argument = argument @Slot () def work ( self ): # some long running task... import time for i in range ( 10 ): time . sleep ( 1 ) self . increment . emit ( i ) self . finished . emit () worker , thread = new_worker_qthread ( Worker , 'argument' , _start_thread = True , _connect = { 'increment' : print }, )","title":"Thread workers"},{"location":"utilities/threading/#thread-workers","text":"The objects in this module provide utilities for running tasks in a separate thread. In general (with the exception of new_worker_qthread ), everything here wraps Qt's QRunnable API . The highest level object is the @thread_worker decorator. It was originally written for napari , and was later extracted into superqt . You may also be interested in reading the napari documentation on this feature, which provides a more in-depth/introductory usage guide. For additional control, you can create your own FunctionWorker or GeneratorWorker objects.","title":"Thread workers"},{"location":"utilities/threading/#superqt.utils.WorkerBase","text":"Bases: QRunnable , Generic [ _R ] Base class for creating a Worker that can run in another thread. Parameters: Name Type Description Default SignalsClass type , optional A QObject subclass that contains signals, by default WorkerBaseSignals WorkerBaseSignals Attributes: Name Type Description signals WorkerBaseSignals signal emitter object. To allow identify which worker thread emitted signal.","title":"WorkerBase"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.__getattr__","text":"Pass through attr requests to signals to simplify connection API. The goal is to enable worker.yielded.connect instead of worker.signals.yielded.connect . Because multiple inheritance of Qt classes is not well supported in PyQt, we have to use composition here (signals are provided by QObjects, and QRunnable is not a QObject). So this passthrough allows us to connect to signals on the _signals object.","title":"__getattr__()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.abort_requested","text":"Whether the worker has been requested to stop.","title":"abort_requested()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.await_workers","text":"Ask all workers to quit, and wait up to msec for quit. Attempts to clean up all running workers by calling worker.quit() method. Any workers in the WorkerBase._worker_set set will have this method. By default, this function will block indefinitely, until worker threads finish. If a timeout is provided, a RuntimeError will be raised if the workers do not gracefully exit in the time requests, but the threads will NOT be killed. It is (currently) left to the user to use their OS to force-quit rogue threads. Important If the user does not put any yields in their function, and the function is super long, it will just hang... For instance, there's no graceful way to kill this thread in python: @thread_worker def ZZZzzz (): time . sleep ( 10000000 ) This is why it's always advisable to use a generator that periodically yields for long-running computations in another thread. See this stack-overflow post for a good discussion on the difficulty of killing a rogue python thread: Parameters: Name Type Description Default msecs int , optional Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. If msecs is None (the default), the timeout is ignored (waits for the last thread to exit). None Raises: Type Description RuntimeError If a timeout is provided and workers do not quit successfully within the time allotted.","title":"await_workers()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.is_running","text":"Whether the worker has been started","title":"is_running()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.quit","text":"Send a request to abort the worker. Note It is entirely up to subclasses to honor this method by checking self.abort_requested periodically in their worker.work method, and exiting if True .","title":"quit()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.run","text":"Start the worker. The end-user should never need to call this function. But it cannot be made private or renamed, since it is called by Qt. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work This is the function that actually gets called when calling QThreadPool.start(worker) . It simply wraps the work() method, and emits a few signals. Subclasses should NOT override this method (except with good reason), and instead should implement work() .","title":"run()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.start","text":"Start this worker in a thread and add it to the global threadpool. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work","title":"start()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.work","text":"Main method to execute the worker. The end-user should never need to call this function. But subclasses must implement this method (See GeneratorFunction.work for an example implementation). Minimally, it should check self.abort_requested periodically and exit if True. Examples: class MyWorker ( WorkerBase ): def work ( self ): i = 0 while True : if self . abort_requested : self . aborted . emit () break i += 1 if i > max_iters : break time . sleep ( 0.5 )","title":"work()"},{"location":"utilities/threading/#superqt.utils.FunctionWorker","text":"Bases: WorkerBase [ _R ] QRunnable with signals that wraps a simple long-running function. Note FunctionWorker does not provide a way to stop a very long-running function (e.g. time.sleep(10000) ). So whenever possible, it is better to implement your long running function as a generator that yields periodically, and use the GeneratorWorker instead. Parameters: Name Type Description Default func Callable A function to call in another thread required *args will be passed to the function () **kwargs will be passed to the function {} Raises: Type Description TypeError If func is a generator function and not a regular function.","title":"FunctionWorker"},{"location":"utilities/threading/#superqt.utils.GeneratorWorker","text":"Bases: WorkerBase , Generic [ _Y , _S , _R ] QRunnable with signals that wraps a long-running generator. Provides a convenient way to run a generator function in another thread, while allowing 2-way communication between threads, using plain-python generator syntax in the original function. Parameters: Name Type Description Default func callable The function being run in another thread. May be a generator function. required SignalsClass type , optional A QObject subclass that contains signals, by default GeneratorWorkerSignals GeneratorWorkerSignals *args Will be passed to func on instantiation () **kwargs Will be passed to func on instantiation {}","title":"GeneratorWorker"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.is_paused","text":"Whether the worker is currently paused.","title":"is_paused()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.pause","text":"Request to pause the worker.","title":"pause()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.resume","text":"Send a request to resume the worker.","title":"resume()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.send","text":"Send a value into the function (if a generator was used).","title":"send()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.toggle_pause","text":"Request to pause the worker if playing or resume if paused.","title":"toggle_pause()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.work","text":"Core event loop that calls the original function. Enters a continual loop, yielding and returning from the original function. Checks for various events (quit, pause, resume, etc...). (To clarify: we are creating a rudimentary event loop here because there IS NO Qt event loop running in the other thread to hook into)","title":"work()"},{"location":"utilities/threading/#convenience-functions","text":"","title":"Convenience functions"},{"location":"utilities/threading/#superqt.utils.thread_worker","text":"Decorator that runs a function in a separate thread when called. When called, the decorated function returns a WorkerBase . See create_worker for additional keyword arguments that can be used when calling the function. The returned worker will have these signals: started : emitted when the work is started finished : emitted when the work is finished returned : emitted with return value errored : emitted with error object on Exception It will also have a worker.start() method that can be used to start execution of the function in another thread. (useful if you need to connect callbacks to signals prior to execution) If the decorated function is a generator, the returned worker will also provide these signals: yielded : emitted with yielded values paused : emitted when a running job has successfully paused resumed : emitted when a paused job has successfully resumed aborted : emitted when a running job is successfully aborted And these methods: quit : ask the thread to quit toggle_paused : toggle the running state of the thread. send : send a value into the generator. (This requires that your decorator function uses the value = yield syntax) Parameters: Name Type Description Default function callable Function to call in another thread. For communication between threads may be a generator function. None start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None connect Dict [ str , Union [ Callable , Sequence ]] A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None worker_class Type [ WorkerBase ] The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False Returns: Type Description callable function that creates a worker, puts it in a new thread and returns the worker instance. Examples: @thread_worker def long_function ( start , end ): # do work, periodically yielding i = start while i <= end : time . sleep ( 0.1 ) yield i # do teardown return 'anything' # call the function to start running in another thread. worker = long_function () # connect signals here if desired... or they may be added using the # `connect` argument in the `@thread_worker` decorator... in which # case the worker will start immediately when long_function() is called worker . start ()","title":"thread_worker()"},{"location":"utilities/threading/#superqt.utils.create_worker","text":"Convenience function to start a function in another thread. By default, uses FunctionWorker for functions and GeneratorWorker for generators, but a custom WorkerBase subclass may be provided. If so, it must be a subclass of WorkerBase , which defines a standard set of signals and a run method. Parameters: Name Type Description Default func Callable The function to call in another thread. required _start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None _connect Dict [ str , Union [ Callable , Sequence ]], optional A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None _worker_class type of The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None _ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False *args will be passed to func () **kwargs will be passed to func {} Returns: Name Type Description worker WorkerBase An instantiated worker. If _start_thread was False , the worker will have a .start() method that can be used to start the thread. Raises: Type Description TypeError If a worker_class is provided that is not a subclass of WorkerBase. TypeError If _connect is provided and is not a dict of {str: callable} Examples: def long_function ( duration ): import time time . sleep ( duration ) worker = create_worker ( long_function , 10 )","title":"create_worker()"},{"location":"utilities/threading/#superqt.utils.new_worker_qthread","text":"This is a convenience function to start a worker in a QThread . In most cases, the thread_worker decorator is sufficient and preferable. But this allows the user to completely customize the Worker object. However, they must then maintain control over the thread and clean up appropriately. It follows the pattern described here and in the qt thread docs see also: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ A QThread object is not a thread! It should be thought of as a class to manage a thread, not as the actual code or object that runs in that thread. The QThread object is created on the main thread and lives there. Worker objects which derive from QObject are the things that actually do the work. They can be moved to a QThread as is done here. Mostly ignorable detail While the signals/slots syntax of the worker looks very similar to standard \"single-threaded\" signals & slots, note that inter-thread signals and slots (automatically) use an event-based QueuedConnection, while intra-thread signals use a DirectConnection. See Signals and Slots Across Threads Parameters: Name Type Description Default Worker QObject QObject type that implements a work() method. The Worker should also emit a finished signal when the work is done. required _start_thread bool If True, thread will be started immediately, otherwise, thread must be manually started with thread.start(). False _connect dict Optional dictionary of {signal: function} to connect to the new worker. for instance: _connect = {'incremented': myfunc} will result in: worker.incremented.connect(myfunc) None *args will be passed to the Worker class on instantiation. () **kwargs will be passed to the Worker class on instantiation. {} Returns: Name Type Description worker WorkerBase The created worker. thread QThread The thread on which the worker is running. Examples: Create some QObject that has a long-running work method: class Worker ( QObject ): finished = Signal () increment = Signal ( int ) def __init__ ( self , argument ): super () . __init__ () self . argument = argument @Slot () def work ( self ): # some long running task... import time for i in range ( 10 ): time . sleep ( 1 ) self . increment . emit ( i ) self . finished . emit () worker , thread = new_worker_qthread ( Worker , 'argument' , _start_thread = True , _connect = { 'increment' : print }, )","title":"new_worker_qthread()"},{"location":"utilities/throttling/","text":"Throttling & Debouncing These utilities allow you to throttle or debounce a function. This is useful when you have a function that is called multiple times in a short period of time, and you want to make sure it is only \"actually\" called once (or at least no more than a certain frequency). For background on throttling and debouncing, see: https://blog.openreplay.com/forever-functional-debouncing-and-throttling-for-performance https://css-tricks.com/debouncing-throttling-explained-examples/ superqt . utils . qdebounced ( func = None , timeout = 100 , leading = False , timer_type = Qt . TimerType . PreciseTimer ) Creates a debounced function that delays invoking func . func will not be invoked until timeout ms have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the debounced function. Subsequent calls to the debounced function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default False False timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer superqt . utils . qthrottled ( func = None , timeout = 100 , leading = True , timer_type = Qt . TimerType . PreciseTimer ) Creates a throttled function that invokes func at most once per timeout. The throttled function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options to indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the throttled function. Subsequent calls to the throttled function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default True True timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer superqt.utils.QSignalDebouncer Bases: GenericSignalThrottler A Signal Debouncer. This object's triggered signal will not be emitted until self.timeout() milliseconds have elapsed since the last time triggered was emitted. superqt.utils.QSignalThrottler Bases: GenericSignalThrottler A Signal Throttler. This object's triggered signal will emit at most once per timeout (set with setTimeout()). superqt.utils._throttler.GenericSignalThrottler Bases: QObject cancel () Cancel any pending emissions. emissionPolicy () Return the emission policy (trailing or leading). flush () Force emission of any pending emissions. kind () Return the kind of throttler (throttler or debouncer). setTimeout ( timeout ) Set timeout in milliseconds setTimerType ( timerType ) Set current Qt.TimerType. throttle () Emit triggered if not running, then start timer. timeout () Return current timeout in milliseconds. timerType () Return current Qt.TimerType .","title":"Throttling & Debouncing"},{"location":"utilities/throttling/#throttling-debouncing","text":"These utilities allow you to throttle or debounce a function. This is useful when you have a function that is called multiple times in a short period of time, and you want to make sure it is only \"actually\" called once (or at least no more than a certain frequency). For background on throttling and debouncing, see: https://blog.openreplay.com/forever-functional-debouncing-and-throttling-for-performance https://css-tricks.com/debouncing-throttling-explained-examples/","title":"Throttling & Debouncing"},{"location":"utilities/throttling/#superqt.utils.qdebounced","text":"Creates a debounced function that delays invoking func . func will not be invoked until timeout ms have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the debounced function. Subsequent calls to the debounced function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default False False timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer","title":"qdebounced()"},{"location":"utilities/throttling/#superqt.utils.qthrottled","text":"Creates a throttled function that invokes func at most once per timeout. The throttled function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options to indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the throttled function. Subsequent calls to the throttled function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default True True timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer","title":"qthrottled()"},{"location":"utilities/throttling/#superqt.utils.QSignalDebouncer","text":"Bases: GenericSignalThrottler A Signal Debouncer. This object's triggered signal will not be emitted until self.timeout() milliseconds have elapsed since the last time triggered was emitted.","title":"QSignalDebouncer"},{"location":"utilities/throttling/#superqt.utils.QSignalThrottler","text":"Bases: GenericSignalThrottler A Signal Throttler. This object's triggered signal will emit at most once per timeout (set with setTimeout()).","title":"QSignalThrottler"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler","text":"Bases: QObject","title":"GenericSignalThrottler"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.cancel","text":"Cancel any pending emissions.","title":"cancel()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.emissionPolicy","text":"Return the emission policy (trailing or leading).","title":"emissionPolicy()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.flush","text":"Force emission of any pending emissions.","title":"flush()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.kind","text":"Return the kind of throttler (throttler or debouncer).","title":"kind()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.setTimeout","text":"Set timeout in milliseconds","title":"setTimeout()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.setTimerType","text":"Set current Qt.TimerType.","title":"setTimerType()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.throttle","text":"Emit triggered if not running, then start timer.","title":"throttle()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.timeout","text":"Return current timeout in milliseconds.","title":"timeout()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.timerType","text":"Return current Qt.TimerType .","title":"timerType()"},{"location":"widgets/","text":"Widgets The following are QWidget subclasses: Sliders and Numerical Inputs Widget Description QDoubleRangeSlider Multi-handle slider for float values QDoubleSlider Slider for float values QLabeledDoubleRangeSlider QDoubleRangeSlider variant with editable labels for each handle QLabeledDoubleSlider QSlider for float values with editable QSpinBox with the current value QLabeledRangeSlider QRangeSlider variant, with editable labels for each handle QLabeledSlider QSlider with editable QSpinBox that shows the current value QLargeIntSpinBox QSpinbox that accepts arbitrarily large integers QRangeSlider Multi-handle slider Labels and categorical inputs Widget Description QElidingLabel A QLabel variant that will elide text (add \u2026 ) to fit width. QEnumComboBox QComboBox that populates the combobox from a python Enum QSearchableComboBox QComboBox variant that filters available options based on text input QSearchableListWidget QListWidget variant with search field that filters available options Frames and containers Widget Description QCollapsible A collapsible widget to hide and unhide child widgets.","title":"Widgets"},{"location":"widgets/#widgets","text":"The following are QWidget subclasses:","title":"Widgets"},{"location":"widgets/#sliders-and-numerical-inputs","text":"Widget Description QDoubleRangeSlider Multi-handle slider for float values QDoubleSlider Slider for float values QLabeledDoubleRangeSlider QDoubleRangeSlider variant with editable labels for each handle QLabeledDoubleSlider QSlider for float values with editable QSpinBox with the current value QLabeledRangeSlider QRangeSlider variant, with editable labels for each handle QLabeledSlider QSlider with editable QSpinBox that shows the current value QLargeIntSpinBox QSpinbox that accepts arbitrarily large integers QRangeSlider Multi-handle slider","title":"Sliders and Numerical Inputs"},{"location":"widgets/#labels-and-categorical-inputs","text":"Widget Description QElidingLabel A QLabel variant that will elide text (add \u2026 ) to fit width. QEnumComboBox QComboBox that populates the combobox from a python Enum QSearchableComboBox QComboBox variant that filters available options based on text input QSearchableListWidget QListWidget variant with search field that filters available options","title":"Labels and categorical inputs"},{"location":"widgets/#frames-and-containers","text":"Widget Description QCollapsible A collapsible widget to hide and unhide child widgets.","title":"Frames and containers"},{"location":"widgets/qcollapsible/","text":"QCollapsible Collapsible QFrame that can be expanded or collapsed by clicking on the header. from qtpy.QtWidgets import QApplication , QLabel , QPushButton from superqt import QCollapsible app = QApplication ([]) collapsible = QCollapsible ( \"Advanced analysis\" ) collapsible . addWidget ( QLabel ( \"This is the inside of the collapsible frame\" )) for i in range ( 10 ): collapsible . addWidget ( QPushButton ( f \"Content button { i + 1 } \" )) collapsible . expand ( animate = False ) collapsible . show () app . exec_ () Qt Class QFrame Methods A collapsible widget to hide and unhide child widgets. Based on https://stackoverflow.com/a/68141638 addWidget ( widget : QWidget ) Add a widget to the central content widget's layout. collapse ( animate : bool = True ) Collapse (hide) the collapsible section content () -> QWidget Return the current content widget. expand ( animate : bool = True ) Expand (show) the collapsible section isExpanded () -> bool Return whether the collapsible section is visible locked () -> bool Return True if collapse/expand is disabled removeWidget ( widget : QWidget ) Remove widget from the central content widget's layout. setContent ( content : QWidget ) Replace central widget (the widget that gets expanded/collapsed). setDuration ( msecs : int ) Set duration of the collapse/expand animation. setEasingCurve ( easing : QEasingCurve ) Set the easing curve for the collapse/expand animation setLocked ( locked : bool = True ) Set whether collapse/expand is disabled setText ( text : str ) Set the text of the toggle button. text () -> str Return the text of the toggle button.","title":"QCollapsible"},{"location":"widgets/qcollapsible/#qcollapsible","text":"Collapsible QFrame that can be expanded or collapsed by clicking on the header. from qtpy.QtWidgets import QApplication , QLabel , QPushButton from superqt import QCollapsible app = QApplication ([]) collapsible = QCollapsible ( \"Advanced analysis\" ) collapsible . addWidget ( QLabel ( \"This is the inside of the collapsible frame\" )) for i in range ( 10 ): collapsible . addWidget ( QPushButton ( f \"Content button { i + 1 } \" )) collapsible . expand ( animate = False ) collapsible . show () app . exec_ ()","title":"QCollapsible"},{"location":"widgets/qcollapsible/#qt-class","text":"QFrame","title":"Qt Class"},{"location":"widgets/qcollapsible/#methods","text":"A collapsible widget to hide and unhide child widgets. Based on https://stackoverflow.com/a/68141638","title":"Methods"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.addWidget","text":"Add a widget to the central content widget's layout.","title":"addWidget()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.collapse","text":"Collapse (hide) the collapsible section","title":"collapse()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.content","text":"Return the current content widget.","title":"content()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.expand","text":"Expand (show) the collapsible section","title":"expand()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.isExpanded","text":"Return whether the collapsible section is visible","title":"isExpanded()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.locked","text":"Return True if collapse/expand is disabled","title":"locked()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.removeWidget","text":"Remove widget from the central content widget's layout.","title":"removeWidget()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setContent","text":"Replace central widget (the widget that gets expanded/collapsed).","title":"setContent()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setDuration","text":"Set duration of the collapse/expand animation.","title":"setDuration()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setEasingCurve","text":"Set the easing curve for the collapse/expand animation","title":"setEasingCurve()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setLocked","text":"Set whether collapse/expand is disabled","title":"setLocked()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setText","text":"Set the text of the toggle button.","title":"setText()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.text","text":"Return the text of the toggle button.","title":"text()"},{"location":"widgets/qdoublerangeslider/","text":"QDoubleRangeSlider Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleRangeSlider app = QApplication ([]) slider = QDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ () Qt Class QSlider Methods","title":"QDoubleRangeSlider"},{"location":"widgets/qdoublerangeslider/#qdoublerangeslider","text":"Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleRangeSlider app = QApplication ([]) slider = QDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ ()","title":"QDoubleRangeSlider"},{"location":"widgets/qdoublerangeslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qdoublerangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qdoubleslider/","text":"QDoubleSlider QSlider variant that accepts floating point values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleSlider app = QApplication ([]) slider = QDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue ( 0.5 ) slider . show () app . exec_ () Qt Class QSlider Methods","title":"QDoubleSlider"},{"location":"widgets/qdoubleslider/#qdoubleslider","text":"QSlider variant that accepts floating point values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleSlider app = QApplication ([]) slider = QDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue ( 0.5 ) slider . show () app . exec_ ()","title":"QDoubleSlider"},{"location":"widgets/qdoubleslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qdoubleslider/#methods","text":"","title":"Methods"},{"location":"widgets/qelidinglabel/","text":"QElidingLabel QLabel variant that will elide text (i.e. add an ellipsis) if it is too long to fit in the available space. from qtpy.QtWidgets import QApplication from superqt import QElidingLabel app = QApplication ([]) widget = QElidingLabel ( \"a skj skjfskfj sdlf sdfl sdlfk jsdf sdlkf jdsf dslfksdl sdlfk sdf sdl \" \"fjsdlf kjsdlfk laskdfsal as lsdfjdsl kfjdslf asfd dslkjfldskf sdlkfj\" ) widget . setWordWrap ( True ) widget . resize ( 300 , 20 ) widget . show () app . exec_ () Qt Class QLabel Methods A QLabel variant that will elide text (add '\u2026') to fit width. QElidingLabel() QElidingLabel(parent: Optional[QWidget], f: Qt.WindowFlags = ...) QElidingLabel(text: str, parent: Optional[QWidget] = None, f: Qt.WindowFlags = ...) For a multiline eliding label, use setWordWrap(True) . In this case, text will wrap to fit the width, and only the last line will be elided. When wordWrap() is True, sizeHint() will return the size required to fit the full text. elideMode () -> Qt . TextElideMode The current Qt.TextElideMode. setElideMode ( mode : Qt . TextElideMode ) Set the elide mode to a Qt.TextElideMode. wrapText ( text , width , font = None ) -> List [ str ] staticmethod Returns text , split as it would be wrapped for width , given font . Static method.","title":"QElidingLabel"},{"location":"widgets/qelidinglabel/#qelidinglabel","text":"QLabel variant that will elide text (i.e. add an ellipsis) if it is too long to fit in the available space. from qtpy.QtWidgets import QApplication from superqt import QElidingLabel app = QApplication ([]) widget = QElidingLabel ( \"a skj skjfskfj sdlf sdfl sdlfk jsdf sdlkf jdsf dslfksdl sdlfk sdf sdl \" \"fjsdlf kjsdlfk laskdfsal as lsdfjdsl kfjdslf asfd dslkjfldskf sdlkfj\" ) widget . setWordWrap ( True ) widget . resize ( 300 , 20 ) widget . show () app . exec_ ()","title":"QElidingLabel"},{"location":"widgets/qelidinglabel/#qt-class","text":"QLabel","title":"Qt Class"},{"location":"widgets/qelidinglabel/#methods","text":"A QLabel variant that will elide text (add '\u2026') to fit width. QElidingLabel() QElidingLabel(parent: Optional[QWidget], f: Qt.WindowFlags = ...) QElidingLabel(text: str, parent: Optional[QWidget] = None, f: Qt.WindowFlags = ...) For a multiline eliding label, use setWordWrap(True) . In this case, text will wrap to fit the width, and only the last line will be elided. When wordWrap() is True, sizeHint() will return the size required to fit the full text.","title":"Methods"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.elideMode","text":"The current Qt.TextElideMode.","title":"elideMode()"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.setElideMode","text":"Set the elide mode to a Qt.TextElideMode.","title":"setElideMode()"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.wrapText","text":"Returns text , split as it would be wrapped for width , given font . Static method.","title":"wrapText()"},{"location":"widgets/qenumcombobox/","text":"QEnumComboBox QEnumComboBox is a variant of QComboBox that populates the items in the combobox based on a python Enum class. In addition to all the methods provided by QComboBox , this subclass adds the methods enumClass / setEnumClass to get/set the current Enum class represented by the combobox, and currentEnum / setCurrentEnum to get/set the current Enum member in the combobox. There is also a new signal currentEnumChanged(enum) analogous to currentIndexChanged and currentTextChanged . Method like insertItem and addItem are blocked and try of its usage will end with RuntimeError from enum import Enum from qtpy.QtWidgets import QApplication from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 app = QApplication ([]) combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) combo . show () app . exec_ () Another option is to use optional enum_class argument of constructor and change # option A: combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) # option B: combo = QEnumComboBox ( enum_class = SampleEnum ) Allow None QEnumComboBox also allows using Optional type annotation: from enum import Enum from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 # as usual: # you must create a QApplication before create a widget. combo = QEnumComboBox () combo . setEnumClass ( SampleEnum , allow_none = True ) In this case there is added option ---- and the currentEnum() method will return None when it is selected. Qt Class QComboBox Signals currentEnumChanged Methods ComboBox presenting options from a python Enum. If the Enum class does not implement __str__ then a human readable name is created from the name of the enum member, replacing underscores with spaces. currentEnum () -> Optional [ EnumType ] current value as Enum member enumClass () -> Optional [ EnumMeta ] return current Enum class isOptional () -> bool return if current enum is with optional annotation setCurrentEnum ( value : Optional [ EnumType ]) -> None Set value with Enum. setEnumClass ( enum : Optional [ EnumMeta ], allow_none = False ) Set enum class from which members value should be selected","title":"QEnumComboBox"},{"location":"widgets/qenumcombobox/#qenumcombobox","text":"QEnumComboBox is a variant of QComboBox that populates the items in the combobox based on a python Enum class. In addition to all the methods provided by QComboBox , this subclass adds the methods enumClass / setEnumClass to get/set the current Enum class represented by the combobox, and currentEnum / setCurrentEnum to get/set the current Enum member in the combobox. There is also a new signal currentEnumChanged(enum) analogous to currentIndexChanged and currentTextChanged . Method like insertItem and addItem are blocked and try of its usage will end with RuntimeError from enum import Enum from qtpy.QtWidgets import QApplication from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 app = QApplication ([]) combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) combo . show () app . exec_ () Another option is to use optional enum_class argument of constructor and change # option A: combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) # option B: combo = QEnumComboBox ( enum_class = SampleEnum )","title":"QEnumComboBox"},{"location":"widgets/qenumcombobox/#allow-none","text":"QEnumComboBox also allows using Optional type annotation: from enum import Enum from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 # as usual: # you must create a QApplication before create a widget. combo = QEnumComboBox () combo . setEnumClass ( SampleEnum , allow_none = True ) In this case there is added option ---- and the currentEnum() method will return None when it is selected.","title":"Allow None"},{"location":"widgets/qenumcombobox/#qt-class","text":"QComboBox","title":"Qt Class"},{"location":"widgets/qenumcombobox/#signals","text":"","title":"Signals"},{"location":"widgets/qenumcombobox/#currentenumchanged","text":"","title":"currentEnumChanged"},{"location":"widgets/qenumcombobox/#methods","text":"ComboBox presenting options from a python Enum. If the Enum class does not implement __str__ then a human readable name is created from the name of the enum member, replacing underscores with spaces.","title":"Methods"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.currentEnum","text":"current value as Enum member","title":"currentEnum()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.enumClass","text":"return current Enum class","title":"enumClass()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.isOptional","text":"return if current enum is with optional annotation","title":"isOptional()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.setCurrentEnum","text":"Set value with Enum.","title":"setCurrentEnum()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.setEnumClass","text":"Set enum class from which members value should be selected","title":"setEnumClass()"},{"location":"widgets/qlabeleddoublerangeslider/","text":"QLabeledDoubleRangeSlider Labeled Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleRangeSlider app = QApplication ([]) slider = QLabeledDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ () Qt Class QAbstractSlider Enums QLabeledDoubleRangeSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue QLabeledDoubleRangeSlider.LabelPosition NoLabel LabelsAbove LabelsBelow Methods decimals () -> int setDecimals ( prec : int )","title":"QLabeledDoubleRangeSlider"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangeslider","text":"Labeled Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleRangeSlider app = QApplication ([]) slider = QLabeledDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ ()","title":"QLabeledDoubleRangeSlider"},{"location":"widgets/qlabeleddoublerangeslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeleddoublerangeslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangeslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledDoubleRangeSlider.EdgeLabelMode"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangesliderlabelposition","text":"NoLabel LabelsAbove LabelsBelow","title":"QLabeledDoubleRangeSlider.LabelPosition"},{"location":"widgets/qlabeleddoublerangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeleddoublerangeslider/#superqt.sliders._labeled.QLabeledDoubleRangeSlider.decimals","text":"","title":"decimals()"},{"location":"widgets/qlabeleddoublerangeslider/#superqt.sliders._labeled.QLabeledDoubleRangeSlider.setDecimals","text":"","title":"setDecimals()"},{"location":"widgets/qlabeleddoubleslider/","text":"QLabeledDoubleSlider QDoubleSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleSlider app = QApplication ([]) slider = QLabeledDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 2.5 ) slider . setValue ( 1.3 ) slider . show () app . exec_ () Qt Class QAbstractSlider Enums QLabeledDoubleSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods decimals () -> int setDecimals ( prec : int )","title":"QLabeledDoubleSlider"},{"location":"widgets/qlabeleddoubleslider/#qlabeleddoubleslider","text":"QDoubleSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleSlider app = QApplication ([]) slider = QLabeledDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 2.5 ) slider . setValue ( 1.3 ) slider . show () app . exec_ ()","title":"QLabeledDoubleSlider"},{"location":"widgets/qlabeleddoubleslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeleddoubleslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeleddoubleslider/#qlabeleddoubleslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledDoubleSlider.EdgeLabelMode"},{"location":"widgets/qlabeleddoubleslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeleddoubleslider/#superqt.sliders._labeled.QLabeledDoubleSlider.decimals","text":"","title":"decimals()"},{"location":"widgets/qlabeleddoubleslider/#superqt.sliders._labeled.QLabeledDoubleSlider.setDecimals","text":"","title":"setDecimals()"},{"location":"widgets/qlabeledrangeslider/","text":"QLabeledRangeSlider Labeled variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledRangeSlider app = QApplication ([]) slider = QLabeledRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () Qt Class QAbstractSlider Signals editingFinished Enums QLabeledRangeSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue QLabeledRangeSlider.LabelPosition NoLabel LabelsAbove LabelsBelow Methods edgeLabelMode () -> EdgeLabelMode Return current EdgeLabelMode . handleLabelPosition () -> LabelPosition Return where/whether labels are shown adjacent to slider handles. setEdgeLabelMode ( opt : EdgeLabelMode ) Set EdgeLabelMode , controls what is shown at the min/max labels. setHandleLabelPosition ( opt : LabelPosition ) -> LabelPosition Set where/whether labels are shown adjacent to slider handles. If you find that you need to fine tune the position of the handle labels: QLabeledRangeSlider.label_shift_x : adjust horizontal label position QLabeledRangeSlider.label_shift_y : adjust vertical label position","title":"QLabeledRangeSlider"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangeslider","text":"Labeled variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledRangeSlider app = QApplication ([]) slider = QLabeledRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ ()","title":"QLabeledRangeSlider"},{"location":"widgets/qlabeledrangeslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeledrangeslider/#signals","text":"","title":"Signals"},{"location":"widgets/qlabeledrangeslider/#editingfinished","text":"","title":"editingFinished"},{"location":"widgets/qlabeledrangeslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangeslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledRangeSlider.EdgeLabelMode"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangesliderlabelposition","text":"NoLabel LabelsAbove LabelsBelow","title":"QLabeledRangeSlider.LabelPosition"},{"location":"widgets/qlabeledrangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.edgeLabelMode","text":"Return current EdgeLabelMode .","title":"edgeLabelMode()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.handleLabelPosition","text":"Return where/whether labels are shown adjacent to slider handles.","title":"handleLabelPosition()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.setEdgeLabelMode","text":"Set EdgeLabelMode , controls what is shown at the min/max labels.","title":"setEdgeLabelMode()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.setHandleLabelPosition","text":"Set where/whether labels are shown adjacent to slider handles. If you find that you need to fine tune the position of the handle labels: QLabeledRangeSlider.label_shift_x : adjust horizontal label position QLabeledRangeSlider.label_shift_y : adjust vertical label position","title":"setHandleLabelPosition()"},{"location":"widgets/qlabeledslider/","text":"QLabeledSlider QSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledSlider app = QApplication ([]) slider = QLabeledSlider ( Qt . Orientation . Horizontal ) slider . setValue ( 42 ) slider . show () app . exec_ () Qt Class QAbstractSlider Signals editingFinished Enums QLabeledSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods edgeLabelMode () -> EdgeLabelMode Return current EdgeLabelMode . setEdgeLabelMode ( opt : EdgeLabelMode ) -> None Set the EdgeLabelMode .","title":"QLabeledSlider"},{"location":"widgets/qlabeledslider/#qlabeledslider","text":"QSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledSlider app = QApplication ([]) slider = QLabeledSlider ( Qt . Orientation . Horizontal ) slider . setValue ( 42 ) slider . show () app . exec_ ()","title":"QLabeledSlider"},{"location":"widgets/qlabeledslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeledslider/#signals","text":"","title":"Signals"},{"location":"widgets/qlabeledslider/#editingfinished","text":"","title":"editingFinished"},{"location":"widgets/qlabeledslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeledslider/#qlabeledslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledSlider.EdgeLabelMode"},{"location":"widgets/qlabeledslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeledslider/#superqt.sliders._labeled.QLabeledSlider.edgeLabelMode","text":"Return current EdgeLabelMode .","title":"edgeLabelMode()"},{"location":"widgets/qlabeledslider/#superqt.sliders._labeled.QLabeledSlider.setEdgeLabelMode","text":"Set the EdgeLabelMode .","title":"setEdgeLabelMode()"},{"location":"widgets/qlargeintspinbox/","text":"QLargeIntSpinBox QSpinBox variant that allows to enter large integers, without overflow. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLargeIntSpinBox app = QApplication ([]) slider = QLargeIntSpinBox () slider . setRange ( 0 , 4.53e8 ) slider . setValue ( 4.53e8 ) slider . show () app . exec_ () Qt Class QAbstractSpinBox Signals valueChanged textChanged Methods An integer spinboxes backed by unbound python integer Qt's built-in QSpinBox is backed by a signed 32-bit integer. This could become limiting, particularly in large dense segmentations. This class behaves like a QSpinBox backed by an unbound python int. Does not yet support \"prefix\", \"suffix\" or \"specialValue\" like QSpinBox. maximum () minimum () setMaximum ( max ) setMinimum ( min ) setRange ( minimum , maximum ) setSingleStep ( step ) setValue ( value ) singleStep () value ()","title":"QLargeIntSpinBox"},{"location":"widgets/qlargeintspinbox/#qlargeintspinbox","text":"QSpinBox variant that allows to enter large integers, without overflow. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLargeIntSpinBox app = QApplication ([]) slider = QLargeIntSpinBox () slider . setRange ( 0 , 4.53e8 ) slider . setValue ( 4.53e8 ) slider . show () app . exec_ ()","title":"QLargeIntSpinBox"},{"location":"widgets/qlargeintspinbox/#qt-class","text":"QAbstractSpinBox","title":"Qt Class"},{"location":"widgets/qlargeintspinbox/#signals","text":"","title":"Signals"},{"location":"widgets/qlargeintspinbox/#valuechanged","text":"","title":"valueChanged"},{"location":"widgets/qlargeintspinbox/#textchanged","text":"","title":"textChanged"},{"location":"widgets/qlargeintspinbox/#methods","text":"An integer spinboxes backed by unbound python integer Qt's built-in QSpinBox is backed by a signed 32-bit integer. This could become limiting, particularly in large dense segmentations. This class behaves like a QSpinBox backed by an unbound python int. Does not yet support \"prefix\", \"suffix\" or \"specialValue\" like QSpinBox.","title":"Methods"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.maximum","text":"","title":"maximum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.minimum","text":"","title":"minimum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setMaximum","text":"","title":"setMaximum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setMinimum","text":"","title":"setMinimum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setRange","text":"","title":"setRange()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setSingleStep","text":"","title":"setSingleStep()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setValue","text":"","title":"setValue()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.singleStep","text":"","title":"singleStep()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.value","text":"","title":"value()"},{"location":"widgets/qrangeslider/","text":"QRangeSlider A multi-handle slider widget than can be used to select a range of values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QRangeSlider app = QApplication ([]) slider = QRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () QRangeSlider inherits from QSlider and attempts to match the Qt API as closely as possible It uses platform-specific styles (for handle, groove, & ticks) but also supports QSS style sheets. Supports mouse wheel events Supports more than 2 handles (e.g. slider.setValue([0, 10, 60, 80]) ) As QRangeSlider inherits from QtWidgets.QSlider , you can use all of the same methods available in the QSlider API . The major difference is that value() and sliderPosition() are reimplemented as tuples of int (where the length of the tuple is equal to the number of handles in the slider.) These options are in addition to the Qt QSlider API, and control the behavior of the bar between handles. getter setter type default description barIsVisible setBarIsVisible hideBar / showBar bool True Whether the bar between handles is visible. barMovesAllHandles setBarMovesAllHandles bool True Whether clicking on the bar moves all handles or just the nearest barIsRigid setBarIsRigid bool True Whether bar length is constant or \"elastic\" when dragging the bar beyond min/max. Screenshots code that generates the images below import os from qtpy import QtCore from qtpy import QtWidgets as QtW # patch for Qt 5.15 on macos >= 12 os . environ [ \"USE_MAC_SLIDER_PATCH\" ] = \"1\" from superqt import QRangeSlider # noqa QSS = \"\"\" QSlider { min-height: 20px; } QSlider::groove:horizontal { border: 0px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #888, stop:1 #ddd); height: 20px; border-radius: 10px; } QSlider::handle { background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.35, fy:0.3, stop:0 #eef, stop:1 #002); height: 20px; width: 20px; border-radius: 10px; } QSlider::sub-page:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); border-top-left-radius: 10px; border-bottom-left-radius: 10px; } QRangeSlider { qproperty-barColor: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); } \"\"\" Horizontal = QtCore . Qt . Orientation . Horizontal class DemoWidget ( QtW . QWidget ): def __init__ ( self ) -> None : super () . __init__ () reg_hslider = QtW . QSlider ( Horizontal ) reg_hslider . setValue ( 50 ) range_hslider = QRangeSlider ( Horizontal ) range_hslider . setValue (( 20 , 80 )) multi_range_hslider = QRangeSlider ( Horizontal ) multi_range_hslider . setValue (( 11 , 33 , 66 , 88 )) multi_range_hslider . setTickPosition ( QtW . QSlider . TickPosition . TicksAbove ) styled_reg_hslider = QtW . QSlider ( Horizontal ) styled_reg_hslider . setValue ( 50 ) styled_reg_hslider . setStyleSheet ( QSS ) styled_range_hslider = QRangeSlider ( Horizontal ) styled_range_hslider . setValue (( 20 , 80 )) styled_range_hslider . setStyleSheet ( QSS ) reg_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) reg_vslider . setValue ( 50 ) range_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_vslider . setValue (( 22 , 77 )) tick_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) tick_vslider . setValue ( 55 ) tick_vslider . setTickPosition ( QtW . QSlider . TicksRight ) range_tick_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_tick_vslider . setValue (( 22 , 77 )) range_tick_vslider . setTickPosition ( QtW . QSlider . TicksLeft ) szp = QtW . QSizePolicy . Maximum left = QtW . QWidget () left . setLayout ( QtW . QVBoxLayout ()) left . setContentsMargins ( 2 , 2 , 2 , 2 ) label1 = QtW . QLabel ( \"Regular QSlider Unstyled\" ) label2 = QtW . QLabel ( \"QRangeSliders Unstyled\" ) label3 = QtW . QLabel ( \"Styled Sliders (using same stylesheet)\" ) label1 . setSizePolicy ( szp , szp ) label2 . setSizePolicy ( szp , szp ) label3 . setSizePolicy ( szp , szp ) left . layout () . addWidget ( label1 ) left . layout () . addWidget ( reg_hslider ) left . layout () . addWidget ( label2 ) left . layout () . addWidget ( range_hslider ) left . layout () . addWidget ( multi_range_hslider ) left . layout () . addWidget ( label3 ) left . layout () . addWidget ( styled_reg_hslider ) left . layout () . addWidget ( styled_range_hslider ) right = QtW . QWidget () right . setLayout ( QtW . QHBoxLayout ()) right . setContentsMargins ( 15 , 5 , 5 , 0 ) right . layout () . setSpacing ( 30 ) right . layout () . addWidget ( reg_vslider ) right . layout () . addWidget ( range_vslider ) right . layout () . addWidget ( tick_vslider ) right . layout () . addWidget ( range_tick_vslider ) self . setLayout ( QtW . QHBoxLayout ()) self . layout () . addWidget ( left ) self . layout () . addWidget ( right ) self . setGeometry ( 600 , 300 , 580 , 300 ) self . activateWindow () self . show () if __name__ == \"__main__\" : import sys from pathlib import Path dest = Path ( \"screenshots\" ) dest . mkdir ( exist_ok = True ) app = QtW . QApplication ([]) demo = DemoWidget () if \"-snap\" in sys . argv : import platform QtW . QApplication . processEvents () demo . grab () . save ( str ( dest / f \"demo_ { platform . system () . lower () } .png\" )) else : app . exec_ () macOS Catalina Big Sur Windows Linux Qt Class QSlider Methods MultiHandle Range Slider widget. Same API as QSlider, but value , setValue , sliderPosition , and setSliderPosition are all sequences of integers. The valueChanged and sliderMoved signals also both emit a tuple of integers. barColor = Property ( QtGui . QBrush , _getBarColor , _setBarColor ) class-attribute The color of the bar between the first and last handle. applyMacStylePatch () -> str Apply a QSS patch to fix sliders on macos>=12 with QT < 6. see FAQ for more details. barIsRigid () -> bool Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True . barIsVisible () -> bool Whether to show the bar between the first and last handle. barMovesAllHandles () -> bool Whether clicking on the bar moves all handles (default), or just the nearest. hideBar () -> None Hide the bar between the first and last handle. setBarIsRigid ( val : bool = True ) -> None Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True . setBarMovesAllHandles ( val : bool = True ) -> None Whether clicking on the bar moves all handles (default), or just the nearest. setBarVisible ( val : bool = True ) -> None Whether to show the bar between the first and last handle. showBar () -> None Show the bar between the first and last handle. Type changes Note the following changes in types compared to the QSlider API: value () -> Tuple [ int , ... ] setValue ( val : Sequence [ int ]) -> None # Signal valueChanged ( Tuple [ int , ... ]) sliderPosition () -> Tuple [ int , ... ] setSliderPosition ( val : Sequence [ int ]) -> None sliderMoved ( Tuple [ int , ... ])","title":"QRangeSlider"},{"location":"widgets/qrangeslider/#qrangeslider","text":"A multi-handle slider widget than can be used to select a range of values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QRangeSlider app = QApplication ([]) slider = QRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () QRangeSlider inherits from QSlider and attempts to match the Qt API as closely as possible It uses platform-specific styles (for handle, groove, & ticks) but also supports QSS style sheets. Supports mouse wheel events Supports more than 2 handles (e.g. slider.setValue([0, 10, 60, 80]) ) As QRangeSlider inherits from QtWidgets.QSlider , you can use all of the same methods available in the QSlider API . The major difference is that value() and sliderPosition() are reimplemented as tuples of int (where the length of the tuple is equal to the number of handles in the slider.) These options are in addition to the Qt QSlider API, and control the behavior of the bar between handles. getter setter type default description barIsVisible setBarIsVisible hideBar / showBar bool True Whether the bar between handles is visible. barMovesAllHandles setBarMovesAllHandles bool True Whether clicking on the bar moves all handles or just the nearest barIsRigid setBarIsRigid bool True Whether bar length is constant or \"elastic\" when dragging the bar beyond min/max.","title":"QRangeSlider"},{"location":"widgets/qrangeslider/#screenshots","text":"code that generates the images below import os from qtpy import QtCore from qtpy import QtWidgets as QtW # patch for Qt 5.15 on macos >= 12 os . environ [ \"USE_MAC_SLIDER_PATCH\" ] = \"1\" from superqt import QRangeSlider # noqa QSS = \"\"\" QSlider { min-height: 20px; } QSlider::groove:horizontal { border: 0px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #888, stop:1 #ddd); height: 20px; border-radius: 10px; } QSlider::handle { background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.35, fy:0.3, stop:0 #eef, stop:1 #002); height: 20px; width: 20px; border-radius: 10px; } QSlider::sub-page:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); border-top-left-radius: 10px; border-bottom-left-radius: 10px; } QRangeSlider { qproperty-barColor: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); } \"\"\" Horizontal = QtCore . Qt . Orientation . Horizontal class DemoWidget ( QtW . QWidget ): def __init__ ( self ) -> None : super () . __init__ () reg_hslider = QtW . QSlider ( Horizontal ) reg_hslider . setValue ( 50 ) range_hslider = QRangeSlider ( Horizontal ) range_hslider . setValue (( 20 , 80 )) multi_range_hslider = QRangeSlider ( Horizontal ) multi_range_hslider . setValue (( 11 , 33 , 66 , 88 )) multi_range_hslider . setTickPosition ( QtW . QSlider . TickPosition . TicksAbove ) styled_reg_hslider = QtW . QSlider ( Horizontal ) styled_reg_hslider . setValue ( 50 ) styled_reg_hslider . setStyleSheet ( QSS ) styled_range_hslider = QRangeSlider ( Horizontal ) styled_range_hslider . setValue (( 20 , 80 )) styled_range_hslider . setStyleSheet ( QSS ) reg_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) reg_vslider . setValue ( 50 ) range_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_vslider . setValue (( 22 , 77 )) tick_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) tick_vslider . setValue ( 55 ) tick_vslider . setTickPosition ( QtW . QSlider . TicksRight ) range_tick_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_tick_vslider . setValue (( 22 , 77 )) range_tick_vslider . setTickPosition ( QtW . QSlider . TicksLeft ) szp = QtW . QSizePolicy . Maximum left = QtW . QWidget () left . setLayout ( QtW . QVBoxLayout ()) left . setContentsMargins ( 2 , 2 , 2 , 2 ) label1 = QtW . QLabel ( \"Regular QSlider Unstyled\" ) label2 = QtW . QLabel ( \"QRangeSliders Unstyled\" ) label3 = QtW . QLabel ( \"Styled Sliders (using same stylesheet)\" ) label1 . setSizePolicy ( szp , szp ) label2 . setSizePolicy ( szp , szp ) label3 . setSizePolicy ( szp , szp ) left . layout () . addWidget ( label1 ) left . layout () . addWidget ( reg_hslider ) left . layout () . addWidget ( label2 ) left . layout () . addWidget ( range_hslider ) left . layout () . addWidget ( multi_range_hslider ) left . layout () . addWidget ( label3 ) left . layout () . addWidget ( styled_reg_hslider ) left . layout () . addWidget ( styled_range_hslider ) right = QtW . QWidget () right . setLayout ( QtW . QHBoxLayout ()) right . setContentsMargins ( 15 , 5 , 5 , 0 ) right . layout () . setSpacing ( 30 ) right . layout () . addWidget ( reg_vslider ) right . layout () . addWidget ( range_vslider ) right . layout () . addWidget ( tick_vslider ) right . layout () . addWidget ( range_tick_vslider ) self . setLayout ( QtW . QHBoxLayout ()) self . layout () . addWidget ( left ) self . layout () . addWidget ( right ) self . setGeometry ( 600 , 300 , 580 , 300 ) self . activateWindow () self . show () if __name__ == \"__main__\" : import sys from pathlib import Path dest = Path ( \"screenshots\" ) dest . mkdir ( exist_ok = True ) app = QtW . QApplication ([]) demo = DemoWidget () if \"-snap\" in sys . argv : import platform QtW . QApplication . processEvents () demo . grab () . save ( str ( dest / f \"demo_ { platform . system () . lower () } .png\" )) else : app . exec_ ()","title":"Screenshots"},{"location":"widgets/qrangeslider/#macos","text":"","title":"macOS"},{"location":"widgets/qrangeslider/#catalina","text":"","title":"Catalina"},{"location":"widgets/qrangeslider/#big-sur","text":"","title":"Big Sur"},{"location":"widgets/qrangeslider/#windows","text":"","title":"Windows"},{"location":"widgets/qrangeslider/#linux","text":"","title":"Linux"},{"location":"widgets/qrangeslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qrangeslider/#methods","text":"MultiHandle Range Slider widget. Same API as QSlider, but value , setValue , sliderPosition , and setSliderPosition are all sequences of integers. The valueChanged and sliderMoved signals also both emit a tuple of integers.","title":"Methods"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barColor","text":"The color of the bar between the first and last handle.","title":"barColor"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.applyMacStylePatch","text":"Apply a QSS patch to fix sliders on macos>=12 with QT < 6. see FAQ for more details.","title":"applyMacStylePatch()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barIsRigid","text":"Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True .","title":"barIsRigid()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barIsVisible","text":"Whether to show the bar between the first and last handle.","title":"barIsVisible()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barMovesAllHandles","text":"Whether clicking on the bar moves all handles (default), or just the nearest.","title":"barMovesAllHandles()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.hideBar","text":"Hide the bar between the first and last handle.","title":"hideBar()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarIsRigid","text":"Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True .","title":"setBarIsRigid()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarMovesAllHandles","text":"Whether clicking on the bar moves all handles (default), or just the nearest.","title":"setBarMovesAllHandles()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarVisible","text":"Whether to show the bar between the first and last handle.","title":"setBarVisible()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.showBar","text":"Show the bar between the first and last handle.","title":"showBar()"},{"location":"widgets/qrangeslider/#type-changes","text":"Note the following changes in types compared to the QSlider API: value () -> Tuple [ int , ... ] setValue ( val : Sequence [ int ]) -> None # Signal valueChanged ( Tuple [ int , ... ]) sliderPosition () -> Tuple [ int , ... ] setSliderPosition ( val : Sequence [ int ]) -> None sliderMoved ( Tuple [ int , ... ])","title":"Type changes"},{"location":"widgets/qsearchablecombobox/","text":"QSearchableComboBox QSearchableComboBox is a variant of QComboBox that allow to filter list of options by enter part of text. It could be drop in replacement for QComboBox . from qtpy.QtWidgets import QApplication from superqt import QSearchableComboBox app = QApplication ([]) combo = QSearchableComboBox () combo . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) combo . show () app . exec_ () Qt Class QComboBox","title":"QSearchableComboBox"},{"location":"widgets/qsearchablecombobox/#qsearchablecombobox","text":"QSearchableComboBox is a variant of QComboBox that allow to filter list of options by enter part of text. It could be drop in replacement for QComboBox . from qtpy.QtWidgets import QApplication from superqt import QSearchableComboBox app = QApplication ([]) combo = QSearchableComboBox () combo . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) combo . show () app . exec_ ()","title":"QSearchableComboBox"},{"location":"widgets/qsearchablecombobox/#qt-class","text":"QComboBox","title":"Qt Class"},{"location":"widgets/qsearchablelistwidget/","text":"QSearchableListWidget QSearchableListWidget is a variant of QListWidget that add text entry above list widget that allow to filter list of available options. Due to implementation details, this widget it does not inherit directly from QListWidget but it does fully satisfy its api. The only limitation is that it cannot be used as argument of QListWidgetItem constructor. from qtpy.QtWidgets import QApplication from superqt import QSearchableListWidget app = QApplication ([]) slider = QSearchableListWidget () slider . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) slider . show () app . exec_ () Qt Class QWidget Methods addItem ( * args ) addItems ( * args ) insertItem ( * args ) insertItems ( * args ) update_visible ( text )","title":"QSearchableListWidget"},{"location":"widgets/qsearchablelistwidget/#qsearchablelistwidget","text":"QSearchableListWidget is a variant of QListWidget that add text entry above list widget that allow to filter list of available options. Due to implementation details, this widget it does not inherit directly from QListWidget but it does fully satisfy its api. The only limitation is that it cannot be used as argument of QListWidgetItem constructor. from qtpy.QtWidgets import QApplication from superqt import QSearchableListWidget app = QApplication ([]) slider = QSearchableListWidget () slider . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) slider . show () app . exec_ ()","title":"QSearchableListWidget"},{"location":"widgets/qsearchablelistwidget/#qt-class","text":"QWidget","title":"Qt Class"},{"location":"widgets/qsearchablelistwidget/#methods","text":"","title":"Methods"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.addItem","text":"","title":"addItem()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.addItems","text":"","title":"addItems()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.insertItem","text":"","title":"insertItem()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.insertItems","text":"","title":"insertItems()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.update_visible","text":"","title":"update_visible()"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"superqt \"missing\" widgets and components for PyQt/PySide This repository aims to provide high-quality community-contributed Qt widgets and components for PyQt & PySide that are not provided in the native QtWidgets module. Components are tested on: macOS, Windows, & Linux Python 3.7 and above PyQt5 (5.11 and above) & PyQt6 PySide2 (5.11 and above) & PySide6 Installation pip install superqt conda install -c conda-forge superqt Usage See the Widgets and Utilities pages for features offered by superqt.","title":"superqt"},{"location":"#superqt","text":"","title":"superqt"},{"location":"#missing-widgets-and-components-for-pyqtpyside","text":"This repository aims to provide high-quality community-contributed Qt widgets and components for PyQt & PySide that are not provided in the native QtWidgets module. Components are tested on: macOS, Windows, & Linux Python 3.7 and above PyQt5 (5.11 and above) & PyQt6 PySide2 (5.11 and above) & PySide6","title":"\"missing\" widgets and components for PyQt/PySide"},{"location":"#installation","text":"pip install superqt conda install -c conda-forge superqt","title":"Installation"},{"location":"#usage","text":"See the Widgets and Utilities pages for features offered by superqt.","title":"Usage"},{"location":"faq/","text":"FAQ Sliders not dragging properly on MacOS 12+ Details On MacOS Monterey, with Qt5, there is a bug that causes all sliders (including native Qt sliders) to not respond properly to drag events. See: https://bugreports.qt.io/browse/QTBUG-98093 https://github.com/napari/superqt/issues/74 Superqt includes a workaround for this issue, but it is not perfect, and it requires using a custom stylesheet (which may interfere with your own styles). Note that you may not see this issue if you're already using custom stylesheets. To opt in to the workaround, do any of the following: set the environment variable USE_MAC_SLIDER_PATCH=1 before importing superqt (note: this is safe to use even if you're targeting more than just MacOS 12, it will only be applied when needed) call the applyMacStylePatch() method on any of the superqt slider subclasses (note, this will override your slider styles) apply the stylesheet manually: from superqt.sliders import MONTEREY_SLIDER_STYLES_FIX slider . setStyleSheet ( MONTEREY_SLIDER_STYLES_FIX )","title":"FAQ"},{"location":"faq/#faq","text":"","title":"FAQ"},{"location":"faq/#sliders-not-dragging-properly-on-macos-12","text":"Details On MacOS Monterey, with Qt5, there is a bug that causes all sliders (including native Qt sliders) to not respond properly to drag events. See: https://bugreports.qt.io/browse/QTBUG-98093 https://github.com/napari/superqt/issues/74 Superqt includes a workaround for this issue, but it is not perfect, and it requires using a custom stylesheet (which may interfere with your own styles). Note that you may not see this issue if you're already using custom stylesheets. To opt in to the workaround, do any of the following: set the environment variable USE_MAC_SLIDER_PATCH=1 before importing superqt (note: this is safe to use even if you're targeting more than just MacOS 12, it will only be applied when needed) call the applyMacStylePatch() method on any of the superqt slider subclasses (note, this will override your slider styles) apply the stylesheet manually: from superqt.sliders import MONTEREY_SLIDER_STYLES_FIX slider . setStyleSheet ( MONTEREY_SLIDER_STYLES_FIX )","title":"Sliders not dragging properly on MacOS 12+"},{"location":"utilities/","text":"Utilities Font Icons Object Description addFont Add an OTF/TTF file at to the font registry. font Create QFont for a given font-icon font family key icon Create a QIcon for font-con glyph key setTextIcon Set text on a QWidget to a specific font & glyph. IconFont Helper class that provides a standard way to create an IconFont . IconOpts Options for rendering an icon Animation Base class for adding animations to a font-icon. Threading tools Object Description ensure_main_thread Decorator that ensures a function is called in the main QApplication thread. ensure_object_thread Decorator that ensures a QObject method is called in the object's thread. FunctionWorker QRunnable with signals that wraps a simple long-running function. GeneratorWorker QRunnable with signals that wraps a long-running generator. create_worker Create a worker to run a target function in another thread. thread_worker Decorator for create_worker , turn a function into a worker. Miscellaneous Object Description QMessageHandler A context manager to intercept messages from Qt. CodeSyntaxHighlight A QSyntaxHighlighter for code syntax highlighting.","title":"Utilities"},{"location":"utilities/#utilities","text":"","title":"Utilities"},{"location":"utilities/#font-icons","text":"Object Description addFont Add an OTF/TTF file at to the font registry. font Create QFont for a given font-icon font family key icon Create a QIcon for font-con glyph key setTextIcon Set text on a QWidget to a specific font & glyph. IconFont Helper class that provides a standard way to create an IconFont . IconOpts Options for rendering an icon Animation Base class for adding animations to a font-icon.","title":"Font Icons"},{"location":"utilities/#threading-tools","text":"Object Description ensure_main_thread Decorator that ensures a function is called in the main QApplication thread. ensure_object_thread Decorator that ensures a QObject method is called in the object's thread. FunctionWorker QRunnable with signals that wraps a simple long-running function. GeneratorWorker QRunnable with signals that wraps a long-running generator. create_worker Create a worker to run a target function in another thread. thread_worker Decorator for create_worker , turn a function into a worker.","title":"Threading tools"},{"location":"utilities/#miscellaneous","text":"Object Description QMessageHandler A context manager to intercept messages from Qt. CodeSyntaxHighlight A QSyntaxHighlighter for code syntax highlighting.","title":"Miscellaneous"},{"location":"utilities/code_syntax_highlight/","text":"CodeSyntaxHighlight A code highlighter subclass of QSyntaxHighlighter that can be used to highlight code in a QTextEdit. Code lexer and available styles are from pygments python library List of available languages are available here . List of available styles are available here . Example from qtpy.QtGui import QColor , QPalette from qtpy.QtWidgets import QApplication , QTextEdit from superqt.utils import CodeSyntaxHighlight app = QApplication ([]) text_area = QTextEdit () highlight = CodeSyntaxHighlight ( text_area . document (), \"python\" , \"monokai\" ) palette = text_area . palette () palette . setColor ( QPalette . Base , QColor ( highlight . background_color )) text_area . setPalette ( palette ) text_area . setText ( \"\"\"from argparse import ArgumentParser def main(): parser = ArgumentParser() parser.add_argument(\"name\", help=\"Your name\") args = parser.parse_args() print(f\"Hello {args.name}\") if __name__ == \"__main__\": main() \"\"\" ) text_area . show () text_area . resize ( 400 , 200 ) app . exec_ () Qt Class QSyntaxHighlighter Methods background_color () property","title":"CodeSyntaxHighlight"},{"location":"utilities/code_syntax_highlight/#codesyntaxhighlight","text":"A code highlighter subclass of QSyntaxHighlighter that can be used to highlight code in a QTextEdit. Code lexer and available styles are from pygments python library List of available languages are available here . List of available styles are available here .","title":"CodeSyntaxHighlight"},{"location":"utilities/code_syntax_highlight/#example","text":"from qtpy.QtGui import QColor , QPalette from qtpy.QtWidgets import QApplication , QTextEdit from superqt.utils import CodeSyntaxHighlight app = QApplication ([]) text_area = QTextEdit () highlight = CodeSyntaxHighlight ( text_area . document (), \"python\" , \"monokai\" ) palette = text_area . palette () palette . setColor ( QPalette . Base , QColor ( highlight . background_color )) text_area . setPalette ( palette ) text_area . setText ( \"\"\"from argparse import ArgumentParser def main(): parser = ArgumentParser() parser.add_argument(\"name\", help=\"Your name\") args = parser.parse_args() print(f\"Hello {args.name}\") if __name__ == \"__main__\": main() \"\"\" ) text_area . show () text_area . resize ( 400 , 200 ) app . exec_ ()","title":"Example"},{"location":"utilities/code_syntax_highlight/#qt-class","text":"QSyntaxHighlighter","title":"Qt Class"},{"location":"utilities/code_syntax_highlight/#methods","text":"","title":"Methods"},{"location":"utilities/code_syntax_highlight/#superqt.utils._code_syntax_highlight.CodeSyntaxHighlight.background_color","text":"","title":"background_color()"},{"location":"utilities/fonticon/","text":"Font icons The superqt.fonticon module provides a set of utilities for working with font icons such as Font Awesome or Material Design Icons . Basic Example from fonticon_fa5 import FA5S from qtpy.QtCore import QSize from qtpy.QtWidgets import QApplication , QPushButton from superqt.fonticon import icon , pulse app = QApplication ([]) btn2 = QPushButton () btn2 . setIcon ( icon ( FA5S . smile , color = \"blue\" )) btn2 . setIconSize ( QSize ( 225 , 225 )) btn2 . show () app . exec () Font Icon plugins Ready-made fonticon packs are available as plugins: Font Awesome 5 pip install fonticon-fontawesome5 Font Awesome 6 pip install fonticon-fontawesome6 Material Design Icons pip install fonticon-materialdesignicons6 See also https://github.com/tlambert03/fonticon-bootstrapicons https://github.com/tlambert03/fonticon-linearicons https://github.com/tlambert03/fonticon-feather superqt.fonticon is a pluggable system, and font icon packs may use the \"superqt.fonticon\" entry point to register themselves with superqt. See fonticon-cookiecutter for a template, or look through the following repos for examples: https://github.com/tlambert03/fonticon-fontawesome6 https://github.com/tlambert03/fonticon-fontawesome5 https://github.com/tlambert03/fonticon-materialdesignicons6 API superqt . fonticon . icon ( glyph_key , scale_factor = DEFAULT_SCALING_FACTOR , color = None , opacity = 1 , animation = None , transform = None , states = {}) Create a QIcon for glyph_key , with a number of optional settings The glyph_key (e.g. 'fa5s.smile') represents a Font-family & style, and a glpyh. In most cases, the key should be provided by a plugin in the environment, like: fonticon-fontawesome5 ('fa5s' & 'fa5r' prefixes) fonticon-materialdesignicons6 ('mdi6' prefix) ...but fonts can also be added manually using addFont . Parameters: Name Type Description Default glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required scale_factor float , optional Scale factor (fraction of widget height), When widget icon is painted on widget, it will use font.setPixelSize(round(wdg.height() * scale_factor)) . by default 0.875. DEFAULT_SCALING_FACTOR color ValidColor , optional Color for the font, by default None. (e.g. The default QColor ) Valid color types include QColor , int , str , Qt.GlobalColor , tuple (of integer: RGB[A]) (anything that can be passed to QColor ). None opacity float , optional Opacity of icon, by default 1 1 animation Animation , optional Animation for the icon. A subclass of superqt.fonticon.Animation, that provides a concrete animate method. (see \"spin\" and \"pulse\" for examples). by default None. None transform QTransform , optional A QTransform to apply when painting the icon, by default None None states dict , optional Provide additional styling for the icon in different states. states must be a mapping of string to dict, where: the key represents a QIcon.State (\"on\", \"off\"), a QIcon.Mode (\"normal\", \"active\", \"selected\", \"disabled\"), or any combination of a state & mode separated by an underscore (e.g. \"off_active\", \"selected_on\", etc...). the value is a dict with all of the same key/value meanings listed above as parameters to this function (e.g. glyph_key , color , scale_factor , animation , etc...) Missing keys in the state dicts will be taken from the default options, provided by the paramters above. {} Returns: Type Description QFontIcon A subclass of QIcon. Can be used wherever QIcons are used, such as widget.setIcon() Examples: simple example (using the string 'fa5s.smile' assumes the fonticon-fontawesome5 plugin is installed) >>> btn = QPushButton () >>> btn . setIcon ( icon ( 'fa5s.smile' )) can also directly import from fonticon_fa5 >>> from fonticon_fa5 import FA5S >>> btn . setIcon ( icon ( FA5S . smile )) with animation >>> btn2 = QPushButton () >>> btn2 . setIcon ( icon ( FA5S . spinner , animation = pulse ( btn2 ))) complicated example >>> btn = QPushButton () >>> btn . setIcon ( ... icon ( ... FA5S . ambulance , ... color = \"blue\" , ... states = { ... \"active\" : { ... \"glyph\" : FA5S . bath , ... \"color\" : \"red\" , ... \"scale_factor\" : 0.5 , ... \"animation\" : pulse ( btn ), ... }, ... \"disabled\" : { ... \"color\" : \"green\" , ... \"scale_factor\" : 0.8 , ... \"animation\" : spin ( btn ) ... }, ... }, ... ) ... ) >>> btn . setIconSize ( QSize ( 256 , 256 )) >>> btn . show () superqt . fonticon . setTextIcon ( widget , glyph_key , size = None ) Set text on a widget to a specific font & glyph. This is an alternative to setting a QIcon with a pixmap. It may be easier to combine with dynamic stylesheets. Parameters: Name Type Description Default widget QWidget A widget supporting a setText method. required glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required size int , optional Size for QFont. passed to setPixelSize , by default None None superqt . fonticon . font ( font_prefix , size = None ) Create QFont for font_prefix Parameters: Name Type Description Default font_prefix str Font_prefix, such as 'fa5s' or 'mdi6', representing a font-family and style. required size int , optional Size for QFont. passed to setPixelSize , by default None None Returns: Type Description QFont QFont instance that can be used to add fonticons to widgets. superqt.fonticon.IconOpts dataclass Options for rendering an icon. Parameters: Name Type Description Default glyph_key str , optional The key of the glyph to use, e.g. 'fa5s.smile' , by default None _Unset scale_factor float , optional The scale factor to use, by default None _Unset color ValidColor , optional The color to use, by default None . Colors may be specified as a string, QColor , Qt.GlobalColor , or a 3 or 4-tuple of integers. _Unset opacity float , optional The opacity to use, by default None _Unset animation Animation , optional The animation to use, by default None _Unset superqt . fonticon . addFont ( filepath , prefix , charmap = None ) Add OTF/TTF file at filepath to the registry under prefix . If you'd like to later use a fontkey in the form of prefix.some-name , then charmap must be provided and provide a mapping for all of the glyph names to their unicode numbers. If a charmap is not provided, glyphs must be directly accessed with their unicode as something like key.\uffff . Note in most cases, users will not need this. Instead, they should install a font plugin, like: fonticon-fontawesome5 fonticon-materialdesignicons6 Parameters: Name Type Description Default filepath str Path to an OTF or TTF file containing the fonts required prefix str A prefix that will represent this font file when used for lookup. For example, 'fa5s' for 'Font-Awesome 5 Solid'. required charmap Dict [ str , str ], optional optional mapping for all of the glyph names to their unicode numbers. See note above. None Returns: Type Description Tuple [ str , str ], optional font-family and font-style for the file just registered, or None if something goes wrong. Animations the animation parameter to icon() accepts a subclass of Animation that will be superqt.fonticon.Animation Bases: ABC Base icon animation class. animate ( painter ) abstractmethod Setup and start the timer for the animation. superqt.fonticon.pulse Bases: spin Animation that spins an icon in slower, discrete steps. superqt.fonticon.spin Bases: Animation Animation that smoothly spins an icon.","title":"Font icons"},{"location":"utilities/fonticon/#font-icons","text":"The superqt.fonticon module provides a set of utilities for working with font icons such as Font Awesome or Material Design Icons .","title":"Font icons"},{"location":"utilities/fonticon/#basic-example","text":"from fonticon_fa5 import FA5S from qtpy.QtCore import QSize from qtpy.QtWidgets import QApplication , QPushButton from superqt.fonticon import icon , pulse app = QApplication ([]) btn2 = QPushButton () btn2 . setIcon ( icon ( FA5S . smile , color = \"blue\" )) btn2 . setIconSize ( QSize ( 225 , 225 )) btn2 . show () app . exec ()","title":"Basic Example"},{"location":"utilities/fonticon/#font-icon-plugins","text":"Ready-made fonticon packs are available as plugins:","title":"Font Icon plugins"},{"location":"utilities/fonticon/#font-awesome-5","text":"pip install fonticon-fontawesome5","title":"Font Awesome 5"},{"location":"utilities/fonticon/#font-awesome-6","text":"pip install fonticon-fontawesome6","title":"Font Awesome 6"},{"location":"utilities/fonticon/#material-design-icons","text":"pip install fonticon-materialdesignicons6","title":"Material Design Icons"},{"location":"utilities/fonticon/#see-also","text":"https://github.com/tlambert03/fonticon-bootstrapicons https://github.com/tlambert03/fonticon-linearicons https://github.com/tlambert03/fonticon-feather superqt.fonticon is a pluggable system, and font icon packs may use the \"superqt.fonticon\" entry point to register themselves with superqt. See fonticon-cookiecutter for a template, or look through the following repos for examples: https://github.com/tlambert03/fonticon-fontawesome6 https://github.com/tlambert03/fonticon-fontawesome5 https://github.com/tlambert03/fonticon-materialdesignicons6","title":"See also"},{"location":"utilities/fonticon/#api","text":"","title":"API"},{"location":"utilities/fonticon/#superqt.fonticon.icon","text":"Create a QIcon for glyph_key , with a number of optional settings The glyph_key (e.g. 'fa5s.smile') represents a Font-family & style, and a glpyh. In most cases, the key should be provided by a plugin in the environment, like: fonticon-fontawesome5 ('fa5s' & 'fa5r' prefixes) fonticon-materialdesignicons6 ('mdi6' prefix) ...but fonts can also be added manually using addFont . Parameters: Name Type Description Default glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required scale_factor float , optional Scale factor (fraction of widget height), When widget icon is painted on widget, it will use font.setPixelSize(round(wdg.height() * scale_factor)) . by default 0.875. DEFAULT_SCALING_FACTOR color ValidColor , optional Color for the font, by default None. (e.g. The default QColor ) Valid color types include QColor , int , str , Qt.GlobalColor , tuple (of integer: RGB[A]) (anything that can be passed to QColor ). None opacity float , optional Opacity of icon, by default 1 1 animation Animation , optional Animation for the icon. A subclass of superqt.fonticon.Animation, that provides a concrete animate method. (see \"spin\" and \"pulse\" for examples). by default None. None transform QTransform , optional A QTransform to apply when painting the icon, by default None None states dict , optional Provide additional styling for the icon in different states. states must be a mapping of string to dict, where: the key represents a QIcon.State (\"on\", \"off\"), a QIcon.Mode (\"normal\", \"active\", \"selected\", \"disabled\"), or any combination of a state & mode separated by an underscore (e.g. \"off_active\", \"selected_on\", etc...). the value is a dict with all of the same key/value meanings listed above as parameters to this function (e.g. glyph_key , color , scale_factor , animation , etc...) Missing keys in the state dicts will be taken from the default options, provided by the paramters above. {} Returns: Type Description QFontIcon A subclass of QIcon. Can be used wherever QIcons are used, such as widget.setIcon() Examples: simple example (using the string 'fa5s.smile' assumes the fonticon-fontawesome5 plugin is installed) >>> btn = QPushButton () >>> btn . setIcon ( icon ( 'fa5s.smile' )) can also directly import from fonticon_fa5 >>> from fonticon_fa5 import FA5S >>> btn . setIcon ( icon ( FA5S . smile )) with animation >>> btn2 = QPushButton () >>> btn2 . setIcon ( icon ( FA5S . spinner , animation = pulse ( btn2 ))) complicated example >>> btn = QPushButton () >>> btn . setIcon ( ... icon ( ... FA5S . ambulance , ... color = \"blue\" , ... states = { ... \"active\" : { ... \"glyph\" : FA5S . bath , ... \"color\" : \"red\" , ... \"scale_factor\" : 0.5 , ... \"animation\" : pulse ( btn ), ... }, ... \"disabled\" : { ... \"color\" : \"green\" , ... \"scale_factor\" : 0.8 , ... \"animation\" : spin ( btn ) ... }, ... }, ... ) ... ) >>> btn . setIconSize ( QSize ( 256 , 256 )) >>> btn . show ()","title":"icon()"},{"location":"utilities/fonticon/#superqt.fonticon.setTextIcon","text":"Set text on a widget to a specific font & glyph. This is an alternative to setting a QIcon with a pixmap. It may be easier to combine with dynamic stylesheets. Parameters: Name Type Description Default widget QWidget A widget supporting a setText method. required glyph_key str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. required size int , optional Size for QFont. passed to setPixelSize , by default None None","title":"setTextIcon()"},{"location":"utilities/fonticon/#superqt.fonticon.font","text":"Create QFont for font_prefix Parameters: Name Type Description Default font_prefix str Font_prefix, such as 'fa5s' or 'mdi6', representing a font-family and style. required size int , optional Size for QFont. passed to setPixelSize , by default None None Returns: Type Description QFont QFont instance that can be used to add fonticons to widgets.","title":"font()"},{"location":"utilities/fonticon/#superqt.fonticon.IconOpts","text":"Options for rendering an icon. Parameters: Name Type Description Default glyph_key str , optional The key of the glyph to use, e.g. 'fa5s.smile' , by default None _Unset scale_factor float , optional The scale factor to use, by default None _Unset color ValidColor , optional The color to use, by default None . Colors may be specified as a string, QColor , Qt.GlobalColor , or a 3 or 4-tuple of integers. _Unset opacity float , optional The opacity to use, by default None _Unset animation Animation , optional The animation to use, by default None _Unset","title":"IconOpts"},{"location":"utilities/fonticon/#superqt.fonticon.addFont","text":"Add OTF/TTF file at filepath to the registry under prefix . If you'd like to later use a fontkey in the form of prefix.some-name , then charmap must be provided and provide a mapping for all of the glyph names to their unicode numbers. If a charmap is not provided, glyphs must be directly accessed with their unicode as something like key.\uffff . Note in most cases, users will not need this. Instead, they should install a font plugin, like: fonticon-fontawesome5 fonticon-materialdesignicons6 Parameters: Name Type Description Default filepath str Path to an OTF or TTF file containing the fonts required prefix str A prefix that will represent this font file when used for lookup. For example, 'fa5s' for 'Font-Awesome 5 Solid'. required charmap Dict [ str , str ], optional optional mapping for all of the glyph names to their unicode numbers. See note above. None Returns: Type Description Tuple [ str , str ], optional font-family and font-style for the file just registered, or None if something goes wrong.","title":"addFont()"},{"location":"utilities/fonticon/#animations","text":"the animation parameter to icon() accepts a subclass of Animation that will be","title":"Animations"},{"location":"utilities/fonticon/#superqt.fonticon.Animation","text":"Bases: ABC Base icon animation class.","title":"Animation"},{"location":"utilities/fonticon/#superqt.fonticon._animations.Animation.animate","text":"Setup and start the timer for the animation.","title":"animate()"},{"location":"utilities/fonticon/#superqt.fonticon.pulse","text":"Bases: spin Animation that spins an icon in slower, discrete steps.","title":"pulse"},{"location":"utilities/fonticon/#superqt.fonticon.spin","text":"Bases: Animation Animation that smoothly spins an icon.","title":"spin"},{"location":"utilities/qmessagehandler/","text":"QMessageHandler superqt.utils.QMessageHandler A context manager to intercept messages from Qt. Parameters: Name Type Description Default logger logging . Logger , optional If provided, intercepted messages will be logged with logger at the corresponding python log level, by default None None Attributes: Name Type Description records list of tuple Captured messages. This is a 3-tuple of: (log_level: int, message: str, context: dict) Examples: >>> handler = QMessageHandler () >>> handler . install () # now all Qt output will be available at mh.records >>> with QMessageHandler () as handler : # temporarily install ... ... >>> logger = logging . getLogger ( __name__ ) >>> with QMessageHandler ( logger ): # re-reoute Qt messages to a python logger. ... ... __enter__ () Enter a context with this handler installed install () Install this handler (override the current QtMessageHandler). uninstall () Uninstall this handler, restoring the previous handler.","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#qmessagehandler","text":"","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#superqt.utils.QMessageHandler","text":"A context manager to intercept messages from Qt. Parameters: Name Type Description Default logger logging . Logger , optional If provided, intercepted messages will be logged with logger at the corresponding python log level, by default None None Attributes: Name Type Description records list of tuple Captured messages. This is a 3-tuple of: (log_level: int, message: str, context: dict) Examples: >>> handler = QMessageHandler () >>> handler . install () # now all Qt output will be available at mh.records >>> with QMessageHandler () as handler : # temporarily install ... ... >>> logger = logging . getLogger ( __name__ ) >>> with QMessageHandler ( logger ): # re-reoute Qt messages to a python logger. ... ...","title":"QMessageHandler"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.__enter__","text":"Enter a context with this handler installed","title":"__enter__()"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.install","text":"Install this handler (override the current QtMessageHandler).","title":"install()"},{"location":"utilities/qmessagehandler/#superqt.utils._message_handler.QMessageHandler.uninstall","text":"Uninstall this handler, restoring the previous handler.","title":"uninstall()"},{"location":"utilities/thread_decorators/","text":"Threading decorators superqt provides two decorators that help to ensure that given function is running in the desired thread: ensure_main_thread ensure_main_thread ensures that the decorated function/method runs in the main thread ensure_object_thread ensure_object_thread ensures that a decorated bound method of a QObject runs in the thread in which the instance lives ( see qt documentation for details ). Usage By default, functions are executed asynchronously (they return immediately with an instance of concurrent.futures.Future ). To block and wait for the result, see Synchronous mode from qtpy.QtCore import QObject from superqt import ensure_main_thread , ensure_object_thread @ensure_main_thread def sample_function (): print ( \"This function will run in main thread\" ) class SampleObject ( QObject ): def __init__ ( self ): super () . __init__ () self . _value = 1 @ensure_main_thread def sample_method1 ( self ): print ( \"This method will run in main thread\" ) @ensure_object_thread def sample_method3 ( self ): import time print ( \"sleeping\" ) time . sleep ( 1 ) print ( \"This method will run in object thread\" ) @property def value ( self ): print ( \"return value\" ) return self . _value @value . setter @ensure_object_thread def value ( self , value ): print ( \"this setter will run in object thread\" ) self . _value = value As can be seen in this example these decorators can also be used for setters. These decorators should not be used as replacement of Qt Signals but rather to interact with Qt objects from non Qt code. Synchronous mode If you'd like for the program to block and wait for the result of your function call, use the await_return=True parameter, and optionally specify a timeout. Important Using synchronous mode may significantly impact performance. from superqt import ensure_main_thread @ensure_main_thread def sample_function1 (): return 1 @ensure_main_thread ( await_return = True ) def sample_function2 (): return 2 assert sample_function1 () is None assert sample_function2 () == 2 # optionally, specify a timeout @ensure_main_thread ( await_return = True , timeout = 10000 ) def sample_function (): return 1","title":"Threading decorators"},{"location":"utilities/thread_decorators/#threading-decorators","text":"superqt provides two decorators that help to ensure that given function is running in the desired thread:","title":"Threading decorators"},{"location":"utilities/thread_decorators/#ensure_main_thread","text":"ensure_main_thread ensures that the decorated function/method runs in the main thread","title":"ensure_main_thread"},{"location":"utilities/thread_decorators/#ensure_object_thread","text":"ensure_object_thread ensures that a decorated bound method of a QObject runs in the thread in which the instance lives ( see qt documentation for details ).","title":"ensure_object_thread"},{"location":"utilities/thread_decorators/#usage","text":"By default, functions are executed asynchronously (they return immediately with an instance of concurrent.futures.Future ). To block and wait for the result, see Synchronous mode from qtpy.QtCore import QObject from superqt import ensure_main_thread , ensure_object_thread @ensure_main_thread def sample_function (): print ( \"This function will run in main thread\" ) class SampleObject ( QObject ): def __init__ ( self ): super () . __init__ () self . _value = 1 @ensure_main_thread def sample_method1 ( self ): print ( \"This method will run in main thread\" ) @ensure_object_thread def sample_method3 ( self ): import time print ( \"sleeping\" ) time . sleep ( 1 ) print ( \"This method will run in object thread\" ) @property def value ( self ): print ( \"return value\" ) return self . _value @value . setter @ensure_object_thread def value ( self , value ): print ( \"this setter will run in object thread\" ) self . _value = value As can be seen in this example these decorators can also be used for setters. These decorators should not be used as replacement of Qt Signals but rather to interact with Qt objects from non Qt code.","title":"Usage"},{"location":"utilities/thread_decorators/#synchronous-mode","text":"If you'd like for the program to block and wait for the result of your function call, use the await_return=True parameter, and optionally specify a timeout. Important Using synchronous mode may significantly impact performance. from superqt import ensure_main_thread @ensure_main_thread def sample_function1 (): return 1 @ensure_main_thread ( await_return = True ) def sample_function2 (): return 2 assert sample_function1 () is None assert sample_function2 () == 2 # optionally, specify a timeout @ensure_main_thread ( await_return = True , timeout = 10000 ) def sample_function (): return 1","title":"Synchronous mode"},{"location":"utilities/threading/","text":"Thread workers The objects in this module provide utilities for running tasks in a separate thread. In general (with the exception of new_worker_qthread ), everything here wraps Qt's QRunnable API . The highest level object is the @thread_worker decorator. It was originally written for napari , and was later extracted into superqt . You may also be interested in reading the napari documentation on this feature, which provides a more in-depth/introductory usage guide. For additional control, you can create your own FunctionWorker or GeneratorWorker objects. superqt.utils.WorkerBase Bases: QRunnable , Generic [ _R ] Base class for creating a Worker that can run in another thread. Parameters: Name Type Description Default SignalsClass type , optional A QObject subclass that contains signals, by default WorkerBaseSignals WorkerBaseSignals Attributes: Name Type Description signals WorkerBaseSignals signal emitter object. To allow identify which worker thread emitted signal. __getattr__ ( name ) Pass through attr requests to signals to simplify connection API. The goal is to enable worker.yielded.connect instead of worker.signals.yielded.connect . Because multiple inheritance of Qt classes is not well supported in PyQt, we have to use composition here (signals are provided by QObjects, and QRunnable is not a QObject). So this passthrough allows us to connect to signals on the _signals object. abort_requested () property Whether the worker has been requested to stop. await_workers ( msecs = None ) classmethod Ask all workers to quit, and wait up to msec for quit. Attempts to clean up all running workers by calling worker.quit() method. Any workers in the WorkerBase._worker_set set will have this method. By default, this function will block indefinitely, until worker threads finish. If a timeout is provided, a RuntimeError will be raised if the workers do not gracefully exit in the time requests, but the threads will NOT be killed. It is (currently) left to the user to use their OS to force-quit rogue threads. Important If the user does not put any yields in their function, and the function is super long, it will just hang... For instance, there's no graceful way to kill this thread in python: @thread_worker def ZZZzzz (): time . sleep ( 10000000 ) This is why it's always advisable to use a generator that periodically yields for long-running computations in another thread. See this stack-overflow post for a good discussion on the difficulty of killing a rogue python thread: Parameters: Name Type Description Default msecs int , optional Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. If msecs is None (the default), the timeout is ignored (waits for the last thread to exit). None Raises: Type Description RuntimeError If a timeout is provided and workers do not quit successfully within the time allotted. is_running () property Whether the worker has been started quit () Send a request to abort the worker. Note It is entirely up to subclasses to honor this method by checking self.abort_requested periodically in their worker.work method, and exiting if True . run () Start the worker. The end-user should never need to call this function. But it cannot be made private or renamed, since it is called by Qt. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work This is the function that actually gets called when calling QThreadPool.start(worker) . It simply wraps the work() method, and emits a few signals. Subclasses should NOT override this method (except with good reason), and instead should implement work() . start () Start this worker in a thread and add it to the global threadpool. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work work () Main method to execute the worker. The end-user should never need to call this function. But subclasses must implement this method (See GeneratorFunction.work for an example implementation). Minimally, it should check self.abort_requested periodically and exit if True. Examples: class MyWorker ( WorkerBase ): def work ( self ): i = 0 while True : if self . abort_requested : self . aborted . emit () break i += 1 if i > max_iters : break time . sleep ( 0.5 ) superqt.utils.FunctionWorker Bases: WorkerBase [ _R ] QRunnable with signals that wraps a simple long-running function. Note FunctionWorker does not provide a way to stop a very long-running function (e.g. time.sleep(10000) ). So whenever possible, it is better to implement your long running function as a generator that yields periodically, and use the GeneratorWorker instead. Parameters: Name Type Description Default func Callable A function to call in another thread required *args will be passed to the function () **kwargs will be passed to the function {} Raises: Type Description TypeError If func is a generator function and not a regular function. superqt.utils.GeneratorWorker Bases: WorkerBase , Generic [ _Y , _S , _R ] QRunnable with signals that wraps a long-running generator. Provides a convenient way to run a generator function in another thread, while allowing 2-way communication between threads, using plain-python generator syntax in the original function. Parameters: Name Type Description Default func callable The function being run in another thread. May be a generator function. required SignalsClass type , optional A QObject subclass that contains signals, by default GeneratorWorkerSignals GeneratorWorkerSignals *args Will be passed to func on instantiation () **kwargs Will be passed to func on instantiation {} is_paused () property Whether the worker is currently paused. pause () Request to pause the worker. resume () Send a request to resume the worker. send ( value ) Send a value into the function (if a generator was used). toggle_pause () Request to pause the worker if playing or resume if paused. work () Core event loop that calls the original function. Enters a continual loop, yielding and returning from the original function. Checks for various events (quit, pause, resume, etc...). (To clarify: we are creating a rudimentary event loop here because there IS NO Qt event loop running in the other thread to hook into) Convenience functions superqt . utils . thread_worker ( function = None , start_thread = None , connect = None , worker_class = None , ignore_errors = False ) Decorator that runs a function in a separate thread when called. When called, the decorated function returns a WorkerBase . See create_worker for additional keyword arguments that can be used when calling the function. The returned worker will have these signals: started : emitted when the work is started finished : emitted when the work is finished returned : emitted with return value errored : emitted with error object on Exception It will also have a worker.start() method that can be used to start execution of the function in another thread. (useful if you need to connect callbacks to signals prior to execution) If the decorated function is a generator, the returned worker will also provide these signals: yielded : emitted with yielded values paused : emitted when a running job has successfully paused resumed : emitted when a paused job has successfully resumed aborted : emitted when a running job is successfully aborted And these methods: quit : ask the thread to quit toggle_paused : toggle the running state of the thread. send : send a value into the generator. (This requires that your decorator function uses the value = yield syntax) Parameters: Name Type Description Default function callable Function to call in another thread. For communication between threads may be a generator function. None start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None connect Dict [ str , Union [ Callable , Sequence ]] A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None worker_class Type [ WorkerBase ] The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False Returns: Type Description callable function that creates a worker, puts it in a new thread and returns the worker instance. Examples: @thread_worker def long_function ( start , end ): # do work, periodically yielding i = start while i <= end : time . sleep ( 0.1 ) yield i # do teardown return 'anything' # call the function to start running in another thread. worker = long_function () # connect signals here if desired... or they may be added using the # `connect` argument in the `@thread_worker` decorator... in which # case the worker will start immediately when long_function() is called worker . start () superqt . utils . create_worker ( func , * args , _start_thread = None , _connect = None , _worker_class = None , _ignore_errors = False , ** kwargs ) Convenience function to start a function in another thread. By default, uses FunctionWorker for functions and GeneratorWorker for generators, but a custom WorkerBase subclass may be provided. If so, it must be a subclass of WorkerBase , which defines a standard set of signals and a run method. Parameters: Name Type Description Default func Callable The function to call in another thread. required _start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None _connect Dict [ str , Union [ Callable , Sequence ]], optional A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None _worker_class type of The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None _ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False *args will be passed to func () **kwargs will be passed to func {} Returns: Name Type Description worker WorkerBase An instantiated worker. If _start_thread was False , the worker will have a .start() method that can be used to start the thread. Raises: Type Description TypeError If a worker_class is provided that is not a subclass of WorkerBase. TypeError If _connect is provided and is not a dict of {str: callable} Examples: def long_function ( duration ): import time time . sleep ( duration ) worker = create_worker ( long_function , 10 ) superqt . utils . new_worker_qthread ( Worker , * args , _start_thread = False , _connect = None , ** kwargs ) This is a convenience function to start a worker in a QThread . In most cases, the thread_worker decorator is sufficient and preferable. But this allows the user to completely customize the Worker object. However, they must then maintain control over the thread and clean up appropriately. It follows the pattern described here and in the qt thread docs see also: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ A QThread object is not a thread! It should be thought of as a class to manage a thread, not as the actual code or object that runs in that thread. The QThread object is created on the main thread and lives there. Worker objects which derive from QObject are the things that actually do the work. They can be moved to a QThread as is done here. Mostly ignorable detail While the signals/slots syntax of the worker looks very similar to standard \"single-threaded\" signals & slots, note that inter-thread signals and slots (automatically) use an event-based QueuedConnection, while intra-thread signals use a DirectConnection. See Signals and Slots Across Threads Parameters: Name Type Description Default Worker QObject QObject type that implements a work() method. The Worker should also emit a finished signal when the work is done. required _start_thread bool If True, thread will be started immediately, otherwise, thread must be manually started with thread.start(). False _connect dict Optional dictionary of {signal: function} to connect to the new worker. for instance: _connect = {'incremented': myfunc} will result in: worker.incremented.connect(myfunc) None *args will be passed to the Worker class on instantiation. () **kwargs will be passed to the Worker class on instantiation. {} Returns: Name Type Description worker WorkerBase The created worker. thread QThread The thread on which the worker is running. Examples: Create some QObject that has a long-running work method: class Worker ( QObject ): finished = Signal () increment = Signal ( int ) def __init__ ( self , argument ): super () . __init__ () self . argument = argument @Slot () def work ( self ): # some long running task... import time for i in range ( 10 ): time . sleep ( 1 ) self . increment . emit ( i ) self . finished . emit () worker , thread = new_worker_qthread ( Worker , 'argument' , _start_thread = True , _connect = { 'increment' : print }, )","title":"Thread workers"},{"location":"utilities/threading/#thread-workers","text":"The objects in this module provide utilities for running tasks in a separate thread. In general (with the exception of new_worker_qthread ), everything here wraps Qt's QRunnable API . The highest level object is the @thread_worker decorator. It was originally written for napari , and was later extracted into superqt . You may also be interested in reading the napari documentation on this feature, which provides a more in-depth/introductory usage guide. For additional control, you can create your own FunctionWorker or GeneratorWorker objects.","title":"Thread workers"},{"location":"utilities/threading/#superqt.utils.WorkerBase","text":"Bases: QRunnable , Generic [ _R ] Base class for creating a Worker that can run in another thread. Parameters: Name Type Description Default SignalsClass type , optional A QObject subclass that contains signals, by default WorkerBaseSignals WorkerBaseSignals Attributes: Name Type Description signals WorkerBaseSignals signal emitter object. To allow identify which worker thread emitted signal.","title":"WorkerBase"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.__getattr__","text":"Pass through attr requests to signals to simplify connection API. The goal is to enable worker.yielded.connect instead of worker.signals.yielded.connect . Because multiple inheritance of Qt classes is not well supported in PyQt, we have to use composition here (signals are provided by QObjects, and QRunnable is not a QObject). So this passthrough allows us to connect to signals on the _signals object.","title":"__getattr__()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.abort_requested","text":"Whether the worker has been requested to stop.","title":"abort_requested()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.await_workers","text":"Ask all workers to quit, and wait up to msec for quit. Attempts to clean up all running workers by calling worker.quit() method. Any workers in the WorkerBase._worker_set set will have this method. By default, this function will block indefinitely, until worker threads finish. If a timeout is provided, a RuntimeError will be raised if the workers do not gracefully exit in the time requests, but the threads will NOT be killed. It is (currently) left to the user to use their OS to force-quit rogue threads. Important If the user does not put any yields in their function, and the function is super long, it will just hang... For instance, there's no graceful way to kill this thread in python: @thread_worker def ZZZzzz (): time . sleep ( 10000000 ) This is why it's always advisable to use a generator that periodically yields for long-running computations in another thread. See this stack-overflow post for a good discussion on the difficulty of killing a rogue python thread: Parameters: Name Type Description Default msecs int , optional Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. If msecs is None (the default), the timeout is ignored (waits for the last thread to exit). None Raises: Type Description RuntimeError If a timeout is provided and workers do not quit successfully within the time allotted.","title":"await_workers()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.is_running","text":"Whether the worker has been started","title":"is_running()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.quit","text":"Send a request to abort the worker. Note It is entirely up to subclasses to honor this method by checking self.abort_requested periodically in their worker.work method, and exiting if True .","title":"quit()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.run","text":"Start the worker. The end-user should never need to call this function. But it cannot be made private or renamed, since it is called by Qt. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work This is the function that actually gets called when calling QThreadPool.start(worker) . It simply wraps the work() method, and emits a few signals. Subclasses should NOT override this method (except with good reason), and instead should implement work() .","title":"run()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.start","text":"Start this worker in a thread and add it to the global threadpool. The order of method calls when starting a worker is: calls QThreadPool.globalInstance().start(worker) | triggered by the QThreadPool.start() method | | called by worker.run | | | V V V worker.start -> worker.run -> worker.work","title":"start()"},{"location":"utilities/threading/#superqt.utils._qthreading.WorkerBase.work","text":"Main method to execute the worker. The end-user should never need to call this function. But subclasses must implement this method (See GeneratorFunction.work for an example implementation). Minimally, it should check self.abort_requested periodically and exit if True. Examples: class MyWorker ( WorkerBase ): def work ( self ): i = 0 while True : if self . abort_requested : self . aborted . emit () break i += 1 if i > max_iters : break time . sleep ( 0.5 )","title":"work()"},{"location":"utilities/threading/#superqt.utils.FunctionWorker","text":"Bases: WorkerBase [ _R ] QRunnable with signals that wraps a simple long-running function. Note FunctionWorker does not provide a way to stop a very long-running function (e.g. time.sleep(10000) ). So whenever possible, it is better to implement your long running function as a generator that yields periodically, and use the GeneratorWorker instead. Parameters: Name Type Description Default func Callable A function to call in another thread required *args will be passed to the function () **kwargs will be passed to the function {} Raises: Type Description TypeError If func is a generator function and not a regular function.","title":"FunctionWorker"},{"location":"utilities/threading/#superqt.utils.GeneratorWorker","text":"Bases: WorkerBase , Generic [ _Y , _S , _R ] QRunnable with signals that wraps a long-running generator. Provides a convenient way to run a generator function in another thread, while allowing 2-way communication between threads, using plain-python generator syntax in the original function. Parameters: Name Type Description Default func callable The function being run in another thread. May be a generator function. required SignalsClass type , optional A QObject subclass that contains signals, by default GeneratorWorkerSignals GeneratorWorkerSignals *args Will be passed to func on instantiation () **kwargs Will be passed to func on instantiation {}","title":"GeneratorWorker"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.is_paused","text":"Whether the worker is currently paused.","title":"is_paused()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.pause","text":"Request to pause the worker.","title":"pause()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.resume","text":"Send a request to resume the worker.","title":"resume()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.send","text":"Send a value into the function (if a generator was used).","title":"send()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.toggle_pause","text":"Request to pause the worker if playing or resume if paused.","title":"toggle_pause()"},{"location":"utilities/threading/#superqt.utils._qthreading.GeneratorWorker.work","text":"Core event loop that calls the original function. Enters a continual loop, yielding and returning from the original function. Checks for various events (quit, pause, resume, etc...). (To clarify: we are creating a rudimentary event loop here because there IS NO Qt event loop running in the other thread to hook into)","title":"work()"},{"location":"utilities/threading/#convenience-functions","text":"","title":"Convenience functions"},{"location":"utilities/threading/#superqt.utils.thread_worker","text":"Decorator that runs a function in a separate thread when called. When called, the decorated function returns a WorkerBase . See create_worker for additional keyword arguments that can be used when calling the function. The returned worker will have these signals: started : emitted when the work is started finished : emitted when the work is finished returned : emitted with return value errored : emitted with error object on Exception It will also have a worker.start() method that can be used to start execution of the function in another thread. (useful if you need to connect callbacks to signals prior to execution) If the decorated function is a generator, the returned worker will also provide these signals: yielded : emitted with yielded values paused : emitted when a running job has successfully paused resumed : emitted when a paused job has successfully resumed aborted : emitted when a running job is successfully aborted And these methods: quit : ask the thread to quit toggle_paused : toggle the running state of the thread. send : send a value into the generator. (This requires that your decorator function uses the value = yield syntax) Parameters: Name Type Description Default function callable Function to call in another thread. For communication between threads may be a generator function. None start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None connect Dict [ str , Union [ Callable , Sequence ]] A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None worker_class Type [ WorkerBase ] The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False Returns: Type Description callable function that creates a worker, puts it in a new thread and returns the worker instance. Examples: @thread_worker def long_function ( start , end ): # do work, periodically yielding i = start while i <= end : time . sleep ( 0.1 ) yield i # do teardown return 'anything' # call the function to start running in another thread. worker = long_function () # connect signals here if desired... or they may be added using the # `connect` argument in the `@thread_worker` decorator... in which # case the worker will start immediately when long_function() is called worker . start ()","title":"thread_worker()"},{"location":"utilities/threading/#superqt.utils.create_worker","text":"Convenience function to start a function in another thread. By default, uses FunctionWorker for functions and GeneratorWorker for generators, but a custom WorkerBase subclass may be provided. If so, it must be a subclass of WorkerBase , which defines a standard set of signals and a run method. Parameters: Name Type Description Default func Callable The function to call in another thread. required _start_thread bool Whether to immediaetly start the thread. If False, the returned worker must be manually started with worker.start() . by default it will be False if the _connect argument is None , otherwise True . None _connect Dict [ str , Union [ Callable , Sequence ]], optional A mapping of \"signal_name\" -> callable or list of callable : callback functions to connect to the various signals offered by the worker class. by default None None _worker_class type of The WorkerBase to instantiate, by default FunctionWorker will be used if func is a regular function, and GeneratorWorker will be used if it is a generator. None _ignore_errors bool If False (the default), errors raised in the other thread will be reraised in the main thread (makes debugging significantly easier). False *args will be passed to func () **kwargs will be passed to func {} Returns: Name Type Description worker WorkerBase An instantiated worker. If _start_thread was False , the worker will have a .start() method that can be used to start the thread. Raises: Type Description TypeError If a worker_class is provided that is not a subclass of WorkerBase. TypeError If _connect is provided and is not a dict of {str: callable} Examples: def long_function ( duration ): import time time . sleep ( duration ) worker = create_worker ( long_function , 10 )","title":"create_worker()"},{"location":"utilities/threading/#superqt.utils.new_worker_qthread","text":"This is a convenience function to start a worker in a QThread . In most cases, the thread_worker decorator is sufficient and preferable. But this allows the user to completely customize the Worker object. However, they must then maintain control over the thread and clean up appropriately. It follows the pattern described here and in the qt thread docs see also: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ A QThread object is not a thread! It should be thought of as a class to manage a thread, not as the actual code or object that runs in that thread. The QThread object is created on the main thread and lives there. Worker objects which derive from QObject are the things that actually do the work. They can be moved to a QThread as is done here. Mostly ignorable detail While the signals/slots syntax of the worker looks very similar to standard \"single-threaded\" signals & slots, note that inter-thread signals and slots (automatically) use an event-based QueuedConnection, while intra-thread signals use a DirectConnection. See Signals and Slots Across Threads Parameters: Name Type Description Default Worker QObject QObject type that implements a work() method. The Worker should also emit a finished signal when the work is done. required _start_thread bool If True, thread will be started immediately, otherwise, thread must be manually started with thread.start(). False _connect dict Optional dictionary of {signal: function} to connect to the new worker. for instance: _connect = {'incremented': myfunc} will result in: worker.incremented.connect(myfunc) None *args will be passed to the Worker class on instantiation. () **kwargs will be passed to the Worker class on instantiation. {} Returns: Name Type Description worker WorkerBase The created worker. thread QThread The thread on which the worker is running. Examples: Create some QObject that has a long-running work method: class Worker ( QObject ): finished = Signal () increment = Signal ( int ) def __init__ ( self , argument ): super () . __init__ () self . argument = argument @Slot () def work ( self ): # some long running task... import time for i in range ( 10 ): time . sleep ( 1 ) self . increment . emit ( i ) self . finished . emit () worker , thread = new_worker_qthread ( Worker , 'argument' , _start_thread = True , _connect = { 'increment' : print }, )","title":"new_worker_qthread()"},{"location":"utilities/throttling/","text":"Throttling & Debouncing These utilities allow you to throttle or debounce a function. This is useful when you have a function that is called multiple times in a short period of time, and you want to make sure it is only \"actually\" called once (or at least no more than a certain frequency). For background on throttling and debouncing, see: https://blog.openreplay.com/forever-functional-debouncing-and-throttling-for-performance https://css-tricks.com/debouncing-throttling-explained-examples/ superqt . utils . qdebounced ( func = None , timeout = 100 , leading = False , timer_type = Qt . TimerType . PreciseTimer ) Creates a debounced function that delays invoking func . func will not be invoked until timeout ms have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the debounced function. Subsequent calls to the debounced function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default False False timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer superqt . utils . qthrottled ( func = None , timeout = 100 , leading = True , timer_type = Qt . TimerType . PreciseTimer ) Creates a throttled function that invokes func at most once per timeout. The throttled function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options to indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the throttled function. Subsequent calls to the throttled function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default True True timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer superqt.utils.QSignalDebouncer Bases: GenericSignalThrottler A Signal Debouncer. This object's triggered signal will not be emitted until self.timeout() milliseconds have elapsed since the last time triggered was emitted. superqt.utils.QSignalThrottler Bases: GenericSignalThrottler A Signal Throttler. This object's triggered signal will emit at most once per timeout (set with setTimeout()). superqt.utils._throttler.GenericSignalThrottler Bases: QObject cancel () Cancel any pending emissions. emissionPolicy () Return the emission policy (trailing or leading). flush () Force emission of any pending emissions. kind () Return the kind of throttler (throttler or debouncer). setTimeout ( timeout ) Set timeout in milliseconds setTimerType ( timerType ) Set current Qt.TimerType. throttle () Emit triggered if not running, then start timer. timeout () Return current timeout in milliseconds. timerType () Return current Qt.TimerType .","title":"Throttling & Debouncing"},{"location":"utilities/throttling/#throttling-debouncing","text":"These utilities allow you to throttle or debounce a function. This is useful when you have a function that is called multiple times in a short period of time, and you want to make sure it is only \"actually\" called once (or at least no more than a certain frequency). For background on throttling and debouncing, see: https://blog.openreplay.com/forever-functional-debouncing-and-throttling-for-performance https://css-tricks.com/debouncing-throttling-explained-examples/","title":"Throttling & Debouncing"},{"location":"utilities/throttling/#superqt.utils.qdebounced","text":"Creates a debounced function that delays invoking func . func will not be invoked until timeout ms have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the debounced function. Subsequent calls to the debounced function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default False False timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer","title":"qdebounced()"},{"location":"utilities/throttling/#superqt.utils.qthrottled","text":"Creates a throttled function that invokes func at most once per timeout. The throttled function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them. Options to indicate whether func should be invoked on the leading and/or trailing edge of the wait timeout. The func is invoked with the last arguments provided to the throttled function. Subsequent calls to the throttled function return the result of the last func invocation. This decorator may be used with or without parameters. Parameters: Name Type Description Default func Callable A function to throttle None timeout int Timeout in milliseconds to wait before allowing another call, by default 100 100 leading bool Whether to invoke the function on the leading edge of the wait timer, by default True True timer_type Qt . TimerType The timer type. by default Qt.TimerType.PreciseTimer One of: - Qt.PreciseTimer : Precise timers try to keep millisecond accuracy - Qt.CoarseTimer : Coarse timers try to keep accuracy within 5% of the desired interval - Qt.VeryCoarseTimer : Very coarse timers only keep full second accuracy Qt.TimerType.PreciseTimer","title":"qthrottled()"},{"location":"utilities/throttling/#superqt.utils.QSignalDebouncer","text":"Bases: GenericSignalThrottler A Signal Debouncer. This object's triggered signal will not be emitted until self.timeout() milliseconds have elapsed since the last time triggered was emitted.","title":"QSignalDebouncer"},{"location":"utilities/throttling/#superqt.utils.QSignalThrottler","text":"Bases: GenericSignalThrottler A Signal Throttler. This object's triggered signal will emit at most once per timeout (set with setTimeout()).","title":"QSignalThrottler"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler","text":"Bases: QObject","title":"GenericSignalThrottler"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.cancel","text":"Cancel any pending emissions.","title":"cancel()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.emissionPolicy","text":"Return the emission policy (trailing or leading).","title":"emissionPolicy()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.flush","text":"Force emission of any pending emissions.","title":"flush()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.kind","text":"Return the kind of throttler (throttler or debouncer).","title":"kind()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.setTimeout","text":"Set timeout in milliseconds","title":"setTimeout()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.setTimerType","text":"Set current Qt.TimerType.","title":"setTimerType()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.throttle","text":"Emit triggered if not running, then start timer.","title":"throttle()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.timeout","text":"Return current timeout in milliseconds.","title":"timeout()"},{"location":"utilities/throttling/#superqt.utils._throttler.GenericSignalThrottler.timerType","text":"Return current Qt.TimerType .","title":"timerType()"},{"location":"widgets/","text":"Widgets The following are QWidget subclasses: Sliders and Numerical Inputs Widget Description QDoubleRangeSlider Multi-handle slider for float values QDoubleSlider Slider for float values QLabeledDoubleRangeSlider QDoubleRangeSlider variant with editable labels for each handle QLabeledDoubleSlider QSlider for float values with editable QSpinBox with the current value QLabeledRangeSlider QRangeSlider variant, with editable labels for each handle QLabeledSlider QSlider with editable QSpinBox that shows the current value QLargeIntSpinBox QSpinbox that accepts arbitrarily large integers QRangeSlider Multi-handle slider QQuantity Pint-backed quantity widget (magnitude combined with unit dropdown) Labels and categorical inputs Widget Description QElidingLabel A QLabel variant that will elide text (add \u2026 ) to fit width. QEnumComboBox QComboBox that populates the combobox from a python Enum QSearchableComboBox QComboBox variant that filters available options based on text input QSearchableListWidget QListWidget variant with search field that filters available options Frames and containers Widget Description QCollapsible A collapsible widget to hide and unhide child widgets.","title":"Widgets"},{"location":"widgets/#widgets","text":"The following are QWidget subclasses:","title":"Widgets"},{"location":"widgets/#sliders-and-numerical-inputs","text":"Widget Description QDoubleRangeSlider Multi-handle slider for float values QDoubleSlider Slider for float values QLabeledDoubleRangeSlider QDoubleRangeSlider variant with editable labels for each handle QLabeledDoubleSlider QSlider for float values with editable QSpinBox with the current value QLabeledRangeSlider QRangeSlider variant, with editable labels for each handle QLabeledSlider QSlider with editable QSpinBox that shows the current value QLargeIntSpinBox QSpinbox that accepts arbitrarily large integers QRangeSlider Multi-handle slider QQuantity Pint-backed quantity widget (magnitude combined with unit dropdown)","title":"Sliders and Numerical Inputs"},{"location":"widgets/#labels-and-categorical-inputs","text":"Widget Description QElidingLabel A QLabel variant that will elide text (add \u2026 ) to fit width. QEnumComboBox QComboBox that populates the combobox from a python Enum QSearchableComboBox QComboBox variant that filters available options based on text input QSearchableListWidget QListWidget variant with search field that filters available options","title":"Labels and categorical inputs"},{"location":"widgets/#frames-and-containers","text":"Widget Description QCollapsible A collapsible widget to hide and unhide child widgets.","title":"Frames and containers"},{"location":"widgets/qcollapsible/","text":"QCollapsible Collapsible QFrame that can be expanded or collapsed by clicking on the header. from qtpy.QtWidgets import QApplication , QLabel , QPushButton from superqt import QCollapsible app = QApplication ([]) collapsible = QCollapsible ( \"Advanced analysis\" ) collapsible . addWidget ( QLabel ( \"This is the inside of the collapsible frame\" )) for i in range ( 10 ): collapsible . addWidget ( QPushButton ( f \"Content button { i + 1 } \" )) collapsible . expand ( animate = False ) collapsible . show () app . exec_ () Qt Class QFrame Methods A collapsible widget to hide and unhide child widgets. Based on https://stackoverflow.com/a/68141638 addWidget ( widget : QWidget ) Add a widget to the central content widget's layout. collapse ( animate : bool = True ) Collapse (hide) the collapsible section content () -> QWidget Return the current content widget. expand ( animate : bool = True ) Expand (show) the collapsible section isExpanded () -> bool Return whether the collapsible section is visible locked () -> bool Return True if collapse/expand is disabled removeWidget ( widget : QWidget ) Remove widget from the central content widget's layout. setContent ( content : QWidget ) Replace central widget (the widget that gets expanded/collapsed). setDuration ( msecs : int ) Set duration of the collapse/expand animation. setEasingCurve ( easing : QEasingCurve ) Set the easing curve for the collapse/expand animation setLocked ( locked : bool = True ) Set whether collapse/expand is disabled setText ( text : str ) Set the text of the toggle button. text () -> str Return the text of the toggle button.","title":"QCollapsible"},{"location":"widgets/qcollapsible/#qcollapsible","text":"Collapsible QFrame that can be expanded or collapsed by clicking on the header. from qtpy.QtWidgets import QApplication , QLabel , QPushButton from superqt import QCollapsible app = QApplication ([]) collapsible = QCollapsible ( \"Advanced analysis\" ) collapsible . addWidget ( QLabel ( \"This is the inside of the collapsible frame\" )) for i in range ( 10 ): collapsible . addWidget ( QPushButton ( f \"Content button { i + 1 } \" )) collapsible . expand ( animate = False ) collapsible . show () app . exec_ ()","title":"QCollapsible"},{"location":"widgets/qcollapsible/#qt-class","text":"QFrame","title":"Qt Class"},{"location":"widgets/qcollapsible/#methods","text":"A collapsible widget to hide and unhide child widgets. Based on https://stackoverflow.com/a/68141638","title":"Methods"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.addWidget","text":"Add a widget to the central content widget's layout.","title":"addWidget()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.collapse","text":"Collapse (hide) the collapsible section","title":"collapse()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.content","text":"Return the current content widget.","title":"content()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.expand","text":"Expand (show) the collapsible section","title":"expand()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.isExpanded","text":"Return whether the collapsible section is visible","title":"isExpanded()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.locked","text":"Return True if collapse/expand is disabled","title":"locked()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.removeWidget","text":"Remove widget from the central content widget's layout.","title":"removeWidget()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setContent","text":"Replace central widget (the widget that gets expanded/collapsed).","title":"setContent()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setDuration","text":"Set duration of the collapse/expand animation.","title":"setDuration()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setEasingCurve","text":"Set the easing curve for the collapse/expand animation","title":"setEasingCurve()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setLocked","text":"Set whether collapse/expand is disabled","title":"setLocked()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.setText","text":"Set the text of the toggle button.","title":"setText()"},{"location":"widgets/qcollapsible/#superqt.collapsible._collapsible.QCollapsible.text","text":"Return the text of the toggle button.","title":"text()"},{"location":"widgets/qdoublerangeslider/","text":"QDoubleRangeSlider Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleRangeSlider app = QApplication ([]) slider = QDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ () Qt Class QSlider Methods","title":"QDoubleRangeSlider"},{"location":"widgets/qdoublerangeslider/#qdoublerangeslider","text":"Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleRangeSlider app = QApplication ([]) slider = QDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ ()","title":"QDoubleRangeSlider"},{"location":"widgets/qdoublerangeslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qdoublerangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qdoubleslider/","text":"QDoubleSlider QSlider variant that accepts floating point values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleSlider app = QApplication ([]) slider = QDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue ( 0.5 ) slider . show () app . exec_ () Qt Class QSlider Methods","title":"QDoubleSlider"},{"location":"widgets/qdoubleslider/#qdoubleslider","text":"QSlider variant that accepts floating point values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QDoubleSlider app = QApplication ([]) slider = QDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue ( 0.5 ) slider . show () app . exec_ ()","title":"QDoubleSlider"},{"location":"widgets/qdoubleslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qdoubleslider/#methods","text":"","title":"Methods"},{"location":"widgets/qelidinglabel/","text":"QElidingLabel QLabel variant that will elide text (i.e. add an ellipsis) if it is too long to fit in the available space. from qtpy.QtWidgets import QApplication from superqt import QElidingLabel app = QApplication ([]) widget = QElidingLabel ( \"a skj skjfskfj sdlf sdfl sdlfk jsdf sdlkf jdsf dslfksdl sdlfk sdf sdl \" \"fjsdlf kjsdlfk laskdfsal as lsdfjdsl kfjdslf asfd dslkjfldskf sdlkfj\" ) widget . setWordWrap ( True ) widget . resize ( 300 , 20 ) widget . show () app . exec_ () Qt Class QLabel Methods A QLabel variant that will elide text (add '\u2026') to fit width. QElidingLabel() QElidingLabel(parent: Optional[QWidget], f: Qt.WindowFlags = ...) QElidingLabel(text: str, parent: Optional[QWidget] = None, f: Qt.WindowFlags = ...) For a multiline eliding label, use setWordWrap(True) . In this case, text will wrap to fit the width, and only the last line will be elided. When wordWrap() is True, sizeHint() will return the size required to fit the full text. elideMode () -> Qt . TextElideMode The current Qt.TextElideMode. setElideMode ( mode : Qt . TextElideMode ) Set the elide mode to a Qt.TextElideMode. wrapText ( text , width , font = None ) -> List [ str ] staticmethod Returns text , split as it would be wrapped for width , given font . Static method.","title":"QElidingLabel"},{"location":"widgets/qelidinglabel/#qelidinglabel","text":"QLabel variant that will elide text (i.e. add an ellipsis) if it is too long to fit in the available space. from qtpy.QtWidgets import QApplication from superqt import QElidingLabel app = QApplication ([]) widget = QElidingLabel ( \"a skj skjfskfj sdlf sdfl sdlfk jsdf sdlkf jdsf dslfksdl sdlfk sdf sdl \" \"fjsdlf kjsdlfk laskdfsal as lsdfjdsl kfjdslf asfd dslkjfldskf sdlkfj\" ) widget . setWordWrap ( True ) widget . resize ( 300 , 20 ) widget . show () app . exec_ ()","title":"QElidingLabel"},{"location":"widgets/qelidinglabel/#qt-class","text":"QLabel","title":"Qt Class"},{"location":"widgets/qelidinglabel/#methods","text":"A QLabel variant that will elide text (add '\u2026') to fit width. QElidingLabel() QElidingLabel(parent: Optional[QWidget], f: Qt.WindowFlags = ...) QElidingLabel(text: str, parent: Optional[QWidget] = None, f: Qt.WindowFlags = ...) For a multiline eliding label, use setWordWrap(True) . In this case, text will wrap to fit the width, and only the last line will be elided. When wordWrap() is True, sizeHint() will return the size required to fit the full text.","title":"Methods"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.elideMode","text":"The current Qt.TextElideMode.","title":"elideMode()"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.setElideMode","text":"Set the elide mode to a Qt.TextElideMode.","title":"setElideMode()"},{"location":"widgets/qelidinglabel/#superqt._eliding_label.QElidingLabel.wrapText","text":"Returns text , split as it would be wrapped for width , given font . Static method.","title":"wrapText()"},{"location":"widgets/qenumcombobox/","text":"QEnumComboBox QEnumComboBox is a variant of QComboBox that populates the items in the combobox based on a python Enum class. In addition to all the methods provided by QComboBox , this subclass adds the methods enumClass / setEnumClass to get/set the current Enum class represented by the combobox, and currentEnum / setCurrentEnum to get/set the current Enum member in the combobox. There is also a new signal currentEnumChanged(enum) analogous to currentIndexChanged and currentTextChanged . Method like insertItem and addItem are blocked and try of its usage will end with RuntimeError from enum import Enum from qtpy.QtWidgets import QApplication from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 app = QApplication ([]) combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) combo . show () app . exec_ () Another option is to use optional enum_class argument of constructor and change # option A: combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) # option B: combo = QEnumComboBox ( enum_class = SampleEnum ) Allow None QEnumComboBox also allows using Optional type annotation: from enum import Enum from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 # as usual: # you must create a QApplication before create a widget. combo = QEnumComboBox () combo . setEnumClass ( SampleEnum , allow_none = True ) In this case there is added option ---- and the currentEnum() method will return None when it is selected. Qt Class QComboBox Signals currentEnumChanged Methods ComboBox presenting options from a python Enum. If the Enum class does not implement __str__ then a human readable name is created from the name of the enum member, replacing underscores with spaces. currentEnum () -> Optional [ EnumType ] current value as Enum member enumClass () -> Optional [ EnumMeta ] return current Enum class isOptional () -> bool return if current enum is with optional annotation setCurrentEnum ( value : Optional [ EnumType ]) -> None Set value with Enum. setEnumClass ( enum : Optional [ EnumMeta ], allow_none = False ) Set enum class from which members value should be selected","title":"QEnumComboBox"},{"location":"widgets/qenumcombobox/#qenumcombobox","text":"QEnumComboBox is a variant of QComboBox that populates the items in the combobox based on a python Enum class. In addition to all the methods provided by QComboBox , this subclass adds the methods enumClass / setEnumClass to get/set the current Enum class represented by the combobox, and currentEnum / setCurrentEnum to get/set the current Enum member in the combobox. There is also a new signal currentEnumChanged(enum) analogous to currentIndexChanged and currentTextChanged . Method like insertItem and addItem are blocked and try of its usage will end with RuntimeError from enum import Enum from qtpy.QtWidgets import QApplication from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 app = QApplication ([]) combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) combo . show () app . exec_ () Another option is to use optional enum_class argument of constructor and change # option A: combo = QEnumComboBox () combo . setEnumClass ( SampleEnum ) # option B: combo = QEnumComboBox ( enum_class = SampleEnum )","title":"QEnumComboBox"},{"location":"widgets/qenumcombobox/#allow-none","text":"QEnumComboBox also allows using Optional type annotation: from enum import Enum from superqt import QEnumComboBox class SampleEnum ( Enum ): first = 1 second = 2 third = 3 # as usual: # you must create a QApplication before create a widget. combo = QEnumComboBox () combo . setEnumClass ( SampleEnum , allow_none = True ) In this case there is added option ---- and the currentEnum() method will return None when it is selected.","title":"Allow None"},{"location":"widgets/qenumcombobox/#qt-class","text":"QComboBox","title":"Qt Class"},{"location":"widgets/qenumcombobox/#signals","text":"","title":"Signals"},{"location":"widgets/qenumcombobox/#currentenumchanged","text":"","title":"currentEnumChanged"},{"location":"widgets/qenumcombobox/#methods","text":"ComboBox presenting options from a python Enum. If the Enum class does not implement __str__ then a human readable name is created from the name of the enum member, replacing underscores with spaces.","title":"Methods"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.currentEnum","text":"current value as Enum member","title":"currentEnum()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.enumClass","text":"return current Enum class","title":"enumClass()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.isOptional","text":"return if current enum is with optional annotation","title":"isOptional()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.setCurrentEnum","text":"Set value with Enum.","title":"setCurrentEnum()"},{"location":"widgets/qenumcombobox/#superqt.combobox._enum_combobox.QEnumComboBox.setEnumClass","text":"Set enum class from which members value should be selected","title":"setEnumClass()"},{"location":"widgets/qlabeleddoublerangeslider/","text":"QLabeledDoubleRangeSlider Labeled Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleRangeSlider app = QApplication ([]) slider = QLabeledDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ () Qt Class QAbstractSlider Enums QLabeledDoubleRangeSlider.LabelPosition NoLabel LabelsAbove LabelsBelow QLabeledDoubleRangeSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods decimals () -> int setDecimals ( prec : int )","title":"QLabeledDoubleRangeSlider"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangeslider","text":"Labeled Float variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleRangeSlider app = QApplication ([]) slider = QLabeledDoubleRangeSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 1 ) slider . setValue (( 0.2 , 0.8 )) slider . show () app . exec_ ()","title":"QLabeledDoubleRangeSlider"},{"location":"widgets/qlabeleddoublerangeslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeleddoublerangeslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangesliderlabelposition","text":"NoLabel LabelsAbove LabelsBelow","title":"QLabeledDoubleRangeSlider.LabelPosition"},{"location":"widgets/qlabeleddoublerangeslider/#qlabeleddoublerangeslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledDoubleRangeSlider.EdgeLabelMode"},{"location":"widgets/qlabeleddoublerangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeleddoublerangeslider/#superqt.sliders._labeled.QLabeledDoubleRangeSlider.decimals","text":"","title":"decimals()"},{"location":"widgets/qlabeleddoublerangeslider/#superqt.sliders._labeled.QLabeledDoubleRangeSlider.setDecimals","text":"","title":"setDecimals()"},{"location":"widgets/qlabeleddoubleslider/","text":"QLabeledDoubleSlider QDoubleSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleSlider app = QApplication ([]) slider = QLabeledDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 2.5 ) slider . setValue ( 1.3 ) slider . show () app . exec_ () Qt Class QAbstractSlider Enums QLabeledDoubleSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods decimals () -> int setDecimals ( prec : int )","title":"QLabeledDoubleSlider"},{"location":"widgets/qlabeleddoubleslider/#qlabeleddoubleslider","text":"QDoubleSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledDoubleSlider app = QApplication ([]) slider = QLabeledDoubleSlider ( Qt . Orientation . Horizontal ) slider . setRange ( 0 , 2.5 ) slider . setValue ( 1.3 ) slider . show () app . exec_ ()","title":"QLabeledDoubleSlider"},{"location":"widgets/qlabeleddoubleslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeleddoubleslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeleddoubleslider/#qlabeleddoubleslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledDoubleSlider.EdgeLabelMode"},{"location":"widgets/qlabeleddoubleslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeleddoubleslider/#superqt.sliders._labeled.QLabeledDoubleSlider.decimals","text":"","title":"decimals()"},{"location":"widgets/qlabeleddoubleslider/#superqt.sliders._labeled.QLabeledDoubleSlider.setDecimals","text":"","title":"setDecimals()"},{"location":"widgets/qlabeledrangeslider/","text":"QLabeledRangeSlider Labeled variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledRangeSlider app = QApplication ([]) slider = QLabeledRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () Qt Class QAbstractSlider Signals editingFinished Enums QLabeledRangeSlider.LabelPosition NoLabel LabelsAbove LabelsBelow QLabeledRangeSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods edgeLabelMode () -> EdgeLabelMode Return current EdgeLabelMode . handleLabelPosition () -> LabelPosition Return where/whether labels are shown adjacent to slider handles. setEdgeLabelMode ( opt : EdgeLabelMode ) Set EdgeLabelMode , controls what is shown at the min/max labels. setHandleLabelPosition ( opt : LabelPosition ) -> LabelPosition Set where/whether labels are shown adjacent to slider handles. If you find that you need to fine tune the position of the handle labels: QLabeledRangeSlider.label_shift_x : adjust horizontal label position QLabeledRangeSlider.label_shift_y : adjust vertical label position","title":"QLabeledRangeSlider"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangeslider","text":"Labeled variant of QRangeSlider . (see that page for more details). from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledRangeSlider app = QApplication ([]) slider = QLabeledRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ ()","title":"QLabeledRangeSlider"},{"location":"widgets/qlabeledrangeslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeledrangeslider/#signals","text":"","title":"Signals"},{"location":"widgets/qlabeledrangeslider/#editingfinished","text":"","title":"editingFinished"},{"location":"widgets/qlabeledrangeslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangesliderlabelposition","text":"NoLabel LabelsAbove LabelsBelow","title":"QLabeledRangeSlider.LabelPosition"},{"location":"widgets/qlabeledrangeslider/#qlabeledrangeslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledRangeSlider.EdgeLabelMode"},{"location":"widgets/qlabeledrangeslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.edgeLabelMode","text":"Return current EdgeLabelMode .","title":"edgeLabelMode()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.handleLabelPosition","text":"Return where/whether labels are shown adjacent to slider handles.","title":"handleLabelPosition()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.setEdgeLabelMode","text":"Set EdgeLabelMode , controls what is shown at the min/max labels.","title":"setEdgeLabelMode()"},{"location":"widgets/qlabeledrangeslider/#superqt.sliders._labeled.QLabeledRangeSlider.setHandleLabelPosition","text":"Set where/whether labels are shown adjacent to slider handles. If you find that you need to fine tune the position of the handle labels: QLabeledRangeSlider.label_shift_x : adjust horizontal label position QLabeledRangeSlider.label_shift_y : adjust vertical label position","title":"setHandleLabelPosition()"},{"location":"widgets/qlabeledslider/","text":"QLabeledSlider QSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledSlider app = QApplication ([]) slider = QLabeledSlider ( Qt . Orientation . Horizontal ) slider . setValue ( 42 ) slider . show () app . exec_ () Qt Class QAbstractSlider Signals editingFinished Enums QLabeledSlider.EdgeLabelMode NoLabel LabelIsRange LabelIsValue Methods edgeLabelMode () -> EdgeLabelMode Return current EdgeLabelMode . setEdgeLabelMode ( opt : EdgeLabelMode ) -> None Set the EdgeLabelMode .","title":"QLabeledSlider"},{"location":"widgets/qlabeledslider/#qlabeledslider","text":"QSlider variant that shows an editable (SpinBox) label next to the slider. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLabeledSlider app = QApplication ([]) slider = QLabeledSlider ( Qt . Orientation . Horizontal ) slider . setValue ( 42 ) slider . show () app . exec_ ()","title":"QLabeledSlider"},{"location":"widgets/qlabeledslider/#qt-class","text":"QAbstractSlider","title":"Qt Class"},{"location":"widgets/qlabeledslider/#signals","text":"","title":"Signals"},{"location":"widgets/qlabeledslider/#editingfinished","text":"","title":"editingFinished"},{"location":"widgets/qlabeledslider/#enums","text":"","title":"Enums"},{"location":"widgets/qlabeledslider/#qlabeledslideredgelabelmode","text":"NoLabel LabelIsRange LabelIsValue","title":"QLabeledSlider.EdgeLabelMode"},{"location":"widgets/qlabeledslider/#methods","text":"","title":"Methods"},{"location":"widgets/qlabeledslider/#superqt.sliders._labeled.QLabeledSlider.edgeLabelMode","text":"Return current EdgeLabelMode .","title":"edgeLabelMode()"},{"location":"widgets/qlabeledslider/#superqt.sliders._labeled.QLabeledSlider.setEdgeLabelMode","text":"Set the EdgeLabelMode .","title":"setEdgeLabelMode()"},{"location":"widgets/qlargeintspinbox/","text":"QLargeIntSpinBox QSpinBox variant that allows to enter large integers, without overflow. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLargeIntSpinBox app = QApplication ([]) slider = QLargeIntSpinBox () slider . setRange ( 0 , 4.53e8 ) slider . setValue ( 4.53e8 ) slider . show () app . exec_ () Qt Class QAbstractSpinBox Signals textChanged valueChanged Methods An integer spinboxes backed by unbound python integer Qt's built-in QSpinBox is backed by a signed 32-bit integer. This could become limiting, particularly in large dense segmentations. This class behaves like a QSpinBox backed by an unbound python int. Does not yet support \"prefix\", \"suffix\" or \"specialValue\" like QSpinBox. maximum () minimum () setMaximum ( max ) setMinimum ( min ) setRange ( minimum , maximum ) setSingleStep ( step ) setValue ( value ) singleStep () value ()","title":"QLargeIntSpinBox"},{"location":"widgets/qlargeintspinbox/#qlargeintspinbox","text":"QSpinBox variant that allows to enter large integers, without overflow. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QLargeIntSpinBox app = QApplication ([]) slider = QLargeIntSpinBox () slider . setRange ( 0 , 4.53e8 ) slider . setValue ( 4.53e8 ) slider . show () app . exec_ ()","title":"QLargeIntSpinBox"},{"location":"widgets/qlargeintspinbox/#qt-class","text":"QAbstractSpinBox","title":"Qt Class"},{"location":"widgets/qlargeintspinbox/#signals","text":"","title":"Signals"},{"location":"widgets/qlargeintspinbox/#textchanged","text":"","title":"textChanged"},{"location":"widgets/qlargeintspinbox/#valuechanged","text":"","title":"valueChanged"},{"location":"widgets/qlargeintspinbox/#methods","text":"An integer spinboxes backed by unbound python integer Qt's built-in QSpinBox is backed by a signed 32-bit integer. This could become limiting, particularly in large dense segmentations. This class behaves like a QSpinBox backed by an unbound python int. Does not yet support \"prefix\", \"suffix\" or \"specialValue\" like QSpinBox.","title":"Methods"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.maximum","text":"","title":"maximum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.minimum","text":"","title":"minimum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setMaximum","text":"","title":"setMaximum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setMinimum","text":"","title":"setMinimum()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setRange","text":"","title":"setRange()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setSingleStep","text":"","title":"setSingleStep()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.setValue","text":"","title":"setValue()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.singleStep","text":"","title":"singleStep()"},{"location":"widgets/qlargeintspinbox/#superqt.spinbox._intspin.QLargeIntSpinBox.value","text":"","title":"value()"},{"location":"widgets/qquantity/","text":"QQuantity A widget that allows the user to edit a quantity (a magnitude associated with a unit). Note This widget requires pint : pip install pint or pip install superqt[quantity] from qtpy.QtWidgets import QApplication from superqt import QQuantity app = QApplication ([]) w = QQuantity ( \"1m\" ) w . show () app . exec () Qt Class QWidget Signals unitsChanged valueChanged dimensionalityChanged Methods A combination QDoubleSpinBox and QComboBox for entering quantities. For this widget, value() returns a pint.Quantity object, while setValue() accepts either a number, pint.Quantity , a string that can be parsed by pint . Parameters: Name Type Description Default value Union [ str , pint . Quantity , Number ] The initial value to display. If a string, it will be parsed by pint . required units Union [ pint . util . UnitsContainer , str , pint . Quantity ], optional The units to use if value is a number. If a string, it will be parsed by pint . If a pint.Quantity , the units will be extracted from it. None ureg pint . UnitRegistry , optional The unit registry to use. If not provided, the registry will be extracted from value if it is a pint.Quantity , otherwise the default registry will be used. None parent QWidget , optional The parent widget, by default None None dimensionality () -> UnitsContainer Return the current dimensionality (cast to str for nice repr). isDimensionless () -> bool Return True if the current value is dimensionless. magnitude () -> Union [ float , int ] Return the magnitude of the current value. magnitudeSpinBox () -> QDoubleSpinBox Return the QSpinBox widget used to edit the magnitude. setDecimals ( decimals : int ) -> None Set the number of decimals to display in the spinbox. setMagnitude ( magnitude : Number ) -> None Set the magnitude of the current value. setUnits ( units : Union [ str , Unit , Quantity ]) -> None Set the units of the current value. If units is None , will convert to a dimensionless quantity. Otherwise, units must be compatible with the current dimensionality. setValue ( value : Union [ str , Quantity , Number ], units : Union [ UnitsContainer , str , Quantity ] = None ) -> None Set the current value (will cast to a pint Quantity). text () -> str unitRegistry () -> UnitRegistry Return the pint UnitRegistry used by this widget. units () -> Unit Return the current units. unitsComboBox () -> QComboBox Return the QCombBox widget used to edit the units. value () -> Quantity Return the current value as a pint.Quantity .","title":"QQuantity"},{"location":"widgets/qquantity/#qquantity","text":"A widget that allows the user to edit a quantity (a magnitude associated with a unit). Note This widget requires pint : pip install pint or pip install superqt[quantity] from qtpy.QtWidgets import QApplication from superqt import QQuantity app = QApplication ([]) w = QQuantity ( \"1m\" ) w . show () app . exec ()","title":"QQuantity"},{"location":"widgets/qquantity/#qt-class","text":"QWidget","title":"Qt Class"},{"location":"widgets/qquantity/#signals","text":"","title":"Signals"},{"location":"widgets/qquantity/#unitschanged","text":"","title":"unitsChanged"},{"location":"widgets/qquantity/#valuechanged","text":"","title":"valueChanged"},{"location":"widgets/qquantity/#dimensionalitychanged","text":"","title":"dimensionalityChanged"},{"location":"widgets/qquantity/#methods","text":"A combination QDoubleSpinBox and QComboBox for entering quantities. For this widget, value() returns a pint.Quantity object, while setValue() accepts either a number, pint.Quantity , a string that can be parsed by pint . Parameters: Name Type Description Default value Union [ str , pint . Quantity , Number ] The initial value to display. If a string, it will be parsed by pint . required units Union [ pint . util . UnitsContainer , str , pint . Quantity ], optional The units to use if value is a number. If a string, it will be parsed by pint . If a pint.Quantity , the units will be extracted from it. None ureg pint . UnitRegistry , optional The unit registry to use. If not provided, the registry will be extracted from value if it is a pint.Quantity , otherwise the default registry will be used. None parent QWidget , optional The parent widget, by default None None","title":"Methods"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.dimensionality","text":"Return the current dimensionality (cast to str for nice repr).","title":"dimensionality()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.isDimensionless","text":"Return True if the current value is dimensionless.","title":"isDimensionless()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.magnitude","text":"Return the magnitude of the current value.","title":"magnitude()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.magnitudeSpinBox","text":"Return the QSpinBox widget used to edit the magnitude.","title":"magnitudeSpinBox()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.setDecimals","text":"Set the number of decimals to display in the spinbox.","title":"setDecimals()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.setMagnitude","text":"Set the magnitude of the current value.","title":"setMagnitude()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.setUnits","text":"Set the units of the current value. If units is None , will convert to a dimensionless quantity. Otherwise, units must be compatible with the current dimensionality.","title":"setUnits()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.setValue","text":"Set the current value (will cast to a pint Quantity).","title":"setValue()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.text","text":"","title":"text()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.unitRegistry","text":"Return the pint UnitRegistry used by this widget.","title":"unitRegistry()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.units","text":"Return the current units.","title":"units()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.unitsComboBox","text":"Return the QCombBox widget used to edit the units.","title":"unitsComboBox()"},{"location":"widgets/qquantity/#superqt.spinbox._quantity.QQuantity.value","text":"Return the current value as a pint.Quantity .","title":"value()"},{"location":"widgets/qrangeslider/","text":"QRangeSlider A multi-handle slider widget than can be used to select a range of values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QRangeSlider app = QApplication ([]) slider = QRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () QRangeSlider inherits from QSlider and attempts to match the Qt API as closely as possible It uses platform-specific styles (for handle, groove, & ticks) but also supports QSS style sheets. Supports mouse wheel events Supports more than 2 handles (e.g. slider.setValue([0, 10, 60, 80]) ) As QRangeSlider inherits from QtWidgets.QSlider , you can use all of the same methods available in the QSlider API . The major difference is that value() and sliderPosition() are reimplemented as tuples of int (where the length of the tuple is equal to the number of handles in the slider.) These options are in addition to the Qt QSlider API, and control the behavior of the bar between handles. getter setter type default description barIsVisible setBarIsVisible hideBar / showBar bool True Whether the bar between handles is visible. barMovesAllHandles setBarMovesAllHandles bool True Whether clicking on the bar moves all handles or just the nearest barIsRigid setBarIsRigid bool True Whether bar length is constant or \"elastic\" when dragging the bar beyond min/max. Screenshots code that generates the images below import os from qtpy import QtCore from qtpy import QtWidgets as QtW # patch for Qt 5.15 on macos >= 12 os . environ [ \"USE_MAC_SLIDER_PATCH\" ] = \"1\" from superqt import QRangeSlider # noqa QSS = \"\"\" QSlider { min-height: 20px; } QSlider::groove:horizontal { border: 0px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #888, stop:1 #ddd); height: 20px; border-radius: 10px; } QSlider::handle { background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.35, fy:0.3, stop:0 #eef, stop:1 #002); height: 20px; width: 20px; border-radius: 10px; } QSlider::sub-page:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); border-top-left-radius: 10px; border-bottom-left-radius: 10px; } QRangeSlider { qproperty-barColor: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); } \"\"\" Horizontal = QtCore . Qt . Orientation . Horizontal class DemoWidget ( QtW . QWidget ): def __init__ ( self ) -> None : super () . __init__ () reg_hslider = QtW . QSlider ( Horizontal ) reg_hslider . setValue ( 50 ) range_hslider = QRangeSlider ( Horizontal ) range_hslider . setValue (( 20 , 80 )) multi_range_hslider = QRangeSlider ( Horizontal ) multi_range_hslider . setValue (( 11 , 33 , 66 , 88 )) multi_range_hslider . setTickPosition ( QtW . QSlider . TickPosition . TicksAbove ) styled_reg_hslider = QtW . QSlider ( Horizontal ) styled_reg_hslider . setValue ( 50 ) styled_reg_hslider . setStyleSheet ( QSS ) styled_range_hslider = QRangeSlider ( Horizontal ) styled_range_hslider . setValue (( 20 , 80 )) styled_range_hslider . setStyleSheet ( QSS ) reg_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) reg_vslider . setValue ( 50 ) range_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_vslider . setValue (( 22 , 77 )) tick_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) tick_vslider . setValue ( 55 ) tick_vslider . setTickPosition ( QtW . QSlider . TicksRight ) range_tick_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_tick_vslider . setValue (( 22 , 77 )) range_tick_vslider . setTickPosition ( QtW . QSlider . TicksLeft ) szp = QtW . QSizePolicy . Maximum left = QtW . QWidget () left . setLayout ( QtW . QVBoxLayout ()) left . setContentsMargins ( 2 , 2 , 2 , 2 ) label1 = QtW . QLabel ( \"Regular QSlider Unstyled\" ) label2 = QtW . QLabel ( \"QRangeSliders Unstyled\" ) label3 = QtW . QLabel ( \"Styled Sliders (using same stylesheet)\" ) label1 . setSizePolicy ( szp , szp ) label2 . setSizePolicy ( szp , szp ) label3 . setSizePolicy ( szp , szp ) left . layout () . addWidget ( label1 ) left . layout () . addWidget ( reg_hslider ) left . layout () . addWidget ( label2 ) left . layout () . addWidget ( range_hslider ) left . layout () . addWidget ( multi_range_hslider ) left . layout () . addWidget ( label3 ) left . layout () . addWidget ( styled_reg_hslider ) left . layout () . addWidget ( styled_range_hslider ) right = QtW . QWidget () right . setLayout ( QtW . QHBoxLayout ()) right . setContentsMargins ( 15 , 5 , 5 , 0 ) right . layout () . setSpacing ( 30 ) right . layout () . addWidget ( reg_vslider ) right . layout () . addWidget ( range_vslider ) right . layout () . addWidget ( tick_vslider ) right . layout () . addWidget ( range_tick_vslider ) self . setLayout ( QtW . QHBoxLayout ()) self . layout () . addWidget ( left ) self . layout () . addWidget ( right ) self . setGeometry ( 600 , 300 , 580 , 300 ) self . activateWindow () self . show () if __name__ == \"__main__\" : import sys from pathlib import Path dest = Path ( \"screenshots\" ) dest . mkdir ( exist_ok = True ) app = QtW . QApplication ([]) demo = DemoWidget () if \"-snap\" in sys . argv : import platform QtW . QApplication . processEvents () demo . grab () . save ( str ( dest / f \"demo_ { platform . system () . lower () } .png\" )) else : app . exec_ () macOS Catalina Big Sur Windows Linux Qt Class QSlider Methods MultiHandle Range Slider widget. Same API as QSlider, but value , setValue , sliderPosition , and setSliderPosition are all sequences of integers. The valueChanged and sliderMoved signals also both emit a tuple of integers. barColor = Property ( QtGui . QBrush , _getBarColor , _setBarColor ) class-attribute The color of the bar between the first and last handle. applyMacStylePatch () -> str Apply a QSS patch to fix sliders on macos>=12 with QT < 6. see FAQ for more details. barIsRigid () -> bool Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True . barIsVisible () -> bool Whether to show the bar between the first and last handle. barMovesAllHandles () -> bool Whether clicking on the bar moves all handles (default), or just the nearest. hideBar () -> None Hide the bar between the first and last handle. setBarIsRigid ( val : bool = True ) -> None Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True . setBarMovesAllHandles ( val : bool = True ) -> None Whether clicking on the bar moves all handles (default), or just the nearest. setBarVisible ( val : bool = True ) -> None Whether to show the bar between the first and last handle. showBar () -> None Show the bar between the first and last handle. Type changes Note the following changes in types compared to the QSlider API: value () -> Tuple [ int , ... ] setValue ( val : Sequence [ int ]) -> None # Signal valueChanged ( Tuple [ int , ... ]) sliderPosition () -> Tuple [ int , ... ] setSliderPosition ( val : Sequence [ int ]) -> None sliderMoved ( Tuple [ int , ... ])","title":"QRangeSlider"},{"location":"widgets/qrangeslider/#qrangeslider","text":"A multi-handle slider widget than can be used to select a range of values. from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication from superqt import QRangeSlider app = QApplication ([]) slider = QRangeSlider ( Qt . Orientation . Horizontal ) slider . setValue (( 20 , 80 )) slider . show () app . exec_ () QRangeSlider inherits from QSlider and attempts to match the Qt API as closely as possible It uses platform-specific styles (for handle, groove, & ticks) but also supports QSS style sheets. Supports mouse wheel events Supports more than 2 handles (e.g. slider.setValue([0, 10, 60, 80]) ) As QRangeSlider inherits from QtWidgets.QSlider , you can use all of the same methods available in the QSlider API . The major difference is that value() and sliderPosition() are reimplemented as tuples of int (where the length of the tuple is equal to the number of handles in the slider.) These options are in addition to the Qt QSlider API, and control the behavior of the bar between handles. getter setter type default description barIsVisible setBarIsVisible hideBar / showBar bool True Whether the bar between handles is visible. barMovesAllHandles setBarMovesAllHandles bool True Whether clicking on the bar moves all handles or just the nearest barIsRigid setBarIsRigid bool True Whether bar length is constant or \"elastic\" when dragging the bar beyond min/max.","title":"QRangeSlider"},{"location":"widgets/qrangeslider/#screenshots","text":"code that generates the images below import os from qtpy import QtCore from qtpy import QtWidgets as QtW # patch for Qt 5.15 on macos >= 12 os . environ [ \"USE_MAC_SLIDER_PATCH\" ] = \"1\" from superqt import QRangeSlider # noqa QSS = \"\"\" QSlider { min-height: 20px; } QSlider::groove:horizontal { border: 0px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #888, stop:1 #ddd); height: 20px; border-radius: 10px; } QSlider::handle { background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.35, fy:0.3, stop:0 #eef, stop:1 #002); height: 20px; width: 20px; border-radius: 10px; } QSlider::sub-page:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); border-top-left-radius: 10px; border-bottom-left-radius: 10px; } QRangeSlider { qproperty-barColor: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #227, stop:1 #77a); } \"\"\" Horizontal = QtCore . Qt . Orientation . Horizontal class DemoWidget ( QtW . QWidget ): def __init__ ( self ) -> None : super () . __init__ () reg_hslider = QtW . QSlider ( Horizontal ) reg_hslider . setValue ( 50 ) range_hslider = QRangeSlider ( Horizontal ) range_hslider . setValue (( 20 , 80 )) multi_range_hslider = QRangeSlider ( Horizontal ) multi_range_hslider . setValue (( 11 , 33 , 66 , 88 )) multi_range_hslider . setTickPosition ( QtW . QSlider . TickPosition . TicksAbove ) styled_reg_hslider = QtW . QSlider ( Horizontal ) styled_reg_hslider . setValue ( 50 ) styled_reg_hslider . setStyleSheet ( QSS ) styled_range_hslider = QRangeSlider ( Horizontal ) styled_range_hslider . setValue (( 20 , 80 )) styled_range_hslider . setStyleSheet ( QSS ) reg_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) reg_vslider . setValue ( 50 ) range_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_vslider . setValue (( 22 , 77 )) tick_vslider = QtW . QSlider ( QtCore . Qt . Orientation . Vertical ) tick_vslider . setValue ( 55 ) tick_vslider . setTickPosition ( QtW . QSlider . TicksRight ) range_tick_vslider = QRangeSlider ( QtCore . Qt . Orientation . Vertical ) range_tick_vslider . setValue (( 22 , 77 )) range_tick_vslider . setTickPosition ( QtW . QSlider . TicksLeft ) szp = QtW . QSizePolicy . Maximum left = QtW . QWidget () left . setLayout ( QtW . QVBoxLayout ()) left . setContentsMargins ( 2 , 2 , 2 , 2 ) label1 = QtW . QLabel ( \"Regular QSlider Unstyled\" ) label2 = QtW . QLabel ( \"QRangeSliders Unstyled\" ) label3 = QtW . QLabel ( \"Styled Sliders (using same stylesheet)\" ) label1 . setSizePolicy ( szp , szp ) label2 . setSizePolicy ( szp , szp ) label3 . setSizePolicy ( szp , szp ) left . layout () . addWidget ( label1 ) left . layout () . addWidget ( reg_hslider ) left . layout () . addWidget ( label2 ) left . layout () . addWidget ( range_hslider ) left . layout () . addWidget ( multi_range_hslider ) left . layout () . addWidget ( label3 ) left . layout () . addWidget ( styled_reg_hslider ) left . layout () . addWidget ( styled_range_hslider ) right = QtW . QWidget () right . setLayout ( QtW . QHBoxLayout ()) right . setContentsMargins ( 15 , 5 , 5 , 0 ) right . layout () . setSpacing ( 30 ) right . layout () . addWidget ( reg_vslider ) right . layout () . addWidget ( range_vslider ) right . layout () . addWidget ( tick_vslider ) right . layout () . addWidget ( range_tick_vslider ) self . setLayout ( QtW . QHBoxLayout ()) self . layout () . addWidget ( left ) self . layout () . addWidget ( right ) self . setGeometry ( 600 , 300 , 580 , 300 ) self . activateWindow () self . show () if __name__ == \"__main__\" : import sys from pathlib import Path dest = Path ( \"screenshots\" ) dest . mkdir ( exist_ok = True ) app = QtW . QApplication ([]) demo = DemoWidget () if \"-snap\" in sys . argv : import platform QtW . QApplication . processEvents () demo . grab () . save ( str ( dest / f \"demo_ { platform . system () . lower () } .png\" )) else : app . exec_ ()","title":"Screenshots"},{"location":"widgets/qrangeslider/#macos","text":"","title":"macOS"},{"location":"widgets/qrangeslider/#catalina","text":"","title":"Catalina"},{"location":"widgets/qrangeslider/#big-sur","text":"","title":"Big Sur"},{"location":"widgets/qrangeslider/#windows","text":"","title":"Windows"},{"location":"widgets/qrangeslider/#linux","text":"","title":"Linux"},{"location":"widgets/qrangeslider/#qt-class","text":"QSlider","title":"Qt Class"},{"location":"widgets/qrangeslider/#methods","text":"MultiHandle Range Slider widget. Same API as QSlider, but value , setValue , sliderPosition , and setSliderPosition are all sequences of integers. The valueChanged and sliderMoved signals also both emit a tuple of integers.","title":"Methods"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barColor","text":"The color of the bar between the first and last handle.","title":"barColor"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.applyMacStylePatch","text":"Apply a QSS patch to fix sliders on macos>=12 with QT < 6. see FAQ for more details.","title":"applyMacStylePatch()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barIsRigid","text":"Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True .","title":"barIsRigid()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barIsVisible","text":"Whether to show the bar between the first and last handle.","title":"barIsVisible()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.barMovesAllHandles","text":"Whether clicking on the bar moves all handles (default), or just the nearest.","title":"barMovesAllHandles()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.hideBar","text":"Hide the bar between the first and last handle.","title":"hideBar()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarIsRigid","text":"Whether bar length is constant when dragging the bar. If False , the bar can shorten when dragged beyond min/max. Default is True .","title":"setBarIsRigid()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarMovesAllHandles","text":"Whether clicking on the bar moves all handles (default), or just the nearest.","title":"setBarMovesAllHandles()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.setBarVisible","text":"Whether to show the bar between the first and last handle.","title":"setBarVisible()"},{"location":"widgets/qrangeslider/#superqt.sliders._generic_range_slider._GenericRangeSlider.showBar","text":"Show the bar between the first and last handle.","title":"showBar()"},{"location":"widgets/qrangeslider/#type-changes","text":"Note the following changes in types compared to the QSlider API: value () -> Tuple [ int , ... ] setValue ( val : Sequence [ int ]) -> None # Signal valueChanged ( Tuple [ int , ... ]) sliderPosition () -> Tuple [ int , ... ] setSliderPosition ( val : Sequence [ int ]) -> None sliderMoved ( Tuple [ int , ... ])","title":"Type changes"},{"location":"widgets/qsearchablecombobox/","text":"QSearchableComboBox QSearchableComboBox is a variant of QComboBox that allow to filter list of options by enter part of text. It could be drop in replacement for QComboBox . from qtpy.QtWidgets import QApplication from superqt import QSearchableComboBox app = QApplication ([]) combo = QSearchableComboBox () combo . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) combo . show () app . exec_ () Qt Class QComboBox","title":"QSearchableComboBox"},{"location":"widgets/qsearchablecombobox/#qsearchablecombobox","text":"QSearchableComboBox is a variant of QComboBox that allow to filter list of options by enter part of text. It could be drop in replacement for QComboBox . from qtpy.QtWidgets import QApplication from superqt import QSearchableComboBox app = QApplication ([]) combo = QSearchableComboBox () combo . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) combo . show () app . exec_ ()","title":"QSearchableComboBox"},{"location":"widgets/qsearchablecombobox/#qt-class","text":"QComboBox","title":"Qt Class"},{"location":"widgets/qsearchablelistwidget/","text":"QSearchableListWidget QSearchableListWidget is a variant of QListWidget that add text entry above list widget that allow to filter list of available options. Due to implementation details, this widget it does not inherit directly from QListWidget but it does fully satisfy its api. The only limitation is that it cannot be used as argument of QListWidgetItem constructor. from qtpy.QtWidgets import QApplication from superqt import QSearchableListWidget app = QApplication ([]) slider = QSearchableListWidget () slider . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) slider . show () app . exec_ () Qt Class QWidget Methods addItem ( * args ) addItems ( * args ) insertItem ( * args ) insertItems ( * args ) update_visible ( text )","title":"QSearchableListWidget"},{"location":"widgets/qsearchablelistwidget/#qsearchablelistwidget","text":"QSearchableListWidget is a variant of QListWidget that add text entry above list widget that allow to filter list of available options. Due to implementation details, this widget it does not inherit directly from QListWidget but it does fully satisfy its api. The only limitation is that it cannot be used as argument of QListWidgetItem constructor. from qtpy.QtWidgets import QApplication from superqt import QSearchableListWidget app = QApplication ([]) slider = QSearchableListWidget () slider . addItems ([ \"foo\" , \"bar\" , \"baz\" , \"foobar\" , \"foobaz\" , \"barbaz\" ]) slider . show () app . exec_ ()","title":"QSearchableListWidget"},{"location":"widgets/qsearchablelistwidget/#qt-class","text":"QWidget","title":"Qt Class"},{"location":"widgets/qsearchablelistwidget/#methods","text":"","title":"Methods"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.addItem","text":"","title":"addItem()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.addItems","text":"","title":"addItems()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.insertItem","text":"","title":"insertItem()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.insertItems","text":"","title":"insertItems()"},{"location":"widgets/qsearchablelistwidget/#superqt.selection._searchable_list_widget.QSearchableListWidget.update_visible","text":"","title":"update_visible()"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index e42e9d8..512a384 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,117 +2,122 @@ https://github.com/napari/superqt/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/faq/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/code_syntax_highlight/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/fonticon/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/qmessagehandler/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/thread_decorators/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/threading/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/utilities/throttling/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qcollapsible/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qdoublerangeslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qdoubleslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qelidinglabel/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qenumcombobox/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qlabeleddoublerangeslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qlabeleddoubleslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qlabeledrangeslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qlabeledslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qlargeintspinbox/ - 2022-10-05 + 2022-10-10 + daily + + + https://github.com/napari/superqt/widgets/qquantity/ + 2022-10-10 daily https://github.com/napari/superqt/widgets/qrangeslider/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qsearchablecombobox/ - 2022-10-05 + 2022-10-10 daily https://github.com/napari/superqt/widgets/qsearchablelistwidget/ - 2022-10-05 + 2022-10-10 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 200f9bfccbddb5e4137632f839c538c4a227b5d0..5fb6465ca541fea19271ed5fb9af761087edda05 100644 GIT binary patch literal 395 zcmV;60d)Q!iwFq94n$)D|8r?{Wo=<_E_iKh0M*vPZi6rk0ML8CqT*iC_Owlu-u4CC zxeCMuOCf>SjP~zm+G^`|oHVJ9KtM3&DM}2*{?z&92PDE6cG)IhXG;imbQqdl_Wt&| zddl|Yq8O7W;H3ly+GQlWx~OM&VlXe&|=ei*;xnu7z1M+gAVP`0g-J$ z-rzhW9cXS7Sa)zx$7DGs(!`cRs)iex{eycabPX_RAP#l(UOtUjc~IeXaTIEr)00Q{ z*yZ7uS`iq8Dyz)f3cL<*7(2ON#VVdufG#k5TN@I0077&zPtbc literal 389 zcmV;00eb!)iwFo>em!FX|8r?{Wo=<_E_iKh0M*q|YlAQl0O0ri3h}+h76#j}_HDml zdoIyj<3UU`ch2_TFScdt_Ba^y0-~Ph`4KL$+8ukBeLy4(ew(k0GS9%b!JxO>{Qd29 z^_1`GhiZzBfU}hBX`6S*9`yzK8||RSd*)4y4jF-DAXCG^o=%?iao?fsTsl|={SZ838@vqd*aMNa zkiK9XL>XxAB51QW(1xfvM3Tf#8>tv>V0L%zozYlel0Y2W;9UAOV&g!B*Muoi<5Hd+ zn)}`!eyIh4AyLyRbGiX11MH_hJ#Ru2jv~P4sRbjmpMT)xxrI)*C~>rao@qcYWkpKs j3IZKd^|S&-ZG7Kshs2lg|HIEG0 + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/fonticon/index.html b/utilities/fonticon/index.html index 4b903ba..04c2aa1 100644 --- a/utilities/fonticon/index.html +++ b/utilities/fonticon/index.html @@ -605,6 +605,8 @@ + + @@ -775,6 +777,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/index.html b/utilities/index.html index a4c6ace..c862510 100644 --- a/utilities/index.html +++ b/utilities/index.html @@ -428,6 +428,8 @@ + + @@ -598,6 +600,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/qmessagehandler/index.html b/utilities/qmessagehandler/index.html index edfdff7..b011937 100644 --- a/utilities/qmessagehandler/index.html +++ b/utilities/qmessagehandler/index.html @@ -496,6 +496,8 @@ + + @@ -666,6 +668,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/thread_decorators/index.html b/utilities/thread_decorators/index.html index a36c7e0..66664e4 100644 --- a/utilities/thread_decorators/index.html +++ b/utilities/thread_decorators/index.html @@ -490,6 +490,8 @@ + + @@ -660,6 +662,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/threading/index.html b/utilities/threading/index.html index bba4fb5..9ed1216 100644 --- a/utilities/threading/index.html +++ b/utilities/threading/index.html @@ -627,6 +627,8 @@ + + @@ -797,6 +799,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/utilities/throttling/index.html b/utilities/throttling/index.html index 68cc784..fbde6d8 100644 --- a/utilities/throttling/index.html +++ b/utilities/throttling/index.html @@ -566,6 +566,8 @@ + + @@ -736,6 +738,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/index.html b/widgets/index.html index e16ff21..35b9f65 100644 --- a/widgets/index.html +++ b/widgets/index.html @@ -428,6 +428,8 @@ + + @@ -598,6 +600,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider @@ -751,6 +767,10 @@ QRangeSlider Multi-handle slider + +QQuantity +Pint-backed quantity widget (magnitude combined with unit dropdown) +

    Labels and categorical inputs

    diff --git a/widgets/qcollapsible/index.html b/widgets/qcollapsible/index.html index c8038d6..6e97118 100644 --- a/widgets/qcollapsible/index.html +++ b/widgets/qcollapsible/index.html @@ -428,6 +428,8 @@ + + @@ -743,6 +745,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/qdoublerangeslider/index.html b/widgets/qdoublerangeslider/index.html index 3f4a0c3..4e3583d 100644 --- a/widgets/qdoublerangeslider/index.html +++ b/widgets/qdoublerangeslider/index.html @@ -428,6 +428,8 @@ + + @@ -646,6 +648,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/qdoubleslider/index.html b/widgets/qdoubleslider/index.html index 180abac..c955d1d 100644 --- a/widgets/qdoubleslider/index.html +++ b/widgets/qdoubleslider/index.html @@ -428,6 +428,8 @@ + + @@ -646,6 +648,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/qelidinglabel/index.html b/widgets/qelidinglabel/index.html index d91ff07..eff1b9f 100644 --- a/widgets/qelidinglabel/index.html +++ b/widgets/qelidinglabel/index.html @@ -428,6 +428,8 @@ + + @@ -673,6 +675,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/qenumcombobox/index.html b/widgets/qenumcombobox/index.html index aac26c4..819496d 100644 --- a/widgets/qenumcombobox/index.html +++ b/widgets/qenumcombobox/index.html @@ -428,6 +428,8 @@ + + @@ -714,6 +716,20 @@ +
  • + + QQuantity + +
  • + + + + + + + + +
  • QRangeSlider diff --git a/widgets/qlabeleddoublerangeslider/index.html b/widgets/qlabeleddoublerangeslider/index.html index 33a5b98..f8684eb 100644 --- a/widgets/qlabeleddoublerangeslider/index.html +++ b/widgets/qlabeleddoublerangeslider/index.html @@ -428,6 +428,8 @@ + + @@ -578,15 +580,15 @@