Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Perhaps your experience with QML would be more pleasant if you would write backend in Rust or Julia (my current choice). In Julia I find that it is particularly easy to iterate as it avoids any compilation step although that is not as smooth as using VS Code with hot reload on the side. There is also Felgo for reloading which I guess also preserves the state, but I have not tried it yet.

One quite an advantage for QML is how easy it is to align elements to get started. Personally, I find it quite frustrating to get HTML to do what I want whereas in QML having only used for two months I already see how to model `Kanban` UI with QML.



I still don't get what advantage QML has over something like Svelte. Writing the QML backend with Rust would be nicer, but why wouldn't I just write my front end using Svelte/TypeScript with something like Tauri at that point? With statically typed languages you get autocomplete, more instant feedback, more editor integration for things like renaming functions variables, and the end result won't have type errors at runtime.

Felgo is what I was hoping for, good find! That covers one pain point, but there's still many, many more. QML does have a simple and great list of components to get started with, where as HTML and CSS have accumulated many years of cruft. But, that being said, aligning elements into rows and columns is easy using CSS flexbox[1]. Flexbox has the benefit of being much more versatile than QMLs layout tools as well. I imagine using flexbox you could make the Kanban UI just as easily, and you'll probably run into less limitations.

[1] https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...


The flexbox does not seem to match the power of QML. For instance, I can have a two-pane view as simple as:

Text {

    anchors.top : parent.top

    anchors.bottom : parent.bottom

    anchors.left : parent.horizontalCenter

    anchors.right : parent.right

    anchors.topMargin : 10

    text : "Hello World"
}

which does not reference any dimensions of the objects. It is easy to reference an anchor of a sibling and other parent elements when needed.

Also, making new components is easy; I can inherit properties of a parent element, add my properties and put them in a file for later reuse is something I use extensively. Building each component carelessly using whatever mockery to get the look I need and then isolating it with its own namespace is relieving.


Thanks for the nice response!

> The flexbox does not seem to match the power of QML. For instance, I can have a two-pane view as simple as:

I'm a bit confused by this example. When you make the other pane wouldn't you need to define all of its anchors too? It seems like the more standard QML approach to a two-pane is using RowLayout[1].

  RowLayout {
      anchors.fill: parent
      Rectangle {
          Layout.fillWidth: true
          Text {
            text: "pane 1"
          }
      }
      Rectangle {
          Layout.fillWidth: true
          Text {
              text: "pane 2"
          }
      }
  }
I agree this is pretty nice and intuitive, but flexbox makes this problem easy too.

  <div style="
    width: 100%; 
    height: 100%; 
    display: flex;
  ">
    <p style="flex: 1">pane 1</p>
    <p style="flex: 1">pane 2</p>
  </div>
Yes inline css has problems, but I didn't want to scare you away with Tailwind[2] and I think inlined CSS makes this example clearer.

> It is easy to reference an anchor of a sibling and other parent elements when needed.

It seems like by composing layouts in QML you can avoid a lot of manual anchor setting. Though layouts do have their limits. Is that why you resort to setting anchors manually? Flexbox is much less limited and flexbox layouts compose really well.

Do you have examples of UI layouts you feel QML solves intuitively that flexbox can't solve intuitively?

> Also, making new components is easy; I can inherit properties of a parent element, add my properties and put them in a file for later reuse is something I use extensively

Svelte works the same exact way. Well, except for the part that new components do not inherit from existing components. Svelte and other modern UI frameworks prefer composition over inheritance[3]. Composition allows you to be just as expressive, but without the footguns of inheritance. If you have a specific UI problem you think inheritance solves well, I'd be happy to try and create a matching composition based solution.

> Building each component carelessly using whatever mockery to get the look I need and then isolating it with its own namespace is relieving.

Svelte uses file based components as well. Each file is its own module in TypeScript/JavaScript.

If you have rebuttals or other additional things to add I'd love to hear it!

[1] https://doc.qt.io/qt-6/qml-qtquick-layouts-rowlayout.html

[2] https://tailwindcss.com/

[3] https://en.wikipedia.org/wiki/Composition_over_inheritance


