Line-Height of Text in TextArea !
-
Hi ! Actually I am stuck in a situation where I have a condition of line-Height and I am not able to use it in my TextArea code .
My Textarea is inside Flickable which is further inside a Rectangle .
I want my Rectangle to be of 288 and 78 width and height. And the line-Height is given 22px.
I am finding troubles in handling this . So Please try to help me .
And ignore the codes for Mouse Area .
Thanks in Advance !
TextWidget.qmlimport QtQuick 2.12 import QtQuick.Controls 2.12 import QtQml 2.12 Rectangle { id: parentrect property alias textContent:textarea.text property alias fieldlabel:childrecttext.text property int paintedHeight:22 width:288 height:paintedHeight*3 border.color: "green" color: "gray" Flickable { id:flickitem contentWidth: textarea.width contentHeight:textarea.height anchors.fill: parent TextArea.flickable: TextArea { id:textarea focus: true // height: 22*textarea.lineCount hoverEnabled: true //anchors.fill:parent wrapMode: TextArea.WrapAtWordBoundaryOrAnywhere font.pixelSize: 16 font.family: "Times New Roman" leftPadding: 12 rightPadding: 12 topPadding:6 bottomPadding: 6 onTextChanged: { parentrect.height=(lineCount*parentrect.paintedHeight)+parentrect.paintedHeight } onReadOnlyChanged: { btextreadonly=textarea.readOnly } selectByMouse: true textFormat: TextArea.AutoText Component.onCompleted: { console.log(textarea.paintedHeight) console.log(parentrect.width) console.log(parentrect.height) console.log(childrecttext.paintedHeight) console.log(textarea.lineCount) } /* Function to get Active Focus on Textarea */ function activate() { if(textarea.activeFocusOnPress) textarea.forceActiveFocus() } } ScrollBar.vertical: ScrollBar{ active: hovered || pressed policy: ScrollBar.AlwaysOn } } Rectangle { id:labelrect height: childrecttext.contentHeight width: childrecttext.contentWidth color: "white" anchors{ bottom: parentrect.top left: parentrect.left right: parentrect.right bottomMargin: 8 } Text { id: childrecttext anchors.fill: parent lineHeight: 22 lineHeightMode: Text.FixedHeight font{ pixelSize: 14 family:"Times New Roman" } wrapMode: Text.WordWrap color: "black" } } MouseArea { id:mousearea anchors.fill: parent hoverEnabled: true cursorShape: Qt.IBeamCursor onEntered: { parentrect.state = "Entered"; } onExited: { parentrect.state = "Exited"; } onClicked: { textarea.activeFocusOnPress =btextreadonly?false: true; textarea.cursorVisible=true; textarea.activate(); } onPressAndHold: { if (mouse.source === Qt.MouseEventNotSynthesized) { selectStart = textarea.selectionStart; selectEnd = textarea.selectionEnd; curPos = textarea.cursorPosition; textarea.cursorPosition = curPos; textarea.select(selectStart,selectEnd); } } onDoubleClicked: textarea.selectWord() } states: [ State { name:"Entered" PropertyChanges { target:parentrect; border.color:parentrect.btextreadonly? "black":"blue" } }, State { name:"Exited" PropertyChanges { target:parentrect; border.color:parentrect.btextreadonly?"black":"green" } } ] }
Main.qml
```import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Window 2.12 Window{ width: 800 height: 400 visible: true title: qsTr("TextBox") Rectangle{ id:rect1 width : parent.width/2 height: parent.height color: "White" Row{ id:lightThemerow1 x:10 anchors.top: parent.top anchors.topMargin: 200 spacing: 20 TextWidget{ id:textarea1 fieldlabel:"Lorem ipsum dolor sit amet, conse ctetur adipiscing elit, sed do eiusmod tempor." textContent:"Lorem ipsum dolor sit amet, conse ctetur adipiscing elit, sed do eiusmod tempor incididunt ut labor." } } } }
-
@AnonymousCoder said in Line-Height of Text in TextArea !:
TextArea.flickable: TextArea {
Just
TextArea {
.And it should have
width
defined to some fixed value (same as your parent rectangle). Then, uncomment what you have inheight
and it should work.There is a lot of extra code here, it's hard to debug. Maybe try distilling this into a minimal example, even in a separate app - just to get it to work. Then you can start adding all that extra stuff back in, step by step.
-
@AnonymousCoder said in Line-Height of Text in TextArea !:
TextArea.flickable: TextArea {
Just
TextArea {
.And it should have
width
defined to some fixed value (same as your parent rectangle). Then, uncomment what you have inheight
and it should work.There is a lot of extra code here, it's hard to debug. Maybe try distilling this into a minimal example, even in a separate app - just to get it to work. Then you can start adding all that extra stuff back in, step by step.
@sierdzio I tried but the line height is still 20px only .It is not changing to 22px . Please have a look at the code .
Also how can I change the painted Height of TextArea ?import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQml 2.12 Rectangle { id: parentrect property alias textContent:textarea.text property int paintedHeight:22 width:288 height:78 border.color: "green" color: "white" Flickable { id:flickitem contentWidth: textarea.implicitWidth contentHeight: textarea.implicitHeight anchors.fill: parent boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.VerticalFlick interactive: true ScrollView{ id:scroll anchors.fill: parent height: parent.height width: parent.width TextArea{ id:textarea focus: true anchors.fill: parent implicitWidth: 288 implicitHeight: 22*textarea.lineCount //height: wrapMode: TextArea.WrapAtWordBoundaryOrAnywhere font.pixelSize: 16 font.family: "GE Inspira Sans" leftPadding: 12 rightPadding: 12 topPadding:6 bottomPadding: 6 textFormat: TextArea.AutoText // onTextChanged: { // } Component.onCompleted: { console.log(textarea.paintedHeight) console.log(parentrect.width) console.log(parentrect.height) //console.log(childrecttext.paintedHeight) console.log(textarea.lineCount) } } } } } [Here is the link of images on which I am working][(https://drive.google.com/drive/folders/1FTvkbzDkpll37BSWHkSZtPFVQTdIVx3i?usp=sharing)]
-
Don't worry about
paintedHeight
andimplicitHeight
for now, just use regularheight
.Also how can I change the painted Height of TextArea ?
By modifying font size, adding more text, changing max number of lines, changing wrapping etc. There are many many ways.
-
Don't worry about
paintedHeight
andimplicitHeight
for now, just use regularheight
.Also how can I change the painted Height of TextArea ?
By modifying font size, adding more text, changing max number of lines, changing wrapping etc. There are many many ways.
@sierdzio Yes Even I did that ..Changed to regular height but when I calculate paintedHeight in Console.log() function it is still showing me 60 which means line-height is still 20px right?
And how do I check that line height is changed? -
And what does
height
show? Is it also 60?Maybe set font size in pixels instead of font size?
font.pixelSize: 22
-
And what does
height
show? Is it also 60?Maybe set font size in pixels instead of font size?
font.pixelSize: 22
@sierdzio Just now I calculated the Textarea's height .It showed me 66 px .
But usingfont.pixelSize:22px
The rectangle's height is changing to 108
console.log(textarea.paintedHeight)
console.log(parentrect.width)
console.log(textarea.heigh
console.log(parentrect.height)
console.log(textarea.lineCount)
QML Flickable: Binding loop detected for property "height"
qml: 60
qml: 288
qml: 66
qml: 78
qml: 3 -
@sierdzio Just now I calculated the Textarea's height .It showed me 66 px .
But usingfont.pixelSize:22px
The rectangle's height is changing to 108
console.log(textarea.paintedHeight)
console.log(parentrect.width)
console.log(textarea.heigh
console.log(parentrect.height)
console.log(textarea.lineCount)
QML Flickable: Binding loop detected for property "height"
qml: 60
qml: 288
qml: 66
qml: 78
qml: 3@AnonymousCoder said in Line-Height of Text in TextArea !:
@sierdzio Just now I calculated the Textarea's height .It showed me 66 px .
But usingfont.pixelSize:22px
22
, nopx
- it's just a number.The rectangle's height is changing to 108
That's probably because of all the padding you've added.
-
@AnonymousCoder said in Line-Height of Text in TextArea !:
@sierdzio Just now I calculated the Textarea's height .It showed me 66 px .
But usingfont.pixelSize:22px
22
, nopx
- it's just a number.The rectangle's height is changing to 108
That's probably because of all the padding you've added.
@sierdzio This was the result earlier .
console.log(textarea.paintedHeight qml: 60 console.log(parentrect.width) qml: 288 console.log(textarea.height) qml: 66 console.log(parentrect.height) qml: 78 console.log(textarea.lineCount) qml: 3
And also this statement .Could you please clarify?
QML Flickable: Binding loop detected for property "height" -
QML Flickable: Binding loop detected for property "height"
That means you set some property, which updates another, which sets the first prop again etc. - an infinite loop.
Hey wait, why is there a ScrollView there? Remove it, you don't need it. It is very likely to mess up with the logic here.
-
QML Flickable: Binding loop detected for property "height"
That means you set some property, which updates another, which sets the first prop again etc. - an infinite loop.
Hey wait, why is there a ScrollView there? Remove it, you don't need it. It is very likely to mess up with the logic here.
@sierdzio Okay as You said I have removed the ScrollView But then If the text is more than the height of the Rectangle then it should scroll right .
So I have added ScrollBar inside Flickable .
Flickable { id:flickitem width: textarea.width height: textarea.height anchors.fill: parent boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.HorizontalFlick interactive: true ScrollBar.vertical: Scrollbar{} TextArea{...}
Scrollbar.qml
ScrollBar { id: control size: 0.3 position: 0.2 active: true orientation: Qt.Vertical anchors.right: parent.right contentItem: Rectangle { implicitWidth: 4 implicitHeight: 76 radius: width / 2 color: control.pressed ? "#81e889" : "#c2f4c6" } }
But still it is not scrolling .
-
@AnonymousCoder said in Line-Height of Text in TextArea !:
Scrollbar.qml
You don't need that, there is https://doc.qt.io/qt-5/qml-qtquick-controls2-scrollbar.html. As said, keep custom code to minimum until you make it work.
Flickable {
id:flickitem
width: textarea.width
height: textarea.heightYou set TextArea size to be the same as Flickable - so there is nothing to scroll - the entire text area will be shown.
You need to make the Flickable smaller than TextArea, then set Flickable's
contentHeight
andcontentWidth
to match that of TextArea. -
@AnonymousCoder said in Line-Height of Text in TextArea !:
Scrollbar.qml
You don't need that, there is https://doc.qt.io/qt-5/qml-qtquick-controls2-scrollbar.html. As said, keep custom code to minimum until you make it work.
Flickable {
id:flickitem
width: textarea.width
height: textarea.heightYou set TextArea size to be the same as Flickable - so there is nothing to scroll - the entire text area will be shown.
You need to make the Flickable smaller than TextArea, then set Flickable's
contentHeight
andcontentWidth
to match that of TextArea.This post is deleted! -
@AnonymousCoder said in Line-Height of Text in TextArea !:
Scrollbar.qml
You don't need that, there is https://doc.qt.io/qt-5/qml-qtquick-controls2-scrollbar.html. As said, keep custom code to minimum until you make it work.
Flickable {
id:flickitem
width: textarea.width
height: textarea.heightYou set TextArea size to be the same as Flickable - so there is nothing to scroll - the entire text area will be shown.
You need to make the Flickable smaller than TextArea, then set Flickable's
contentHeight
andcontentWidth
to match that of TextArea.@sierdzio As you said I kept the code as minimum as possible and I tried to do it from scratch.
so for now I have given onlyTextArea{}
and itsbackground:Rectangle{}
Which I have shared here with the results.
TextArea{ id:area width: 288 height: 22*area.lineCount font.pixelSize: 16 font.family: "GE Inspira Sans" topPadding: 6 bottomPadding: 6 leftPadding: 12 rightPadding: 12 text: "Lorem ipsum dolor sit amet, conse ctetur adipiscing elit, sed do eiusmod tempor incididunt ut labor." wrapMode: TextArea.WordWrap background: Rectangle{ id:rect width: 288 height: 78 border.color: "black" } Component.onCompleted: { console.log(area.paintedHeight) console.log(area.height) console.log(rect.height) } }
Results :
qml: 60 qml: 66 qml: 78
And suppose if I get line-height correctly also then how should I check whether it is correct or not?
Is there any way to implement Html here in TextArea?Also I have shared a link to images which I need ( See images with Black background) and those with the above code (see images with white background).
Click here -
@sierdzio Hi , Actually I tried many ways but I got something which is not fully working but still 50% of work is fine .
i am using css property inside
text:
liketext: "<body style=\"line-height:137.5% ;\">"
but i am not sure this is the correct way to do or not .
And now the issue is when I use 137.5% which is 22px line-height then always the 3rd line comes half when the application runs .
So how to fix that ? -
HI @sierdzio and anyone who is watching this thread.
I got one solution on how to achieve line-height of text inside TextArea.
I took help fromQTextDocument
and tried to use it but there is one limitation with this solution.
Actually when I tried to use the keyboard operations(undo,redo,cut,copy,paste,select-all)
then every operation is working but when i tried paste operations(cut-paste, copy-paste )
then theundo, redo
operations won't work . They will only work again when I doselect-all
operation. so this is the limitation with this solution.Now When you see the code in
TextDoc.cpp
there you will find 2 statements which containssetUndoRedoEnabled(false)
&setUndoRedoEnabled(true)
. Here the question arises that why playing with Undo, Redo is needed ? So the answer is its needed because if I dont give these lines then after the paste operation the line-height property is lost ...therefore to achieve it we need that .Again the issue is still "How to achieve line-height of Text in TextArea?" But if you have solution to the above Undo , Redo issue ...Then please help .
Thanks !Mail.Qml
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.12 import TextDoc 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") property int cursor_pos: 0 property bool pasted: false property int prev_len: 0 property int pix: 50 function fun(s) { return (s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); } ScrollView { y:200 clip: true width: 600 height: 400 TextArea { id: ta width: 600 height: 400 wrapMode: Text.WrapAnywhere textFormat: TextEdit.PlainText placeholderText: "Hint Text" text: "sdfffffffffffffff dsf sdf sdf \n sdfdsfdsffsd\n dsfdsfdsfdsfdsfdsfdfdsfsdfdssssssssssssssssssssssssssssss" font.pixelSize: 16 font.family: "courier" background: Rectangle { width: 600 height: 400 border.color: "blue" } Keys.onPressed: { if ( (event.key === Qt.Key_V) && (event.modifiers & Qt.ControlModifier ) ) { pasted = true; } } Keys.onReleased: { if ((event.key === Qt.Key_V) && (pasted)){ pasted = false; tdoc.onCompleted(pix); } } TextDoc { id: tdoc } Component.onCompleted: { tdoc.setTDoc(ta.textDocument); tdoc.onCompleted(pix); } } } }
TextDoc.h
#include <QTextDocument> #include <QQuickTextDocument> #include <QDebug> class TextDo : public QObject { Q_OBJECT public: explicit TextDo(QObject* parent = nullptr); static void registerQmlType(); Q_INVOKABLE void onCompleted(int c); Q_INVOKABLE void setTDoc(QQuickTextDocument* newTDoc) { qDebug() << "setTDoc called"; tDoc = newTDoc; }; private: QQuickTextDocument *tDoc; };
TextDoc.cpp
#include "TextDoc.h" #include <QTextFrame> void TextDo::onCompleted(int c) { qDebug() << "onCompleted called"; tDoc->textDocument()->setUndoRedoEnabled(false); QTextBlockFormat blockFmt = QTextBlockFormat(); blockFmt.setLineHeight(c, QTextBlockFormat::FixedHeight); QTextCursor theCursor(tDoc->textDocument()); theCursor.clearSelection(); theCursor.select(QTextCursor::Document); theCursor.mergeBlockFormat(blockFmt); tDoc->textDocument()->setUndoRedoEnabled(true); } TextDo::TextDo(QObject *parent) { } void TextDo::registerQmlType() { qmlRegisterType<TextDo>("TextDoc", 1, 0, "TextDoc"); }
In Main.cpp just add 1 more statement
TextDo::registerQmlType();
-
Hey @sierdzio
I have found the solution to this generic issue which is "How to achieve line - height of Text in Textarea or Textbox or Textedit (Editable items) ?" .
Actually frankly speaking we don't have a direct solution for this so we will use something which is a bit complicated.Based on my previous comment I would like to add something that the above code is the solution for this issue but there we will have to add some more 2-3 lines of code because previous solution has some issues actually.
Main.qml
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.12 import TextDoc 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") property int cursor_pos: 0 property bool pasted: false property int prev_len: 0 property int pix: 50 function fun(s) { return (s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); } ScrollView { y:200 clip: true width: 600 height: 400 TextArea { id: ta width: 600 height: 400 wrapMode: Text.WrapAnywhere textFormat: TextEdit.PlainText placeholderText: "Hint Text" text: "sdfffffffffffffff dsf sdf sdf \n sdfdsfdsffsd\n dsfdsfdsfdsfdsfdsfdfdsfsdfdssssssssssssssssssssssssssssss" font.pixelSize: 16 font.family: "courier" background: Rectangle { width: 600 height: 400 border.color: "blue" } Keys.onPressed: { if ( (event.key === Qt.Key_V) && (event.modifiers & Qt.ControlModifier ) ) { event.accepted = true; pasted = true; } } Keys.onReleased: { if ((event.key === Qt.Key_V) && (pasted)){ event.accepted = true; pasted = false; tdoc.pasteText(cursorPosition, selectionStart, selectionEnd); } } TextDoc { id: tdoc } Component.onCompleted: { tdoc.setTDoc(ta.textDocument); tdoc.onCompleted(pix); } } } }
TextDoc.h
TextDoc.h #include <QTextDocument> #include <QQuickTextDocument> #include <QDebug> class TextDo : public QObject { Q_OBJECT public: explicit TextDo(QObject* parent = nullptr); static void registerQmlType(); Q_INVOKABLE void onCompleted(int c); Q_INVOKABLE void pasteText(int pos, int selectionStart, int selectionEnd); Q_INVOKABLE void setTDoc(QQuickTextDocument* newTDoc) { qDebug() << "setTDoc called"; tDoc = newTDoc; }; private: QQuickTextDocument *tDoc; };
TextDoc.cpp
#include "TextDoc.h" #include <QTextFrame> void TextDo::onCompleted(int c) { qDebug() << "onCompleted called"; tDoc->textDocument()->setUndoRedoEnabled(false); QTextBlockFormat blockFmt = QTextBlockFormat(); blockFmt.setLineHeight(c, QTextBlockFormat::FixedHeight); QTextCursor theCursor(tDoc->textDocument()); theCursor.clearSelection(); theCursor.select(QTextCursor::Document); theCursor.mergeBlockFormat(blockFmt); tDoc->textDocument()->setUndoRedoEnabled(true); } void TextDoc::pasteText(int pos, int selectionStart, int selectionEnd) { const QString text = QGuiApplication::clipboard()->text() if(text.isNull()) { return; } QTextCursor theCursor(tDoc->textDocument()); if(selectionStart >= 0 && selectionEnd >= 0) { theCursor.setPosition(selectionStart, QTextCursor::MoveAnchor); theCursor.setPosition(selectionEnd, QTextCursor::KeepAnchor); } else { theCursor.setPosition(pos); } theCursor.beginEditBlock(); theCursor.insertText(text); theCursor.endEditBlock(); } TextDo::TextDo(QObject *parent) { } void TextDo::registerQmlType() { qmlRegisterType<TextDo>("TextDoc", 1, 0, "TextDoc"); }
In Main.cpp just add 1 more statement
TextDo::registerQmlType();
Therefore in the above code you can see I have added one more function to TextDoc class which is pasteText() , it actually pastes the text to the clipboard and then tries to apply other clipboard operations.
So this solution is working fine for me and I hope it works for others too.Thanks @sierdzio for helping me and others who are watching this thread.