Remove space between TabButton in TabBar - qt

I'm making a TabBar with custom TabButton and I want to remove the white space between the buttons. I've tried several things but I can't find the correct TabButton property.
This is my code:
Boton.qml:
TabButton {
onCheckedChanged: canvas.requestPaint()
contentItem: Text {
antialiasing: false
text: parent.text
font.family: "monofonto"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "#19F51E"
}
background: Rectangle{
color: 'black'
}
Canvas{
id: canvas
width: parent.width
height: parent.height
onPaint: {
var ctx = getContext("2d");
ctx.reset()
ctx.lineWidth = 5;
ctx.strokeStyle = "#19F51E";
ctx.beginPath()
if (parent.checked){
ctx.moveTo(0, 0)
ctx.lineTo(width, 0)
} else {
ctx.moveTo(0, height)
ctx.lineTo(width, height)
}
ctx.stroke()
}
}
}

I found the property. Setting spacing to 0 works fine.

Related

Doesn't see popup menu on combobox

I'm trying to set a new style to comboBox in qml and get in trouble my combobox doesn't want to show me drop-down list everything else is fine, here is code
The code I took from Internet
T.ComboBox {
id: _comboBox
anchors.bottom: _borderedTextboxPoints.top
anchors.horizontalCenter: _borderedTextboxPoints.horizontalCenter
anchors.bottomMargin: 10
delegate: T.ItemDelegate { //! Changing style of items in list
width: _comboBox.width
contentItem: Text {
text: modelData
color: "black"
font: _comboBox.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: _comboBox.highlightedIndex === index
}
indicator: Canvas { //! Changing style of indicator
id: canvas
x: _comboBox.width - width - _comboBox.rightPadding - 5
y: _comboBox.topPadding + (_comboBox.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
Connections { //! Changing style on pressed
target: _comboBox
function onPressedChanged() { canvas.requestPaint(); }
}
onPaint: {
context.reset();
context.moveTo(0, 0);
context.lineTo(width, 0);
context.lineTo(width / 2, height);
context.closePath();
context.fillStyle = _comboBox.pressed ? "#722ed1" : "#531dab";
context.fill();
}
}
contentItem: Text {
leftPadding: 5
rightPadding: _comboBox.indicator.width + _comboBox.spacing
text: _comboBox.displayText
font: _comboBox.font
color: "black"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
border.color: _comboBox.pressed ? "#2f54eb" : "#1d39c4"
border.width: _comboBox.visualFocus ? 2 : 1
radius: 10
}
popup: T.Popup { //! Changing style of drop-down list
y: _comboBox.height - 1
width: _comboBox.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model:_comboBox.popup.visible ? _comboBox.delegateModel : null
currentIndex: _comboBox.highlightedIndex
T.ScrollIndicator.vertical: T.ScrollIndicator { }
}
}
}
That's look like this
In the popup code add a z and use an index higher than 1
popup: T.Popup { //! Changing style of drop-down list
...
padding: 1
z: 4
...
I used 4 as the z, here because I knew 4 will definitely work. But maybe 2 too would have worked.
This usually happens when you are showing the combo box in a popup.

Line numbers/ line height for a Qml TextArea

We want to implement an embedded code editor in our QtQuick based application. For highlighting we use a QSyntaxHighlighter based on KSyntaxHighlighting. We found no way to determine the line height and line spacing that would allow us to display line numbers next to the code. Supporting dynamic line-wrap would also be a great addition.
Flickable {
id: flickable
flickableDirection: Flickable.VerticalFlick
Layout.preferredWidth: parent.width
Layout.maximumWidth: parent.width
Layout.minimumHeight: 200
Layout.fillHeight: true
Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds
clip: true
ScrollBar.vertical: ScrollBar {
width: 15
active: true
policy: ScrollBar.AlwaysOn
}
property int rowHeight: textArea.font.pixelSize+3
property int marginsTop: 10
property int marginsLeft: 4
property int lineCountWidth: 40
Column {
id: lineNumbers
anchors.left: parent.left
anchors.leftMargin: flickable.marginsLeft
anchors.topMargin: flickable.marginsTop
y: flickable.marginsTop
width: flickable.lineCountWidth
function range(start, end) {
var rangeArray = new Array(end-start);
for(var i = 0; i < rangeArray.length; i++){
rangeArray[i] = start+i;
}
return rangeArray;
}
Repeater {
model: textArea.lineCount
delegate:
Label {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "white" : "#666"
font: textArea.font
width: parent.width
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: flickable.rowHeight
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "red" : "white"
}
}
}
}
Rectangle {
y: 4
height: parent.height
anchors.left: parent.left
anchors.leftMargin: flickable.lineCountWidth + flickable.marginsLeft
width: 1
color: "#ddd"
}
TextArea.flickable: TextArea {
id: textArea
property bool differentFromSavedState: fileManager.textDifferentFromSaved
text: fileManager.textTmpState
textFormat: Qt.PlainText
//dont wrap to allow for easy line annotation wrapMode: TextArea.Wrap
focus: false
selectByMouse: true
leftPadding: flickable.marginsLeft+flickable.lineCountWidth
rightPadding: flickable.marginsLeft
topPadding: flickable.marginsTop
bottomPadding: flickable.marginsTop
background: Rectangle {
color: "white"
border.color: "green"
border.width: 1.5
}
Component.onCompleted: {
fileManager.textEdit = textArea.textDocument
}
onTextChanged: {
fileManager.textTmpState = text
}
function update()
{
text = fileManager.textTmpState
}
}
}
As you can see we use property int rowHeight: textArea.font.pixelSize+3 to guess the line height and line spacing but that of course breaks as soon as DPI or other properties of the system change.
The TextArea type has two properties contentWidth and contentHeight which contains the size of the text content.
So, if you divide the height by the number of lines (which you can get with the property lineCount), you will get the height of a line:
property int rowHeight: textArea.contentHeight / textArea.lineCount
But, if you plan to have multiple line spacing in the same document, you will have to handle each line by manipulating the QTextDocument:
class LineManager: public QObject
{
Q_OBJECT
Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
public:
LineManager(): QObject(), document(nullptr)
{}
Q_INVOKABLE void setDocument(QQuickTextDocument* qdoc)
{
document = qdoc->textDocument();
connect(document, &QTextDocument::blockCountChanged, this, &LineManager::lineCountChanged);
}
Q_INVOKABLE int lineCount() const
{
if (!document)
return 0;
return document->blockCount();
}
Q_INVOKABLE int height(int lineNumber) const
{
return int(document->documentLayout()->blockBoundingRect(document->findBlockByNumber(lineNumber)).height());
}
signals:
void lineCountChanged();
private:
QTextDocument* document;
};
LineManager* mgr = new LineManager();
QQuickView *view = new QQuickView;
view->rootContext()->setContextProperty("lineCounter", mgr);
view->setSource(QUrl("qrc:/main.qml"));
view->show();
Repeater {
model: lineCounter.lineCount
delegate:
Label {
color: "#666"
font: textArea.font
width: parent.width
height: lineCounter.height(index)
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
border.color: "black"
}
}
}
I found a QML only solution:
Use TextEdit instead of TextArea to avoid alignment issues between line numbers and text
Use a 'ListView' to generate the line numbers for the text edit:
Here is an initial solution:
RowLayout {
anchors.fill: parent
ListView {
Layout.preferredWidth: 30
Layout.fillHeight: true
model: textEdit.text.split(/\n/g)
delegate: Text { text: index + 1 }
}
TextEdit {
id: textEdit
Layout.fillWidth: true
Layout.fillHeight: true
}
}
The ListView has a complete copy of each row of text. We can use this copy to compute the line height (taking into account of word wrap). We do this by creating an invisible Text. We can improve the answer further by adding a Flickable to the TextEdit and synchronize the scroll between the ListView and the TextEdit:
Here is a more complete solution:
// NumberedTextEdit.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
Item {
property alias lineNumberFont: lineNumbers.textMetrics.font
property color lineNumberBackground: "#e0e0e0"
property color lineNumberColor: "black"
property alias font: textEdit.font
property alias text: textEdit.text
property color textBackground: "white"
property color textColor: "black"
Rectangle {
anchors.fill: parent
color: textBackground
ListView {
id: lineNumbers
property TextMetrics textMetrics: TextMetrics { text: "99999"; font: textEdit.font }
model: textEdit.text.split(/\n/g)
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
width: textMetrics.boundingRect.width
clip: true
delegate: Rectangle {
width: lineNumbers.width
height: lineText.height
color: lineNumberBackground
Text {
id: lineNumber
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
color: lineNumberColor
font: textMetrics.font
}
Text {
id: lineText
width: flickable.width
text: modelData
font: textEdit.font
visible: false
wrapMode: Text.WordWrap
}
}
onContentYChanged: {
if (!moving) return
flickable.contentY = contentY
}
}
Item {
anchors.left: lineNumbers.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
Flickable {
id: flickable
anchors.fill: parent
clip: true
contentWidth: textEdit.width
contentHeight: textEdit.height
TextEdit {
id: textEdit
width: flickable.width
color: textColor
wrapMode: Text.WordWrap
}
onContentYChanged: {
if (lineNumbers.moving) return
lineNumbers.contentY = contentY
}
}
}
}
}
I've found that you can query the line height using FontMetrics and then getting the true height by Math.ceil(fontMetrics.lineSpacing) for example:
TextEdit {
id: textArea
FontMetrics {
id: fontMetricsId
font: textArea.font
}
Component.onCompleted: {
console.log("Line spacing:" + Math.ceil(fontMetricsId.lineSpacing)
}
}

plus button under listview

I can create "+" (plus) button under all listview items.
This button will add a new item.
I can place it under all exsisting items. But ideály as a part as list.Because of scrolling, scrollbars and other standard listview functions. If listview will be not fill all available page size, scrolls will be ended in the middle of the screan etc...
I tested counting onpaint signal or something like this, but have no success. Because signal for one row goint more than one times, counting is mismatched and button is one time in seccond row, one time below third, sometimes is missing etc...
Example image:
Source code:
import QtQuick 2.10
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
Page {
title: qsTr("Page 1")
anchors.fill: parent
focus: true
property int myIndex: 0
function setVisibility()
{
if(myModel.rowCount()*3 === myIndex)
{
myIndex = 0
return true
}
else
{
myIndex = myIndex + 1
return false
}
}
/*
*
*
* ListView Component
*
*
*/
ListView
{
id: listView1
model: myModel
currentIndex: 0
//property int actualHeight
anchors.fill: parent
clip: true
//spacing: 40
highlightMoveDuration: 1
highlightMoveVelocity: 1
highlightResizeDuration: 0.0
highlight: Rectangle
{
color: "#2e6377"
opacity: 0.3
}
delegate: hDelegate
}
/*
*
*
* ListViewItem Component
*
*
*/
Component
{
id: hDelegate
Item
{
width: parent.width
height: taskInfo.implicitHeight
property variant mainData: model
MouseArea
{
anchors.fill: parent
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
}
onDoubleClicked:
{
listView1.currentIndex = index
stackView.push("page3.qml")
}
onPressAndHold:
{
listView1.currentIndex = index
stackView.push("page3.qml")
}
hoverEnabled: true
}
Row
{
id: taskInfo
spacing: 5
Rectangle
{
id: dificultStatus
height: taskColumn.height
width: taskColumn.height
color: "transparent"
Rectangle
{
id: rect22
color: "green"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Column
{
id: taskColumn
width: listView1.width - editButton.width - dificultStatus.width - 10
Row
{
Text
{
text: task_subject
color: "lightsteelblue"
horizontalAlignment: Text.AlignRight
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
Text
{
text: task_subject
color: "lightsteelblue"
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
}
Text
{
id: text1
height: 50
width: parent.width
clip: true
text: task_body
color: "lightsteelblue"
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
}
Button
{
id: editButton
height: taskColumn.height
width: taskColumn.height
background:
Rectangle
{
anchors.fill: parent
color: "transparent"
Rectangle
{
color: "transparent"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
anchors.fill: parent
text: qsTr("...")
color: "lightsteelblue"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 24
anchors.centerIn: parent
}
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
stackView.push("page3.qml")
}
}
/*
*
*
* AddButton Component
*
*
*/
Button
{
height: taskColumn.height
width: taskColumn.height
x: 0
y: 80
visible: setVisibility()
//visible: (myModel.rowCount() === ++myIndex) ? true : false
background:
Rectangle
{
anchors.fill: parent
color: "transparent"
Rectangle
{
color: "transparent"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
anchors.fill: parent
text: qsTr("+")
color: "lightsteelblue"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 24
anchors.centerIn: parent
}
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
stackView.push("page2.qml")
}
}
}
}
}
}
You can just use ListView's footer property. The default footerPositioning is what you want.

Need responsive height for DropDown List in QML for ComboBox?

I am creating a custom combobox model in which i need to assign a height of a dropDown list in responsive value. It is on length of items at present so unable to reduce or increase its height as per screen resolution. Here is my code :
Rectangle {
width:150;
height: 60;
Rectangle {
id:comboBox
property variant items: ["Item 1", "Item 2", "Item 3"]
property alias selectedItem: chosenItemText.text;
property alias selectedIndex: listView.currentIndex;
signal comboClicked;
width: 100;
height: 30;
z: 100;
smooth:true;
Rectangle {
id:chosenItem
radius:4;
width:parent.width;
height:comboBox.height;
color: "lightsteelblue"
smooth:true;
Text {
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 8;
id:chosenItemText
text:comboBox.items[0];
font.family: "Arial"
font.pointSize: 14;
smooth:true
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
}
}
}
Rectangle {
id:dropDown
width:comboBox.width;
height:0;
clip:true;
radius:4;
anchors.top: chosenItem.bottom;
anchors.margins: 2;
color: "lightgray"
ListView {
id:listView
height:500;
model: comboBox.items
currentIndex: 0
delegate: Item{
width:comboBox.width;
height: comboBox.height;
Text {
text: modelData
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 5;
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = ""
var prevSelection = chosenItemText.text
chosenItemText.text = modelData
if(chosenItemText.text != prevSelection){
comboBox.comboClicked();
}
listView.currentIndex = index;
}
}
}
}
}
Component {
id: highlight
Rectangle {
width:comboBox.width;
height:comboBox.height;
color: "red";
radius: 4
}
}
states: State {
name: "dropDown";
PropertyChanges { target: dropDown; height:30*comboBox.items.length }
}
transitions: Transition {
NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 1000 }
}
}
}
Please suggest me some solution.

qml textedit with slider

Does anyone know how to create a textEdit that can wrap using a slider?
i tried to do it but i got a problem with binding loop...
code:
Flickable
{
id: flick
anchors.fill:parent
contentWidth: edit.paintedWidth
contentHeight: edit.paintedHeight
clip: true
interactive :false
contentY: slider.y
function ensureVisible(r)
{
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit
{
id: edit
width: flick.width*0.9
height: flick.height
focus: true
wrapMode: TextEdit.Wrap
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
text: defaultText
color: textColor
font.family: fontFamily
font.pointSize: fontSize
font.bold: bold
font.italic: italic
font.overline: overline
font.underline: underline
horizontalAlignment: alignment
selectByMouse:true
}
}
Rectangle
{
id: container
height: multiLineEdit.height
width:multiLineEdit.width*0.1
anchors.right:multiLineEdit.right
anchors.top:multiLineEdit.top
radius: 4
opacity: 0.7
smooth: true
gradient: Gradient {
GradientStop { position: 0.0; color: "gray" }
GradientStop { position: 1.0; color: "white" }
}
Rectangle {
id: slider
property int value: Math.round(container.y*100/(slider.width-container.width))
property int tmpVal: 0
x: 1
y: flick.visibleArea.yPosition * flick.height//1
width: parent.width
//The height will change according to the flickable area (the text area)
height: (flick.visibleArea.heightRatio > 1) ? (container.height) :(flick.visibleArea.heightRatio*container.height)
radius: 2
smooth: true
color:"black"
MouseArea {
anchors.fill: parent
drag.target: parent; drag.axis: Drag.YAxis
drag.minimumY: 0; drag.maximumY: container.height - slider.height
}
}
}
in this way i create a textEdit and a slier at the right side of the textEditBox. the slider is now move according to the text, but it(the slider) doe's not control the textEdit box... how i can add this action? (in my way it bring a binding loop)
Maybe you could grab keyboard button press event with a custom slot if key event match left and right arrow i.e.
Please take a look here: link for QWidget::grabKeyboard()

Resources