> Do you have examples of UI layouts you feel QML solves intuitively that flexbox can't solve intuitively?

I think your example on the flexbox use for two pane view illustrates that well. Although I have no experience of using it I get that the gist of it is the same of a RowLayout. It’s a good abstraction for listing many items of the same kind which need to respond dynamically with the change of window dimensions. But when I really need to place two panes 10px appart or put elements on top of it in the bottome left corner, bottom right corner and align margins of the content within the pane anchoring elements manually is so much easier. I remember when I started to learn QML my first instinct was to find where can I make a table and align elements within it where instead I just needed to use anchors.

The beauty of QML is that I can treat RowLayout and Row as elements written in QML itself. If I recall accurately it is possible to loop through child elements and assign properties to them such as anchors with respect to sibiling elements. The abstraction thus is more fundamental.

> Svelte and other modern UI frameworks prefer composition over inheritance

Inheritance is the right abstraction for the UI elements. For instance I don’t need to predict all properties in advance for my custom bottom implemntion when used in the code. Assuming that all of them are available is quite powerful and allows to experiment in place. This work exceptionally well in QML but not in OOP languages in general. Nevertheless, can you come up with `footguns of inheritance` to which QML is susceptible to?

> Svelte uses file based components as well. Each file is its own module in TypeScript/JavaScript.

This sounds interesting. I will give it a try on someday when I will need to make an UI in HTML.


> two panes 10px apart

`gap: 10px`

> put elements on top of it in the bottom left corner, bottom right corner and align margins of the content within the pane anchoring elements manually is so much easier

These instructions seem a bit more vague. If you make this visually or with QML I'm sure I can replicate it in an intuitive way with flexbox.

Flexbox has `align-items`, `justify-content`, `align-content` which covers all the needs of aligning to centers or corners. `padding` and `margin` work exactly like you'd expect. Unlike QML's layouts, you can also enable `flex-wrap` so content automatically wraps when it overflows the allocated space.

Maybe you're also wondering, how do I memorize all these flexbox properties? I don't! Chrome dev tools give you a GUI for editing a flexbox[1], isn't that really nice?

With all these tools, hopefully it becomes clear that you never need to manually define anchors. You can compose these layouts to build whatever complex layouts your heart desires. But, if you are still really attached to the anchor workflow, you can do that with CSS as well. For example, `position: absolute; bottom: 100%; right: 100%` would anchor a child element to the bottom right of its parent.

> The beauty of QML is that I can treat RowLayout and Row as elements written in QML itself.

I totally agree here. My Svelte example from above would become:

  <RowLayout>
    <p>pane 1</p>
    <p>pane 2</p>
  </RowLayout>
What if I told you it's totally trivial to make this RowLayout component yourself in Svelte? This could totally be valid Svelte code! If this sounds interesting, this example[2] is a great starting point. And it would be even more trivial to pull in a great component library like Skeleton UI[3] which does stuff like this for you.

> If I recall accurately it is possible to loop through child elements and assign properties to them such as anchors with respect to sibiling elements. The abstraction thus is more fundamental.

Hopefully this RowLayout example makes it clear that Svelte can also loop through child elements and assign properties.

> Inheritance is the right abstraction for the UI elements

How are you so sure about this? React is one of the most popular and successful tools for building UI elements, and it avoids inheritance entirely. Do you think React's approach is totally offbase? Similarly, Rust and Go do not have inheritance at all. Do you disagree with their design?

> For instance I don’t need to predict all properties in advance for my custom bottom implemention when used in the code. Assuming that all of them are available is quite powerful and allows to experiment in place.

You can expose properties with composition based elements too! You don't need inheritance to support this workflow.

> Nevertheless, can you come up with `footguns of inheritance` to which QML is susceptible to?

I think the composition over inheritance wiki page[4] explains things much more elegantly than I ever could. Though I do think I made a mistake. Does inheritance actually exists in QML land? I don't think so.

It feels like you compose things very similarly to Svelte or React. Maybe it's a just a semantics thing, but imagine HelloText.qml:

  Text {
    text: "hello world!"
  }
