Is it OK to use TableView in Quick Controls 2.0 application?
This will require to have both imports:
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
Will I get any side effects?
Another related question: it seems that TableView belongs to Quick Controls 1.0 set. Is it? Does it mean that if it's possible to use TableView then it's possible to use all the Quick Controls 1.0 controls in Quick Controls 2.0 application?
While it is possible to mix Qt Quick Controls 1 and 2 in the same application, the biggest issue is that Qt Quick Controls 1 are not compatible with Qt's automatic high-DPI scaling, whereas Qt Quick Controls 2 bases its scalability on that. Therefore running such application that mixes the two might not give ideal results on a high-DPI display.
Given that Qt Quick Controls 1 TableView has severe performance issues, one possible alternative is to use plain ListView from Qt Quick core with Row as a delegate. With Qt 5.9 and later, it is possible to explicitly specify the content width and flicking directions so that a vertical ListView can be also flicked horizontally. Here's an overly simple multi-column list example, something you can already try out with the latest Qt 5.9 beta:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id: window
width: 360
height: 360
visible: true
ListView {
id: listView
anchors.fill: parent
contentWidth: headerItem.width
flickableDirection: Flickable.HorizontalAndVerticalFlick
header: Row {
spacing: 1
function itemAt(index) { return repeater.itemAt(index) }
Repeater {
id: repeater
model: ["Quisque", "Posuere", "Curabitur", "Vehicula", "Proin"]
Label {
text: modelData
font.bold: true
font.pixelSize: 20
padding: 10
background: Rectangle { color: "silver" }
}
}
}
model: 100
delegate: Column {
id: delegate
property int row: index
Row {
spacing: 1
Repeater {
model: 5
ItemDelegate {
property int column: index
text: qsTr("%1x%2").arg(delegate.row).arg(column)
width: listView.headerItem.itemAt(column).width
}
}
}
Rectangle {
color: "silver"
width: parent.width
height: 1
}
}
ScrollIndicator.horizontal: ScrollIndicator { }
ScrollIndicator.vertical: ScrollIndicator { }
}
}
Of course, this kind of simplified multi-column list does not provide such features as movable and resizable columns and other bells and whistles that were built into the good old TableView type. On the other hand, the performance is on a whole different level, so if you're targeting something else than classic desktop environments running on computers with endless resources, this route might be worth considering. ;)
import QtQuick.Controls 1.4 as C
import QtQuick.Controls 2.0
C.TableView { //controls 1.4
Button { //controls 2.0
}
}
This will help you avoid any unwanted clashes between the two controls
Related
I am following this tutorial on YouTube and the person sets the TextField to fill the width of the RowLayout. However, it doesn't seem to work for me. I tried using Layout.fillWidth on the CheckBox and it seems to work perfectly fine but it doesn't seem to want to work on the TextField. Here is my code:
main.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
ToDoList.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Here is a screenshot of what mine looks like
What did I do wrong?
I don't know if this has anything to do with it but I made a "Qt Quick Application - Swipe" instead of "Qt Quick Controls 2 Application" as that option wasn't available to me. Thanks in advance for any help.
Edit: I have written step by step instructions to replicate the issue below.
File > New File or Project
From the new window make sure "Application" is selected then click "Qt Quick Application - Swipe" and press "Choose"
Set any name for the project and click "Next"
Set the build system to "qmake" and click "Next"
Set the minimal required Qt version to "Qt 5.9" and the Qt quick controls style to "Material Dark" and click "Next"
Select the "Desktop Qt 5.12.0 MSVC2017 64bit" as the kit and click "Next"
Set the options to have no version control and click "Finish"
Delete "Page1Form.ui.qml" and "Page2Form.ui.qml" from the "Projects" pane
Replace the contents of "main.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
Right click on the root project file and click "Add New"
From the new window make sure "Qt" is selected then click "QML File (Qt Quick 2)" and press "Choose"
Name the file "ToDoList" and click "Next"
Add to project "qml.qrc Prefix: /" then set the options to have no version control and click "Finish"
Replace the contents of "ToDoList.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Run the project
The width is set properly. The problem is with TextField style. You may check it by setting background like
TextField
{
Layout.fillWidth: true
background: Rectangle {
color: "red"
}
}
Or just start typing into those fields with and without Layout.fillWidth: true
Since few months, directly in ListView item we can use ScrollBar.vertical: ScrollBar {} to provide appropriate scrollbar. Unfortunately it doesn't behave natively for me so I decided to surround every ListView in the project with ScrollView and now it works fine except one thing:
import QtQuick 2.9
import QtQuick.Controls 2.2
//import QtQuick.Controls 1.4
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Scroll")
ScrollView {
anchors.fill: parent
ListView {
anchors.fill: parent
model: 20
delegate: Text {
text: "Item " + (index + 1)
height: 50
width: parent.width
}
}
}
}
in the example above I cannot use touch event to scroll the view. I'm working on windows 10 and it doesn't matter if I use ScrollView that comes from QtQuick.Controls 1.4 or QtQuick.Controls 2.2 If I press and hold the mouse button, the view won't follow the mouse moves just like it does in case of ListView alone.
Is there any way to restore this behavior for this particular method of handling scrollbars?
use Flickable { } instead of ScrollView.
* EDIT *
Flickable {} allows the user to scroll left and right using touch events such as flicking, dragging, etc.
It is designed for touch screens. You use it the same way as a ScrollView {}, as a container class.
Flickable {
anchors.fill: parent
ListView {
anchors.fill: parent
model: 20
}
}
I use a ScrollView for my ListView but I need sometimes to disable it.
A simple case would be something like that :
ScrollView {
id: scroll
ListView {
model: DelegateModel {
id: visualModel
model: myModel //Model is set in the cpp
delegate: Rectangle {
...
Button {
onClicked { //Important part
scroll.flickableItem.interactive = false //It doesn't work
}
}
}
}
}
}
How could I proceed ?
As dtech mentioned, the ListView has a built-in Flickable so to scroll, no ScrollView is needed for that. You can also add ScrollBars to a ListView by using:
ScrollBar.vertical: ScrollBar {}
However if you need to use the ScrollView as you want the old-school look-and-feel there is no documented way. Actually, when using QtQuick.Controls 1.x you have to resort to undocumented properties of the Controls quite often.
In this particular case, you could set the properties:
__horizontalScrollBar.enabled: false
__verticalScrollBar.enabled: false
__wheelAreaScrollSpeed: 0
Again: this is not documented and might change if there would be a newer version of the QtQuick.Controls 1.x - this however is unlikely, as right now the focus lies on the development of the modern QtQuick.Controls 2.x which are incompatible with the documented API of the 1.x-versions
I am trying to wrap GridLayout inside an Item and exposing the GridLayout's data property as the default property of the item. But this results in two problems.
I get a crash when exiting the application.
This may in fact be a bug in Qt itself and it might also already been fixed, if not I will report it after fixing 2. I am only able to test on Windows 7 using Qt 5.7.0 MSVC2015 32.bit at the moment.
How to use the attached Layout property? Take look in the following example, which results in the error:
Non-existent attached object
on line
"Layout.alignment: Qt.AlignBottom | Qt.AlignRight".
Example:
//MyCustomLayout.qml
import QtQuick 2.7
import QtQuick.Layouts 1.3
Item {
default property alias data: layout.data
//Some other QML components not to be within GridView here.
GridLayout {
id: layout
anchors.fill: parent
}
//Some other QML components not to be within GridView here.
}
//main.qml
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
visible: true
height: 1024
width: 768
MyCustomLayout {
anchors.fill: parent
Button {
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
}
}
}
For example, this works:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.2
ApplicationWindow
{
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function thingWidth()
{
return width*80/100
}
Column
{
spacing: 10;
anchors.horizontalCenter: parent.horizontalCenter
Thing { color: "red"; width: thingWidth(); }
Thing { color: "yellow"; width: thingWidth(); }
Thing { color: "green"; width: thingWidth(); }
}
}
But change Column to ColumnLayout and it doesn't (resizing window causes layout to go wrong).
any help, thanks.
EDIT 1:
Here's also Thing.qml as requested,
import QtQuick 2.0
Item {
property alias color: rectangle.color
width: 50; height: 50
Rectangle
{
id: rectangle
border.color: "white"
anchors.fill: parent
}
}
It looks like my post is mostly code. Yes, nanny it does! that's because people post code on here.
As from the documentation of Column:
Column is a type that positions its child items along a single column. It can be used as a convenient way to vertically position a series of items without using anchors.
Moreover, it eases transitions during insertion, deletion and so on. It also attaches properties to the items to give them notions about their positions.
On the other side, this is the documentation of GridLayout (please, note that ColumnLayout is a convenience utility, but it is nothing more than a grid with one column, as from its documentation).
It has a completely different set of properties, as well as attached properties, completely oriented to the arrangement of the items.
I guess anyway that the most interesting page from the documentation is that one.
I simply cite it:
Positioner items are container items that manage the positions of items in a declarative user interface. Positioners behave in a similar way to the layout managers used with standard Qt widgets, except that they are also containers in their own right.
Positioners make it easier to work with many items when they need to be arranged in a regular layout.
Qt Quick Layouts can also be used to arrange Qt Quick items in a user interface. They manage both the positions and the sizes of items on a declarative user interface, and are well suited for resizable user interfaces.
Please, note that a Column is a Positioner, while a ColumnLayout is a Layout. When to use them depends mainly on your goal, as usual.