Package: lk-qtquick-scaffold
LK QtQuick ScaffoldUsing Python and QtQuick QML to build desktop applications from a series of
predefined tools.HighlightsA layout engine to extend QML layouts.Integrate Qt logging with python console.Execute Python snippet in QML, and vice versa.Easy-to-use register handler to register Python functions to QML side.Well type-annotated signal and slot (and more elegant writing style!)Hot loader to verify layout changing on the fly.Stylesheet manager to thoroughly control application appearance (color, size,
motion, typography, and so on).A set of built-in widgets/themes to quickly produce beautiful user interface.How to installlk-qtquick-scaffoldrequires Python 3.8+ interpreter version.Use pip install:# the 1.x version. (1.3.0)pipinstalllk-qtquick-scaffold# the next big version is coming soon. currently i've released a preview version.pipinstalllk-qtquick-scaffold>=2.0.0a0Note: many features in this document are based on 2.0, currently the 2.0 formal
release is still in progress, you may install the alpha version to taste the
newest features.Install Qt backendInstalling lk-qtquick-scaffold doesn't include Python for Qt's library. You
need to manually install one of the follows:# choose one to installpipinstallpyside6
pipinstallpyqt6
pipinstallpyside2
pipinstallpyqt5lk-qtquick-scaffold auto detects the Qt backend you've installed (you can also
explicitly set the specific one), it usesqtpyto provide an uniform layer
overrides PySide6/PyQt6/PySide2/PyQt5.Examples quick throughHello worldview.qmlimportQtQuickimportQtQuick.WindowWindow{visible:truewidth:400height:300Text{anchors.centerIn:parenttext:'Hello world!'}}main.pyfromlk_qtquick_scaffoldimportappapp.run('view.qml')Hot loaderTheapp.runmethod acceptsdebug(bool type) parameter, to enable hot
loader mode:fromlk_qtquick_scaffoldimportappapp.run('view.qml',debug=True)It starts a floating window that includes a button "RELOAD", each time when you
modify "view.qml", click "RELOAD" to refresh your GUI:BTW you can run "view.qml" in command line:# see helppy-mlk_qtquick_scaffold-h# runpy-mlk_qtquick_scaffoldrunview.qml# run in debug modepy-mlk_qtquick_scaffoldrunview.qml--debugIt has the same result like above "main.py" does.Register funtions to QMLfromlk_qtquick_scaffoldimportQObject,app,pyside,slotclassMyObject(QObject):@slot(result=str)defhello(self):return'hello world'# 1. register QObject subclasses by `app.register`app.register(MyObject())#   it will be available as 'MyObject' in QML side.# 1.1. or use aliasapp.register(MyObject(),name='PyObject')#   it will be available as 'PyObject' in QML side.# 2. register regular function by `pyside.register`.deffoo(a:int,b:int,c:int):returna+b+cpyside.register(foo)#   it will be available as 'pyside.call("foo", ...)' in QML side.# 2.1. or use aliaspyside.register(foo,name='add_abc')#   it will be available as 'pyside.call("add_abc", ...)' in QML side.view.qmlimportQtQuickItem{Component.onCompleted:{console.log(MyObject.hello())// -> 'hello world'console.log(PyObject.hello())// -> 'hello world'console.log(pyside.call("foo",[1,2,3]))// -> 6console.log(pyside.call("add_abc",[1,2,3]))// -> 6}}Integrate qt logging in python consoleWhen you useconsole.login QML side, it will be printed in Python console:Signal and SlotThesignalandslotwrap on Qt'sSignalandSlotdecorators, but
extended their functionalities:You can get the correct type hint in IDE:Theslotaccepts more types as alias to "QObject" and "QVariant" -- it is
more convenient and more readable:fromlk_qtquick_scaffoldimportQObject,slotclassMyObject(QObject):@slot(int,dict,result=list)# <- heredeffoo(self,index,data):return[index,len(data)]'''it is more readable than:@Slot(int, QJSValue, result='QVariant')def foo(self, index, data):return [index, len(data)]'''Here is a full alias list (which is documented inlk_qtquick_scaffold/qt_core/signal_slot.py):slot(*args)AliasReal valueNoteboolboolbasic typefloatfloatbasic typeintintbasic typestrstrbasic typeQObjectQObjectobjectobjectQObjectobject'item'QObjectobject (string)'object'QObjectobject (string)'qobject'QObjectobject (string)dictQJSValueqjsvaluelistQJSValueqjsvaluesetQJSValueqjsvaluetupleQJSValueqjsvalue...QJSValueqjsvalue'any'QJSValueqjsvalue (string)slot(result=...)AliasReal valueNoteNoneNonebasic typeboolboolbasic typefloatfloatbasic typeintintbasic typestrstrbasic typedict'QVariant'qvariantlist'QVariant'qvariantset'QVariant'qvarianttuple'QVariant'qvariant...'QVariant'qvariantslotdecorator is non-intrusive -- it means the method been decorated can
be called in Python side as usual.fromlk_qtquick_scaffoldimportQObject,slotclassMyObject(QObject):@slot(int,str,result=list)deffoo(self,index,name):return[index,name]my_obj=MyObject()# you can call it like a regular method! (just 'ignore' its docorator.)my_obj.foo(1,'hello')# -> [1, 'hello']Built-in widgets librarylk-qtquick-scaffoldprovides a set of built-in widgets under its~/widgetsdirectory.Basically, you can use it in QML by importing "LKWidgets" (or "LKWidgets 1.0"
for Qt 5.x):importLKWidgetsLKWindow{color:'#DBDBF7'// moon whiteLKRectangle{anchors.fill:parentanchors.margins:32color:'#ECDEC8'// parchment yellowLKColumn{anchors.centerIn:parentalignment:'hcenter'// horizontally center childrenLKGhostButton{text:'SUNDAY'}LKButton{text:'MONDAY'}LKGhostButton{text:'TUESDAY'}LKButton{text:'WEDNESDAY'}LKGhostButton{text:'THURSDAY'}LKButton{text:'FRIDAY'}LKGhostButton{text:'SATURDAY'}}}}The dark theme:More screenshots: seeexamples/lk_widgets/screenshot_*.All widget names are started with 'LK', the full list is inlk_qtquick_scaffold/widgets/LKWidgets/qmldirfile.Note: the widgets documentation is not ready. Currently you may have a look at
theexamples/lk_widgetsscreenshots, or view its source code for more details.High-level model, human-readable APITODOLayout engineLayout engine is powered bylk_qtquick_scaffold.qmlside.layout_helper, which
is registered aspylayoutin QML side.// some_view.qmlimportQtQuickColumn{height:100Item{id: item1;height:20}Item{id: item2;height:0.4}Item{id: item3;height:0}Item{id: item4;height:0}Component.onCompleted:{// horizontally center childrenpylayout.auto_align(this,'hcenter')// auto size children://  width > 1: as pixels//  width > 0 and < 1: as percent of left spared space//  width = 0: as stretch to fill the left spared spacepylayout.auto_size_children(this,'vertical')//  the result is://      item1: 20px//      item2: (100 - 20) * 0.4 = 32px//      item3: (100 - 20 - 32) * 0.5 = 24px//      item4: (100 - 20 - 32) * 0.5 = 24px//          (item 3 and 4 share the left space equally.)}}Executing Python snippet in QML, and vice versatest.pyfromlk_qtquick_scaffoldimporteval_jsdeffoo(item1:QObject,item2:QObject):eval_js('''$a.widthChanged.connect(() => {$b.width = $a.width * 2})''',{'a':item1,'b':item2})view.qmlimportQtQuickListView{model:pyside.eval(`importosfiles=os.listdir(input('target folder: '))returnfiles`)}Style managerlk-qtquick-scaffoldexposes a list of built-in style controlers to QML side
as follows:StyleDescriptionpycolorAll color specifications defined in a canonical name formpyfontFont related specificationspysizeWidth, height, radius, padding, margin, spacing, etc.pymotionAnimation related specifications (duration, easing type, etc.)Usage examples (seen in all LKWidgets):You can overwrite the style by giving a YAML file to load, for example a
"dark-theme.yaml":# this is dark theme color scheme# == general ==blue_1:'#e4e5f8'blue_3:'#5294eb'blue_5:'#3844e6'blue_7:'#0f143b'dark_1:'#424141'dark_2:'#242529'dark_3:'#15141a'dark_5:'#050408'grey_3:'#e8eaed'grey_5:'#a9acb0'# == widgets spec ==border_active:'#797171'border_default:'#575757'border_glow:'$border_active'button_bg_active:'$blue_5'button_bg_default:'$panel_bg'button_bg_hovered:'$dark_1'button_bg_pressed:'$dark_3'button_bg_selected:'$button_bg_pressed'input_bg_active:'$dark_2'input_bg_default:'$panel_bg'input_border_active:'$border_active'input_border_default:'$border_default'input_indicator_active:'$blue_5'panel_bg:'$dark_3'prog_bg:'$blue_1'prog_fg:'$blue_5'sidebar_bg:'$panel_bg'text_default:'$grey_3'text_disabled:'$grey_5'text_hint:'$grey_5'win_bg_default:'$dark_5'The dollar symbol ($) is a simple pointer to the other key.You don't need to write all colors in the file,lk-qtquick-scaffoldhas a
great deduction algorithm to automatically call back "defaults" when required
colors are missing from your sheet.Finally load it by callingpycolor.update_from_file():fromlk_qtquick_scaffoldimportpycolorpycolor.update_from_file('dark-theme.yaml')Warning: currently color name style is under refactoring, it is very unstable
to learn from its style.Galleryhttps://user-images.githubusercontent.com/27986259/180829198-7110831e-c060-436a-a9be-c41452f49932.mp4https://user-images.githubusercontent.com/27986259/180829267-cd497bcc-de38-4d00-bb19-c4a84b251031.mp4TODO:AddMoreWidgetsDemo