Does HelloText inherit from from "Text"? I'd say no. HelloText simply instantiates Text and sets its' text property to "hello world". Though I imagine you would say HelloText inherits from Text and overrides the text property?

Compare this to the Qt Widget world where the difference between inheritance and composition are much more clear. Sometimes a Qt Widget doesn't expose the properties or functionality you want. The best scenario is when Qt Widgets do expose the properties you need. Then you can instantiate them and change those properties. Notice that even Qt Widgets sometimes expose properties without inheritance! When defining bigger fancier widgets, why require inheritance? Break them into smaller parts and expose useful properties. Then you and other programmers can compose custom behavior without going through the sludge of inheriting and overriding!

Perhaps we already agree on that part and it was just a semantics issue about whether QML is actually using composition or inheritance?

> This sounds interesting. I will give it a try on someday when I will need to make an UI in HTML.

Yay, I'm interested to hear what you think!

[1] https://developer.chrome.com/docs/devtools/css/flexbox/

[2] https://svelte.dev/examples/slots

[3] https://www.skeleton.dev/

[4] https://en.wikipedia.org/wiki/Composition_over_inheritance


> Maybe you're also wondering, how do I memorize all these flexbox properties? I don't! Chrome dev tools give you a GUI for editing a flexbox[1], isn't that really nice?

This is quite nice indeed. I didn’t know that Chrome dev tools can be used that way.

> Does HelloText inherit from from "Text"? I'd say no. HelloText simply instantiates Text and sets its' text property to "hello world". Though I imagine you would say HelloText inherits from Text and overrides the text property?

Note that is also possible to create a new properties and signals for the Text which can be referenced by the children. Also it is possible to override the default method on how to treat it’s children for instance if you want to implement a CustomRowLayout. The HelloText thus has properties of the Text and the newly defined ones and it is possible to instantiate it at multiple places with different parameters and children. I don’t see why this is not inheritance…

> Perhaps we already agree on that part and it was just a semantics issue about whether QML is actually using composition or inheritance?

In QML composition is when one places children elements within a component and expose relevant properties and signals to the parent. So I disagree on this part. QML in my opinion is OOP done right.


> Note that is also possible to create a new properties and signals for the Text which can be referenced by the children

This behavior exists without inheritance as well! Let's imagine we want to use our existing `HelloText` component. But like you suggested, let's subscribe to the `onclick` signal and add a `bolded` property. When the user clicks the text, it will toggle the bolded property. We will use React because it's famous for not using inheritance.

```jsx function HelloText(props) { return <Text {...props}>Hello World!</Text>; }

export default function App() { const [bolded, setBolded] = React.useState(false); return <HelloText onClick={() => setBolded(bold => !bold) bold={bolded}} /> } ```

And just like you wanted, even children of `<Text>` could reference `bold` and `onClick`. I'll assume you know what that would look like. If not, let me know and I'm happy to make examples for that too. You can provide default prop values that can be overridden. You can accept functions. You can expose signals.

If you are being attentive, you might have noticed the code that enables this behavior: `{...props}` is the explicit way to pass all the props from the parent `HelloText` to its child `Text`. Unlike React, exposing props is implicit and automatic in QML. Though its trivial to make every component expose all their props to their children, the docs argue that you should avoid this. They say that if you find yourself doing this a lot, you are probably designing things poorly [1].

Here's how I understand this: If you are going back and wishing you exposed more properties or methods all the time, then you are probably developing things top down instead of bottom up. When building UI, it's easier and better if you start by building the smallest possible pieces of your UI. Then you can compose them into bigger, more complex pieces. The other way around is dangerous because you would be designing inherently inflexible abstractions. Even the most elaborate and beautiful castle made of yarn will never be as flexible as a castle made of legos.

For example, when and why would you want this `CustomRowLayout` component? Instead, simply start with the smallest easiest parts of your app. Build the buttons inside that row. Maybe the row has a dropdown item, so you can build that. Compose those parts using `RowLayout`, `ColumnLayout`, `GridLayout`, and `Flow`. Maybe make yourself yourself a `Spacer`. While you build your apps' custom rows in this pattern, you will 1. naturally develop a great toolbox of composable components that are flexible and useful and 2. have a much easier time than reimplementing some method on a `CustonRowLayout` component! Previously you asked me for an example where inheritance is a footgun in UI development. A `CustomRowLayout` is an example as building new row layouts bottom up is clearly superior.

