I'm Trying to make a Circular ListView with List Items arranged on Half Circle. it should look something like this:
I'm using Qt open source license and i cannot find a controller similar in QtControls.
Please any idea or suggestion ?
Thanks in advance
Here is a solution based on the link that folibis shared in the comments above using PathView to layout the items of a model along a PathArc.
import QtQuick
import QtQuick.Window
import QtQuick.Shapes
Window {
visible: true
width: 400
height: 400
Shape {
ShapePath {
strokeWidth: 2
strokeColor: "black"
fillColor: "lightgrey"
startX: 0
startY: 0
PathArc {
x: 0
y: 400
radiusX: 400
radiusY: 400
}
}
}
Shape {
x: 100
ShapePath {
strokeWidth: 2
strokeColor: "grey"
startX: 0
startY: 0
PathArc {
x: 0
y: 400
radiusX: 400
radiusY: 400
}
}
}
PathView {
x: 100
model: ["Apple", "Banana", "Cherry", "Dragonfruit", "Grapefruit", "Orange", "Papaya"]
delegate: Item {
width: 50
height: 50
Rectangle {
height: 50
width: 260
radius: 25
color: "lightgrey"
}
Rectangle {
id: circle
width: 50
height: 50
radius: 25
color: "darkgrey"
}
Text {
anchors.leftMargin: 10
anchors.left: circle.right
anchors.verticalCenter: parent.verticalCenter
text: modelData
font.pixelSize: 24
}
}
path: Path {
// Those 2 coordinates are a bit of hack to push down the first item on the actual arc
// so it won't stick out the top. There might be a better way of doing that
startX: 18
startY: 35
PathArc {
x: 0
y: 400
radiusX: 400
radiusY: 400
}
}
}
}
Related
I want to create a chart like this in qt. I already searched and can not find a way to do it.
I also can not find a way to customize Barchart and look like this in Widget Based Applications
Easy in QML!
import QtQuick 2.0
import QtQuick.Layouts 1.1
Rectangle
{
width: 600
height: 300
ListModel
{
id: dataModel
ListElement { label: "C.A"; value: 37 }
ListElement { label: "C.B"; value: 58 }
ListElement { label: "C.C"; value: 16 }
ListElement { label: "C.D"; value: 5 }
ListElement { label: "C.E"; value: 95 }
ListElement { label: "C.F"; value: 10 }
ListElement { label: "C.G"; value: 27 }
ListElement { label: "C.H"; value: 2 }
}
Rectangle
{
height: 4
width: layout.width
anchors.top: layout.bottom
anchors.horizontalCenter: layout.horizontalCenter
color: "#bbbdbe"
}
RowLayout
{
id: layout
width: 400
height: 200
spacing: 0
anchors.centerIn: parent
Repeater
{
id: rpt
property int barWidth: layout.width / count
model: dataModel
delegate:
Rectangle
{
width: rpt.barWidth
height: layout.height
color: "transparent"
Rectangle
{
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: 3
height: (parent.height * value) / 100
color: "#448bbe"
Rectangle
{
color: "#448bbe"
radius: width / 2
width: 8
height: 8
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
}
Text
{
y: parent.height + 3
anchors.horizontalCenter: parent.horizontalCenter
text: label
}
}
}
}
}
Screenshot
Since the OP didn't specify he wants a solution for a Qt widgets based application [he did after editing the question], the answer is:
Create your own QWidget class. Override the paintEvent and paint in it with a QPainter. I think there's plenty of examples if you google it.
Like this: http://doc.qt.io/qt-5/qtwidgets-painting-basicdrawing-example.html
Or this: http://programmingexamples.wikidot.com/qt-qpainter-example
Or this: Draw on QWidget
You can go for Custom QQuickPaintedItem here you can find an Example.
How to generate a .cpp and .h file for login.qml file?
I have written a .qml file for a login page.
my code is as following
import QtQuick 1.0
Rectangle{
id:screen
color: "lightgray"
width: 3000; height:2700
Column {
id: column1
width: 201
height: 400
Row {
id: row1
width: 40
height:50
TextInput {
id: userName
x: 40
y: 18
width: 80
height: 20
text: qsTr("UserName")
font.pixelSize: 12
}
Rectangle {
id: rectangle1
x: 115
y: 18
width: 80
height: 20
color: "#ffffff"
}
}
Row {
id: row2
width: 40
height: 50
TextInput {
id: password
x: 40
y: 18
width: 80
height: 20
text: qsTr("Password")
font.pixelSize: 12
}
Rectangle {
id: rectangle2
x: 115
y: 18
width: 80
height: 20
color: "#ffffff"
}
}
Row {
id: row3
x: 8
y: 113
width: 40
height: 50
Rectangle {
id: rectangle3
x: 8
y: 8
width: 80
height: 20
color: "#ffffff"
Text {
id: login
text: "Login"
x:4
y:4
width:30
height:10
font.pixelSize: 12
}
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
myclass.doStuffFromQmlSlot();
Qt.quit();
}
}
}
That would be quite some work.
You would need to write a C++ code generator or find an existing one.
You would either need to parse the QML code or load it and traverse the tree to feed your code generator.
Your generated code would then either depend on private Qt headers or you need your own implementations for the QtQuick types.
I'm rendering a custom OpenGL Item, and on top of that I would like to add some widgets.
So far, it's working fine. This is what it looks like.
However, now I am trying to add a Text item to the OpenGL via:
Rectangle{
id: logoTextBox
x: logoButton.x + logoButton.width
y: logoButton.y
width: 200
height: logoButton.height
color: "#EEEEEE"
Text{
id: logoVersionBlurb
y: 10
x: 10
font.pointSize: 8
text: "Ver 1.0"
color: "black"
}
Text{
id: logoNameBlurb
y: 20
x: 10
font.pointSize: 14
font.bold: true
text: "Please work"
}
}
and It looks like this:
I still want the OpenGL to render, but I want the Text to appear overlayed above it. Any ideas?
I'm creating my GLContext like this in QML:
MyGLWidget{
id: glWidget
}
And here is the relevant method from the C++ file
void MyGLWidget::sync()
{
if (!m_renderer) {
m_renderer = new MyGLRenderer();
connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
}
m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
}
Okay, I've found a solution. I set the text's renderType to NativeRendering, and that caused the Triangle to render correctly.
Text{
id:sizeDialogXText
color: "white"
y: sizeDialogTitleText.y + 20
x: sizeDialogTitleText.x
text: "X"
font.pointSize: 12
renderType: Text.NativeRendering //This is the important line
}
In OpenGL terms, what I want to do is modify the projection matrix of a Qt GUI.
Pretend the window is 480x640. It is displayed as normal, and rendered to a texture.
I then take that texture, and stretch it across the entire screen.
Does Qt have something like that? I don't want the GUI looking fine and having appropriately-sized text on a 480x640 tablet, but then it gets loaded up on a 1536x2048 tablet and you need a magnifying glass for the text.
I've written my own GUI in OpenGL before, calculating a vid.width/BASEWIDTH, vid.height/BASEHEIGHT ratio and multiplying the modelview matrix of elements to ensure that a GUI always fills a screen and stays the same size -- obviously this only works perfectly providing the aspect ratio is the same, but I digress.
I messed with layouts in Qt Quick for awhile, and it offers some nice anchoring options, but nothing for stuff like scaling up the text if the parent window is larger. Or am I missing something here?
An OpenGL GUI I wrote had a few options for control position coordinates:
Origin for transforms (Top, Center, Bottom, Left, Center, Right)
PosIsPercentage (specified whether the position coordinates were to be interpreted as a percentage of screen width/height)
This allowed you to set the position as a distance from any edge of the screen, or you could set PosIsPercentage = true and set the X value to 75 to have the coordinate always be at 3/4ths of whatever the screen size was.
There was also a SizeIsPercentage value, so you could set a button to be 10% of the screen width.
I see some of these options in the Qt Quick designer, but they aren't behaving as I expect.
I know this is hard to explain, so here is an image to demonstrate:
http://www.spaddlewit.com/QtLayoutProblem.png
(not what I'm using Qt for, but a good example of the problem I'm having)
Scaling items based on the width and height of the screen works well enough, except when you move to a high DPI device. A better method is to scale items based on the height of the default font. The default font size of a Text item, for example, will always be legible on platforms supported by Qt, no matter the DPI. You can use the same principle to scale font sizes; multiply the default font size by some amount.
Below I've done a quick mock up of the screenshot you linked to:
import QtQuick 2.3
import QtQuick.Controls 1.2
ApplicationWindow {
id: window
contentItem.implicitWidth: 640
contentItem.implicitHeight: 480
contentItem.minimumWidth: 640
contentItem.minimumHeight: 480
contentItem.maximumWidth: 1024
contentItem.maximumHeight: 768
/*
With Qt 5.4, you can also use the new FontMetrics item,
which saves you the overhead of creating a Text item:
For example:
FontMetrics {
id: fontMetrics
}
Then:
font.pixelSize: fontMetrics.font.pixelSize * 4
anchors.margins: fontMetrics.implicitHeight * 2
*/
Text {
id: defaultText
}
Image {
source: "http://cdn2.landscapehdwalls.com/wallpapers/1/perfect-green-hills-1197-1280x800.jpg"
}
Item {
id: container
anchors.fill: parent
anchors.margins: defaultText.implicitHeight * 2
Column {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: container.anchors.margins
Text {
id: yourGameText
text: "Your Game!"
font.pixelSize: defaultText.font.pixelSize * 4
wrapMode: Text.Wrap
}
ListView {
interactive: false
anchors.right: parent.right
width: yourGameText.width
height: container.height * 0.3
model: ["Play Game!", "Options", "Exit"]
delegate: Button {
text: modelData
width: ListView.view.width
}
}
}
Row {
anchors.left: parent.left
anchors.bottom: parent.bottom
spacing: container.anchors.margins
Image {
source: "http://www.facebookbrand.com/img/assets/asset.f.logo.lg.png"
width: defaultText.implicitHeight * 3
height: width
}
Image {
source: "http://g.twimg.com/Twitter_logo_white.png"
width: defaultText.implicitHeight * 3
height: width
}
Image {
source: "http://www.youtube.com/yt/brand/media/image/YouTube-logo-full_color.png"
width: defaultText.implicitHeight * 3
height: width
}
}
}
}
Window Size
The first thing I did was set the default, minimum and maximum size of the window.
Scaling
Next, I created an empty Text item which items and text sizes will be based off. It might seem hackish, and it is a bit, but it also works really well. As mentioned in the comment, in Qt 5.4 there will be a FontMetrics type which you can use instead of creating a Text item that will never actually be shown.
Another alternative is to use Screen's pixelDensity property.
Margins
You said you wanted to:
set the position as a distance from any edge of the screen
I did that by creating an Item that fills the window, and then setting the margins from the edges of the window as some factor of the default font's implicit height. This ensures that the content within the item will be the same physical distance (e.g., in millimetres) from the edge of the window regardless of the DPI of the device you're viewing it on. If you'd rather the distance be larger if the window is larger, you can do this instead:
anchors.margins: window.width * 0.1
Font Sizes
Take a look at the Text item within the Column. If you want to ensure the text is also the same physical size on the screen, you can set font.pixelSize to be the default font's size multiplied by some amount. Again, if you'd rather base it off the size of the screen rather than the DPI, you can do this instead:
font.pixelSize: window.height * 0.05
More Information
The Scalability documentation also gives a nice overview on this topic.
Below is a screenshot of the application running:
The following works, but it's annoying -- you have to create a scaleWidth and scaleHeight function and wrap any constant coordinates in them.
Font sizes scale along the shortest edge of the screen -- this application is a Portrait-only orientation, so it uses scaleWidth(pointSize) for font sizes.
Would be nice to find a solution that's compatible with the QML designer.. is there any way to automatically insert this calculation, maybe afterwards in C++ code at runtime?
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
ApplicationWindow {
id:window
visible: true
width: 480
height: 640
function scaleWidth(w)
{
return w * (width / 480.0)
}
function scaleHeight(h)
{
return h * (height / 640.0)
}
Text {
id: defaultText
}
Image {
id: image1
x: 0
y: 0
width: window.width
height: window.height
fillMode: Image.Stretch
source: "http://cdn2.landscapehdwalls.com/wallpapers/1/perfect-green-hills-1197-1280x800.jpg"
Label {
id: lblTitle
x: 0
y: scaleHeight(8)
text: qsTr("Welcome to the App")
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: scaleWidth(36)
horizontalAlignment: Text.AlignHCenter
}
Label {
id: lblSubtitle
x: 0
text: qsTr("Login to Continue")
font.pointSize: scaleWidth(24)
anchors.top: lblTitle.bottom
anchors.topMargin: scaleHeight(8)
anchors.horizontalCenter: lblTitle.horizontalCenter
}
Item {
id: itemCenterAlign
x: 0
y: 0
width: 0
height: 200
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
id: lblUsername
x: 0
text: qsTr("Username:")
anchors.top: lblSubtitle.bottom
anchors.topMargin: scaleHeight(64)
font.bold: true
font.pointSize: scaleWidth(24)
anchors.right: itemCenterAlign.left
anchors.rightMargin: scaleWidth(8)
}
TextField {
id: txtUsername
width: scaleWidth(224)
height: scaleHeight(43)
anchors.left: itemCenterAlign.right
anchors.leftMargin: scaleWidth(8)
anchors.top: lblSubtitle.bottom
anchors.topMargin: scaleHeight(64)
font.pointSize: scaleWidth(24)
placeholderText: qsTr("Username")
}
Label {
id: lblPIN
x: 0
y: scaleWidth(-8)
text: qsTr("PIN:")
font.bold: true
font.pointSize: scaleWidth(24)
anchors.topMargin: scaleHeight(12)
anchors.right: itemCenterAlign.left
anchors.rightMargin: scaleWidth(8)
anchors.top: lblUsername.bottom
}
TextField {
id: txtPIN
x: 0
y: 0
width: scaleWidth(224)
height: scaleHeight(43)
placeholderText: qsTr("PIN")
font.pointSize: scaleWidth(24)
anchors.topMargin: scaleHeight(8)
anchors.leftMargin: scaleWidth(8)
anchors.left: itemCenterAlign.right
anchors.top: txtUsername.bottom
}
Row {
id: row1
x: 0
y: scaleHeight(277)
width: scaleWidth(464)
height: scaleHeight(115)
spacing: scaleWidth(8)
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: cmdQuit
text: qsTr("Quit")
width: row1.width / 3 - row1.spacing / 2
height: row1.height
}
Button {
id: cmdGPSOnly
text: qsTr("GPS Only")
width: row1.width / 3 - row1.spacing / 2
height: row1.height
}
Button {
id: cmdLogin
text: qsTr("Login")
width: row1.width / 3 - row1.spacing / 2
height: row1.height
}
}
Button {
id: cmdAbout
width: cmdQuit.width
height: scaleHeight(44)
text: qsTr("About")
anchors.top: row1.bottom
anchors.topMargin: scaleHeight(8)
anchors.left: row1.left
anchors.leftMargin: 0
}
Label {
id: lblVersion
y: 619
text: qsTr("v3.0.0.0")
font.pointSize: scaleWidth(16)
anchors.bottom: parent.bottom
anchors.bottomMargin: scaleHeight(8)
anchors.left: parent.left
anchors.leftMargin: scaleWidth(8)
}
Label {
id: lblBooks
x: 0
y: lvBooks.y
text: qsTr("Books Loaded:")
horizontalAlignment: Text.AlignRight
font.pointSize: scaleWidth(24)
anchors.right: lvBooks.left
anchors.rightMargin: scaleWidth(8)
}
Rectangle
{
x: lvBooks.x
y: lvBooks.y
width: lvBooks.width
height: lvBooks.height
color: "white"
border.color: "black"
}
ListView {
id: lvBooks
x: 0
y: 0
width: scaleWidth(224)
height: scaleHeight(160)
anchors.bottom: parent.bottom
anchors.bottomMargin: scaleHeight(8)
anchors.right: parent.right
anchors.rightMargin: scaleWidth(8)
model: ListModel {
ListElement {
name: "Book1"
}
ListElement {
name: "Book2"
}
}
delegate: Item {
x: 5
width: scaleWidth(80)
height: scaleHeight(40)
Row {
Text {
text: name
font.bold: true
font.pointSize: scaleWidth(24)
anchors.verticalCenter: parent.verticalCenter
}
spacing: 0
}
}
}
}
}
I have this problem. I have listview which I populate from QT code , but I want to listview to be touchable, so when I click I can actually select certain item. Now I can navigate with arrows up and down, but when I port it to Android it doesn't work. I have tried to add mouse area, but I can't make it work with listview. So that's problem no.1 and second question is about getting selected item. So when I click on certain item in list I want to read data from it.
Here is a piece of my code if you need more just let me know:
ListView {
id: listview1
x: 0
y: 82
width: 395
height: 942
visible: true
keyNavigationWraps: false
boundsBehavior: Flickable.DragAndOvershootBounds
opacity: 1
maximumFlickVelocity: 2500
anchors.leftMargin: 0
highlightMoveSpeed: 489
contentWidth: 0
preferredHighlightEnd: 2
spacing: 5
highlightRangeMode: ListView.NoHighlightRange
snapMode: ListView.SnapToItem
anchors.bottomMargin: 0
anchors.rightMargin: 179
anchors.topMargin: 82
anchors.fill: parent
model: myModel
delegate:Component {
// id: contactDelegate
Item {
property variant myData: model
width: 450; height: 90
Column {
Text { text: '<b>ID: </b> ' + id_korisnika ; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 8 }
Text { text: '<b>Ime: </b> ' + ime_korisnika ; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 8 }
Text { text: '<b>Prezime: </b> ' + prezime_korisnika; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 8 }
Text { text: '<b>Broj telefona: </b> ' + broj_korisnika ; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 8 }
Text { text: '<b>Adresa: </b> ' + adresa_korisnika ; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 8 }
}
}
}
// delegate: contactDelegate
highlight: Rectangle {color:"black"; radius: 5; opacity: 0.7 }
focus: true
}
BorderImage {
id: border_image1
x: 0
y: 0
width: 501
height: 81
source: "slike/naslov.png"
MouseArea {
id: mouse_area1
x: 0
y: 81
anchors.fill: parent
}
}
Rectangle {
id: rectangle1
x: 395
y: 82
width: 100
height: 718
gradient: Gradient {
GradientStop {
position: 0
color: "#f3eeee"
}
GradientStop {
position: 1
color: "#621717"
}
}
Image {
id: image1
x: 2
y: 314
width: 100
height: 100
source: "slike/Button-Next-icon.png"
}
}
//dodaj korisnika
Flipable {
id: flipable
x: 401
y: 98
width: 87
height: 70
property bool flipped: false
front: Image { x: 0; y: 0; width: 60; height: 58; source: "slike/dodaj_korisnika.png"; anchors.centerIn: parent }
back: Image { x: 0; y: 0; width: 60; height: 58; source: "slike/accept.png"; anchors.centerIn: parent }
transform: Rotation {
id: rotation
origin.x: flipable.width/2
origin.y: flipable.height/2
axis.x: 1; axis.y: 0; axis.z: 0 // set axis.y to 1 to rotate around y-axis
angle: 0 // the default angle
}
states: State {
name: "back"
PropertyChanges { target: rotation; angle: 180 }
when: flipable.flipped
}
transitions: Transition {
NumberAnimation { target: rotation; property: "angle"; duration: 500 }
}
MouseArea {
x: 7
y: 9
width: 73
height: 76
anchors.rightMargin: 7
anchors.leftMargin: 7
anchors.topMargin: 9
anchors.bottomMargin: 9
hoverEnabled: false
anchors.fill: parent
onClicked: {
if(Varijabla.unos_korisnika==1)
{ window.state == 'State1' ? window.state = "" : window.state = 'State1'; flipable.flipped = !flipable.flipped; Varijabla.povecaj() }
else if(Varijabla.unos_korisnika==2)
{
window.state == "" ? window.state = 'State1' : window.state = ""; flipable.flipped = !flipable.flipped; Varijabla.reset();
funkcije.dodaj_korisnika(text_input1.text,text_input2.text,text_input3.text,text_input4.text);
}
}
}
These are text variables available:
TextInput {
id: text_input1
x: 59
y: 131
width: 80
height: 20
font.pixelSize: 12
opacity: 0
}
TextInput {
id: text_input3
x: 59
y: 246
width: 80
height: 20
font.pixelSize: 12
opacity: 0
}
TextInput {
id: text_input4
x: 59
y: 305
width: 80
height: 20
font.pixelSize: 12
opacity: 0
}
TextInput {
id: text_input2
x: 59
y: 190
width: 80
height: 20
font.pixelSize
: 12
opacity: 0
}
MouseArea inside delegate should work just fine, declare a signal in your ListView and emit it from delegate/MouseArea. You can emit arbitrary data, but in most cases model index is enough:
ListView {
signal itemSelected(int index)
delegate: Rectangle {
MouseArea {
anchors.fill: parent
onClicked: itemSelected(model.index)
}
}
}