I am trying to create a simple window in QML with a huge text area in the center and a couple of buttons at the bottom,
bellow is the code
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
id: mainWindow
width: 500
height: 300
visible: true
title: qsTr("Hello World")
flags: Qt.WindowCloseButtonHint | Qt.CustomizeWindowHint | Qt.Dialog | Qt.WindowTitleHint
ColumnLayout{
anchors.fill: parent
anchors.margins: 5
RowLayout {
Layout.alignment: Qt.AlignTop
TextArea {
text: "Hello world!"
}
}
RowLayout {
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
Button {
text: "Ok"
}
Button {
text: "Cancel"
}
}
}
}
however when i press enter key multiple times enough to reach almost at the bottom of the text area, the button moves because the text area resizes, how do I prevent this?
How do I set the text area so that it doesnt resize and push the buttons out of the window, but still be responsive that if the window resize it maintains its positions like buttons will still be buttom right and text area adjusts based on anchor.
It sounds like you want your TextArea to fill the space above the buttons, but your present code is not doing this. If I add a transparent red Rectangle to fill your TextArea, you can see what is happening:
The reason for this is that, by default, the TextArea is only as large as its text (implicitHeight/implicitWidth). Instead, if you want it to fill the top area, you need to specify Layout.fillHeight and Layout.fillWidth. This also means you maybe shouldn't have to rely on Layout.Alignment. Here is your code updated with these fills specified and some alignment properties removed:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
id: mainWindow
width: 500
height: 300
visible: true
title: qsTr("Hello World")
flags: Qt.WindowCloseButtonHint | Qt.CustomizeWindowHint | Qt.Dialog | Qt.WindowTitleHint
ColumnLayout{
anchors.fill: parent
anchors.margins: 5
RowLayout {
TextArea {
text: "Hello world!"
Layout.fillHeight: true
Layout.fillWidth: true
}
}
RowLayout {
Layout.alignment: Qt.AlignRight
Button {
text: "Ok"
}
Button {
text: "Cancel"
}
}
}
}
You can see the result if we add another transparent colored Rectangle to make it visually clear what is happening:
Related
I'm trying to make two group boxes appear next to each other so that each one occupies 50% of the window. However, it looks like the width of each GroupBox is somehow changed depending on the GroupBox title length.
If the GroupBox title is the same for both GroupBox's, it will be 50% of the window. If they are not the same, the GroupBox with the longer title will occupy more of the screen.
It doesn't make sense to me for this to happen, how can I fix it so the length of the title doesn't effect the size of the GroupBox in a layout?
Here's sample code to reproduce the issue...
AppGroupBox.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
GroupBox {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
spacing:0
label.x: 0
}
AppRowLayout.qml
import QtQuick 2.0
import QtQuick.Layouts 1.12
RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
spacing: 0
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
width: 640
height: 480
visible: true
AppRowLayout {
anchors.fill: parent
AppGroupBox {
title: "Short Name"
Layout.fillWidth: true
}
AppGroupBox {
title: "Much Longer Name"
Layout.fillWidth: true
}
}
}
Qt will distribute the free space relative to the Layout.preferredWidth (or implicitWidth if that isn't defined). So, a group box with a longer title will get more space by default, as its implicitWidth is larger.
The solution is to use a fixed preferredWidth for all elements in the RowLayout:
GroupBox {
...
Layout.preferredWidth: 50 // or any other fixed value.
Layout.minimumWidth: implicitWidth // OPTIONAL: may be usefull on small screens to ensure the box is not made smaller than the title width
...
}
Note on attached properties:
Layout.alignment is an attached property available on the children of a Layout (RowLayout, GridLayout or ColumnLayout). Setting it directly inside a RowLayout object is useless (except when the RowLayout itself is a child of another Layout item.
In QML my ComboxBox has items with large words which cannot be fully displayed in the textfield.
When opening the drop-down the items are getting cut at the right end. For that I use elide: Text.ElideRight. This works fine.
But when I select an item and it is getting displayed on the ComboBox, the Text is "scrolled" to the right and I cannot see the beginning. But I have to see the beginning of the display-text and not the end.
I tried several things with my contentItem-delegate, but thats just for the Items in the DropDown-List and not for the ComboBox-own TextField when the Popup ist closed.
The selected Item has the cursor at the right and the text is scrolled to the right. I want it to be scrolled to the left and maybe cut it at the right end.
Maybe using the proper contentItem? This is working for me.
import QtQuick 2.5
import QtQuick.Controls 2.2
import QtQuick.Window 2.2
Window {
visible: true
width: 300
height: 300
ComboBox {
width: 300
contentItem: Text {
text: parent.displayText
font.family: "Arial";
font.pixelSize: 39;
verticalAlignment: Text.AlignVCenter;
horizontalAlignment: Text.AlignLeft;
elide: Text.ElideRight
}
model: ListModel {
id: model
ListElement { text: "This is an example 0123456789 0123456789" }
ListElement { text: "Another example with long text" }
ListElement { text: "Last example" }
}
}
}
I am using Qt 5.15 Quick 2 QML to create a row of custom buttons in a window. When I have a standalone custom button things appear to work fine, but when I put them in a RowLayout there appears to be severe clipping and artifacting issues.
A minimum reproducible example might look like:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
RowLayout
{
anchors.fill:parent
anchors.margins: 25
Button
{
text: "Click Me"
Layout.fillWidth: true
}
CustomButton
{
text: "That Boy Don't Glow Right"
}
Button
{
x: 100; y:100
text: "Click Me"
Layout.fillWidth: true
}
}
}
with the custom control
import QtQuick 2.0
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
Button {
id: control
text: "Click Me"
Glow {
anchors.fill: control
radius: 64
spread: 0
samples: 128
color: "red"
source: control
visible: true
}
}
with example output:
One potential fix is to add change the Glow to
Glow {
anchors.fill: control
width: parent.width
height:parent.height
x:control.x
y:control.y
parent: control.parent
...
But this doesn't seem right. First, it's not obvious to me where parent.width and control.x and control.parent are bound from and what happens in single and multiple nesting. If a CustomButton is placed inside another control with id control, would it rebind the property? And it appears if a RowLayout is placed inside a RowLayout, then it would require parent: control.parent.parent. In my actual code there is some non-trivial positioning to allow margins for a drop shadow, too, and the CustomButton is in another container so the actual code that works is: x:control.x + parent.pad/2 and parent:control.parent.parent.parent which is, frankly, ridiculous and assumes that non-standard fields in the parent are always available.
Is there a better way? Was hoping I could keep the button's ability to glow itself.
According to the docs:
"Note: It is not supported to let the effect include itself, for instance by setting source to the effect's parent."
So it's fortunate that you were able to get your example to work at all. One way to avoid using the parent as a source is to point the Glow object at the Button's background object:
Button {
id: control
Glow {
source: control.background
}
}
The issue seems so trivial that I almost believe it's a bug in Qt itself:
import QtQuick.Window 2.2
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
Window {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
color: "white"
Layout.columnSpan: 2
Layout.fillHeight: true
Layout.fillWidth: true
radius: 5
width: 640/2
height: 480/2
TextArea {
id: txtMemo
anchors.fill: parent
anchors.margins: 5
textColor: "black"
wrapMode: TextEdit.Wrap
readOnly: false
}
}
Button {
x: 0
y: 480/2
width: 640/2
height: 480/2
onClicked: {
//Qt.inputMethod.hide()
txtMemo.visible = false
}
}
}
You need to run this on an Android device to see the bug:
Type something in to the text area so the cursor and virtual keyboard appears.
When you click the button, the cursor & keyboard stay on screen. No idea why, perhaps a feature.
Anyways, that's not the main issue. When I uncomment Qt.inputMethod.hide() and trying to reproduce, an interesting thing happens:
if the keyboard is visible, both the cursor and keyboard disappear - awesome, exactly what I want
however if the keyboard isn't visible (closed by the arrow on the bottom during typing) and the cursor is, the cursor won't disappear at all:
(apologies for the picture quality)
So how do I get rid of the cursor? Tested on Qt 5.9.6 on Android (seems unrelated on Android version, happens on the latest version as well).
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
}
}