But also, React and other modern UI frameworks won't stop you from building `CustomRowLayout` if that's what you really want. Hopefully now it's clear that you can build something like this using React, Svelte, or any other modern UI framework without inheritance. And also, if you find yourself doing this often, maybe that's a sign you are approaching problems from the wrong direction.

> In QML composition is when one places children elements within a component and expose relevant properties and signals to the parent. So I disagree on this part

Honestly, I think this is a fair distinction and definition. Though, then things get a bit hairy on the other side. Clearly React and Svelte support the alternative behavior that you call inheritance in QML. What do you call that now? Did React and Svelte suddenly become OOP frameworks too?

I think the important conclusion is that building complex UI using composition in a bottom up fashion is 1. possible and 2. optimal. QML, Svelte, and React all allow developing top down and bottom up, which is great. Svelte and React simply make top down development explicit.

I will leave things with a message from React's composition vs inheritance page: "At Facebook, we use React in thousands of components, and we haven’t found any use cases where we would recommend creating component inheritance hierarchies.

Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions." [2]

[1] https://react.dev/learn/passing-props-to-a-component#forward... [2] https://legacy.reactjs.org/docs/composition-vs-inheritance.h...


BTW, someone created Flexbox for QML: https://github.com/tripolskypetr/qml-flexbox


It's really awesome someone did this. If you just want the expressiveness of flexbox and don't care about performance, this is perfect!

However, wouldn't the performance for this be very optimal? Check out the `Flex.qml` code[1]. It's all very unoptimized and dynamic QMLScript. None of the function arguments are typed. There is no way the QML compiler is turning any of this into efficient, statically typed C++ code. The beauty of using flexbox in the browser is that all the layout calculations are done natively in the browser without ever touching JavaScript.

[1] https://github.com/tripolskypetr/qml-flexbox/blob/master/qml...


Nope, from what I can tell the entire backend is a Qt C++ binding[1] for the C++ Yoga library[2][3]. You can see the Qt C++ backend is exposed to QML here[4]. So it's C++ all the way down just in a comfortable setting.

[1] https://github.com/tripolskypetr/qml-flexbox/blob/master/obj...

[2] https://github.com/tripolskypetr/qml-flexbox/tree/master/thi...

[3] https://github.com/facebook/yoga

[4] https://github.com/tripolskypetr/qml-flexbox/blob/677a1287df...

P.S. I'll answer your other reply very soon. I'm releasing a new version of my app so it takes its toll on me.


Whoops, I should have been more clear. When I said "It's all very unoptimized and dynamic QMLScript" I meant just the file `Flex.qml`. I'm sure the Qt C++ bindings are fast and great, but check out the `updatePositions` function in `Flex.qml`[1]. This unoptimized and dynamic QMLScript gets ran every time a flex item's width, height, or children change. I imagine if that QMLScript was given types then at least that QMLScript compiler could generate some C++ for it, but right now there are no types so I doubt there is any efficient C++ generated for this script.

On the web it's common to animate the size of flexbox items with CSS animations. These animations are entirely implemented by the browser, and I imagine much of it is even GPU accelerated. No JavaScript is executed for this on the browser. But with this library, you would be running the `Flex.qml`'s `updatePositions` function every frame of the animation. Isn't that wasteful when compared to how flexbox works in the browser? It seems like a browser would be much faster at computing layout for flexbox elements than this, especially when that flexbox's size is being animated with CSS animations.

[1] https://github.com/tripolskypetr/qml-flexbox/blob/master/qml...


Hmm I get your point. I wonder if the the QML type compiler (qmltc) could still compile to C++. It would seem like dark magic if it did tho, because as you said it hasn't given the types. I wonder if it's possible to put this code in the backend in C++, what do you think?


> I wonder if it's possible to put this code in the backend in C++, what do you think?

Yeahh, looks like you'd have to connect to all these signals and be able to access sizing/position from C++. Not sure how possible this is, you probably know better than me.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: