Hacker News new | past | comments | ask | show | jobs | submit login

>You can create a GUI using something like Qt, but the code to make it is messy and unorganized.

It doesn't serve the author well to make this comparison. Saying it's less messy to manage Proton/React source code files and the associated Node/JS/etc infrastructure is an extremely dubious claim. One of the things I like best about Qt is how non-messy Qt development is. Most everything (source files, resources, etc.) lives in a well-organized project that is easily managed using the Qt Creator IDE. The project structure is well-documented and standardized.

It's also quite strange to compare React code to code using the Python binding for Qt. That's not how most Qt apps are written. Most Qt apps these days use QML, which is based on regular old JavaScript. Besides being a more accurate representation of the way Qt development is normally done, it would also be more interesting to compare one JavaScript-based framework to another. (Although I recommend not making the comparison at all, since I don't believe a fair comparison would favor Proton.)




And if we want to compare the syntax then this would be the QML equivalent:

  import QtQuick 2.9  
  import QtQuick.Controls 1.3  
  
  ApplicationWindow {  
    title: "Example"  
    visible: true  
    width: 300  
    height: 300

    Button {  
        text: "Button"  
        anchors.centerIn: parent  
        onClicked: console.log('Hello')  
    }  
  }


Thank you for posting an example. I was going to.

I may be biased, but to me the QML code is much cleaner and clearer than JSX.


Something I would be curious about is what happens when you try to change the view. Like what if you want to make a counter. For me that was always the best thing about react.


I'm not sure what you're asking, but the answer to what I think you're asking is that views change by way of bindings. They can also be changed directly/procedurally, but I'll give an example of a binding.

(Think of an Item as a visual component, which can either be referred to by an id or, as I've done here, referred to by its children as "parent".)

    Item {
        property int count: 1

        Button {
            height: 30; width: 80
            onClicked: parent.count++
        }

        Text {
            height: 20; width: 30
            text: parent.count
        }
    }
The text will update every time you click the button.


Can you have higher order components? In react this is a function that returns a component, often taking another component as a parameter.

What's nice about react is that the JSX syntax is just sugar that converts to function calls.


> Can you have higher order components? In react this is a function that returns a component, often taking another component as a parameter.

The standard way to do this in QML is using the Loader object: http://doc.qt.io/qt-5/qml-qtqml-component.html

You can also go full-eval of course: http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation...


So nice not so see any < > and ( ) all over the place in addition to { }.


Tell me about it. Probably going to be down voted, but this is SO true: https://twitter.com/thomasfuchs/status/810885087214637057


Wow. Thanks for posting that, as an outsider I had no idea QT was so .. straightforward. Now I want to check it out more.


That looks beautiful. Does Qt/QML support the full power of the JS ecosystem? (bleeding edge or at least modern JS, npm)


I've used Qt developing various data-heavy apps for financial research at work and agree that making this comparison is rather inappropriate. For people who are not familiar with JSX this is not any better than the Qt syntax. This would be an alternative to Qt, but before I see a full-fledging app developed with great performance/memory metrics using this, I am not convinced enough to put it in my framework stack.


I used Qt in the early days, and always found the signal/slot model to handle events quite cumbersome. Handling events through closures (like typically done in JavaScript) is, imho, much nicer.


> I used Qt in the early days, and always found the signal/slot model to handle events quite cumbersome. Handling events through closures (like typically done in JavaScript) is, imho, much nicer.

You have been able to bind closures to events in Qt for... dunnno... 6 years maybe ?


Perhaps ironically, Javascript is a first class qt/qml citizen these days. You’ve been able to use QML with javascript—including/mainly via closures—for a while now.


I'm only an occasional Qt user but I believe since c++11 they've gained much better support for anonymous functions.


This seems like a misunderstanding of what React is. JSX is not a template. It is a DSL or superset with direct access to the presentational layer. It gets "transpiled" away in the building phase. React components are not imperative but declarative, they reflect state instead of inflating layout. Layout inflating (QT, Android), MVC/MVVM (XAML), and views being functions of state (React) are paradigm changes.

View = fn(state) solves longstanding issues with all the previous approaches, and of course it decreases their complexity. It is also the first approach that's breaching the platform barrier successfully while maintaining the high-level. You can write React for countless of targets, being able to re-use and apply the eco-system.


There is no reason you couldn't use the example QML above in place of JSX and still receive the same benefits. It would still be `View = fn(state)`; it's just a different syntax for specifying `fn`.


From what i've seen this is layout inflating, you have a template and you fill it imperatively. Which would be one of the oldest paradigms we have. Maybe i am getting this completely wrong, forgive me in that case, but in all examples i've seen so far it's like that.

Could you please paste an example of a real, functional QT component? For instance a component that is re-used in another component,

    const A = ({ text }) => <div>{text}</div>
    const B = () => <A text="hello" />

    <B /> // -> <div>hello</div>
as well as functional composition (higher-order-components):

    const canBeDisabled = Component => props => props.disabled ? null : <Component {...props} />
    const ComposedB = canBeDisabled(B)

    <ComposedB /> // -> <div>hello</div>
    <ComposedB disabled /> // -> null
an example for statefull components would also be nice:

    class C extends Component {
        state = { count: 0 }
        up = () => this.setState(state => ({ count: state.count + 1 })
        render() {
            return <div onClick={this.up}>{this.state.count}</div>
        }
    }

    <C /> // -> <div>0</div>, clicks count up reactively


Here's an equivalent example for your stateful component :

  Text {
    property int count: 0
    text: count

    MouseArea {
     anchors.fill: parent
     onClicked: count++
    }
  }
if you put this in a file `C.qml` or load it as a component (http://doc.qt.io/qt-5/qml-qtqml-component.html), then you can reuse it in other components:

   Item {
     C { }
     C { count: 23 } // starts at 23
   }
For your functionally composed example, all qt objects have a `visible` property so you'd generally do :

   MyItem {
     visible: props.disabled
   }
Note that unlike React, the "default" paradigm is not functional : in QML you describe directly a dataflow graph between the properties of your objects. e.g.

  C { id: myCount }

  Rectangle {
    color: "red"
    // the width will change whenever the count increase
    width: Math.cos(myCount.count) / 2
  }
This is because the objects with which you work in QML are exactly the ones that are going to be rendered - and at a fairly low-level: they mostly translate directly to GL / D3D primitives ; there is no need for a transformative pass like with react.


And that is what i suspected and what i've seen in all examples i have browsed through so far. The enabled prop wasn't the point, it demonstrates functional composition. All of the above uses old, traditional layout inflating, dependency injection, imperative registration for re-using components, ...and common MVC. They are hard for applications that get even slightly complex.

There is a major difference between that and Reacts approach.


Sorry to go full "get off my lawn" here, but: How is this different from, say, simple GDI rendering or Swing? With both View is a function of state and rendering is done via idempotent function calls (WM_PAINT bzw. paint()/paintComponent()). This is the real traditional method. (BTW: The comparison to MVC doesn't really make sense, unless you add flux/redux/etc. to the equation.)


He means the V in MVC and while they pushed that concept for React at the beginning to help people get what it’s for... it’s not really the same at all.


.... where do you see imperative registration, layout inflating and MVC in my example ?


It just doesn't look comparable to the example i've posted. They were really, really simple, so if QT is the same, i would love to see it do the same. As for imperative registration, didn't you just link me to it? If they were functions, you could do:

    const A = () => <div>...</div>
    const B = () => <h1><A /></h1>
Notice that the B component can refer to the A component because it's in the same scope. There's no magic and no binding/loading. A is a function that is called inside B's function body. It also isn't done by inference of an ID (which would be registration).


> const A = () => <div>...</div> ; const B = () => <h1><A /></h1>

Yes, an equivalent in QML would look like this if you want it in a single file:

    Component {
        id: a
        Text { text: "foo" }
    }

    Component {
        id: b
        Rectangle { Loader { sourceComponent: a } }
    }
but the language really wants you to have one component per file, so :

   A.qml: 
   
   Text { text: "foo" }

   B.qml

   Rectangle { A { } }
> if QT is the same,

It's not. QML is at its core not a functional language, it's a declarative & reactive language. In my experience, at least 30-40% of QML code does not need any functions.

> There's no magic and no binding/loading.

I'm not sure we are using the same meaning of binding. The "A" token in your example is obviously bound to the "A" variable declared before.

> It also isn't done by inference of an ID (which would be registration).

ids in QML are just the variable names. eg

   Rectangle { 
     A { id: foo } 
     width: 2 * foo.width
   }


Thanks for the feedback! I'm not a Qt dev, so I wasn't aware of the practices. I'll revise it and remove the Qt code.


Doesn't QT cost $459 per month per developer[1] for use in commercial applications? That price is prohibitive for anyone but established enterprise.

[1] https://www1.qt.io/buy-product/


No. In many cases, you can use Qt under the LGPL and thus for free. This is especially true when you use it via Python bindings such as PyQt.


PyQT isn't LGPL though, it only offers GPLv3 or Commercial licensing.


That's true. So using PyQt you likely need a commercial license for PyQt and not Qt. Alternatively, you can use PySide2 instead of PyQt to avoid this restriction, but it's less mature.


Less mature for the moment, but it's getting more official support and resources, so that will probably change. (They've also changed the name from PySide2 to Qt for Python.)

http://blog.qt.io/blog/2018/04/13/qt-for-python-is-coming-to...

License-wise: "Qt for Python will have the same licensing as Qt for Application Development, i.e. it will be available under GPL, LGPL and commercial."


That's good to know. Thanks for the info.




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

Search: