About JavaFx Layout - layout

I have a question about javafx layout, following is my code you can run the code directly:
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.control.TextBox;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
* #author Administrator
*/
var headerHeight: Number = 50;
var header: Group = Group {
var searchBox: HBox;
content: [
Rectangle {
width: bind scene.width;
height: bind headerHeight;
fill: Color.BLUE
},
searchBox = HBox {
spacing: 10
layoutY: bind (headerHeight - searchBox.layoutBounds.height) / 2;
layoutX: bind scene.width - searchBox.layoutBounds.width - 20;
var textBox: TextBox;
content: [
textBox = TextBox {
promptText: "please input search key"
columns: 20
selectOnFocus: true
}, Button {
text: "search"
strong: true
action: function() {
println("Button clicked");
}
}]
}
]
}
var rect = Rectangle {
width: bind 400;
height: bind 80;
fill: Color.YELLOW
}
var footerHeight: Number = 50;
var footer: Group = Group {
var bounds: Rectangle;
content: [
bounds = Rectangle {
width: bind scene.width;
height: bind footerHeight;
fill: Color.RED
}
]
}
var scene: Scene = Scene {
content: [
VBox {
content: [
header,
rect,
footer
]
}
]
}
function run() {
Stage {
scene: scene
}
}
The scene's height is not normal. Footer's height is 50, but seems only about 30.
what's wrong, any advise?
Thanks.

For some reason the Scene isn't resizing to fit the full contents. I'm not sure why, but you may be able to work around this by setting scene.height = headerHeight + 80 + footerHeight.

Try binding to the Stage instead of Scene.

Related

When I scale an image (by modifying the matrix in the parent scene(normal Item)), I only get an image with moire in QML

original image↑
what I get in qml
what I want to get
I have tried layout's smooth and mipmap but can not achieve the effect, and the difference between nearest and linear does not help at all.
Hmm, how about sampling the image at different resolutions?
Below I am fitting your image into a 400x200 box, but, I resampling the image by setting sourceSize so that it gets resampled at different resolutions.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
ListView {
width: 420
height: parent.height
model: ListModel {
ListElement { w:200; h:100 }
ListElement { w:400; h:200 }
ListElement { w:600; h:300 }
ListElement { w:800; h:400 }
}
delegate: ColumnLayout {
Label { text: w + " x " + h }
Image {
source: "https://www.arcgis.com/sharing/rest/content/items/98dd74d1f18e4dfba334ecea0b371307/data"
fillMode: Image.PreserveAspectFit
Layout.preferredWidth: 400
Layout.preferredHeight: 200
sourceSize: Qt.size(w, h )
}
}
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
}
}
You can Try it Online!

how to set QTreeView background image with QStyle::StandardPixmap in stylesheet method?

i need to change QTreeView background image use QStyle::StandardPixmap with QT stylesheet , i try some method, but it don't work?
The stylesheet look like this, but it not working
QTreeView::branch:closed:adjoins-item {
border-image: url(QStyle::SP_ArrowBack);
}
I suggest quickly uploading QStyle.SP_ArrowBack to the file SP_ArrowBack.png , and then using it in the stylesheet.
import sys
from PyQt5.QtWidgets import QTreeView, QFileSystemModel, QApplication, QStyle
from PyQt5.QtCore import QDir
from PyQt5.QtGui import QIcon
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
self.setWindowIcon(self.style().standardIcon(QStyle.SP_ArrowBack))
### vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
icon = self.style().standardIcon(QStyle.SP_ArrowBack)
pixmap = icon.pixmap(200, 200, QIcon.Normal, QIcon.On)
_icon = "{}.png".format("SP_ArrowBack")
pixmap.save(_icon, quality = -1)
print("Icon loaded ...")
self.setStyleSheet("""
QTreeWidget {border:None;}
QTreeWidget::item { height: 80px;
color: rgba(255,255,255,255);
}
QTreeView {
alternate-background-color: rgba(135,135,135,255);
background: rgba(145,145,145,255);
}
QTreeView::branch:has-siblings:!adjoins-item {
border-image: url(vline.png) 0;
}
QTreeView::branch:has-siblings:adjoins-item {
border-image: url(branch-more.png) 0;
}
QTreeView::branch:!has-children:!has-siblings:adjoins-item {
border-image: url(branch-end.png) 0;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
border-image: none;
image: url(%s); /* <--- _icon */
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings {
border-image: none;
image: url(branch-open.png);
}
QTreeWidget::item[text="Header1"] {
height: 80px;
}
QTreeWidget::item:children {
height: 40px;
}
""" % _icon)
### ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
model = QFileSystemModel()
model.setRootPath(QDir.currentPath())
self.setModel(model)
self.setRootIndex(model.index(QDir.currentPath()))
model.setReadOnly(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Tree()
w.resize(500, 300)
w.show()
sys.exit(app.exec_())

How to connect PyQt5 pyqtSlot to QML ListView signal "activated"?

I would like to connect the activated signal from a QML ListView to a pyqtSlot decorated method from my Python3/PyQt5 (5.6) code.
My current approach is to load the QML scene in my code through QQmlApplicationEngine and then use findChild() to get a reference to my ListView.
The problem is, that I can only find the ListView when searching for a QObject like findChild(QObject, 'myList'). But htis object does not give me access to the activated signal, most likely because this signal is only defined for QAbstractItemView and it descendants.
So if I try findChild(QListView, 'myList') the result is None. Therefor I'm not able to get to the activated signal. Is this a bug in PyQt5 or is there another way for me to connect to this signal?
Here is some minimal working example.
list.py:
import sys
from OpenGL import GL
from PyQt5.QtCore import QUrl, QObject
from PyQt5.QtWidgets import QApplication, QListView
from PyQt5.QtQml import QQmlApplicationEngine
# Main Function
if __name__ == '__main__':
# Create main app
app = QApplication(sys.argv)
# Create QML engine
engine = QQmlApplicationEngine(app)
# Load the QML scene from file
engine.load(QUrl('List.qml'))
for root in engine.rootObjects():
node = root.findChild(QListView, 'myList')
if node:
# At this point I would like to connect something to the
# node.activated signal
print(node)
# Execute the application and exit
sys.exit(app.exec_())
List.qml:
import QtQuick 2.0
import QtQuick.Window 2.2
Window {
visibility: Window.FullScreen
visible: true
ListView {
objectName: "myList"
anchors.fill: parent
delegate: Item {
width: parent.width * 0.8
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
}
Text {
text: name
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
spacing: 10
}
}
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
}
}
You can do that by using QQuickView instead of QQmlApplicationEngine.
I changed your python script to add a new class which inherits from QQuickView, and added a signal to the QML object named "myList".
Moreover, into the QML I removed the Window type for Item type (you can't use Window with QQuickView). If you want to display your application in full screen, you'll have to specify it into MyView class.
In the example, if you click on one of the colored rectangles, the index will be displayed in the console.
list.py:
import sys
from PyQt5.QtCore import QUrl, QObject
from PyQt5.QtWidgets import QApplication, QListView
from PyQt5.QtQuick import QQuickView, QQuickItem
class MyView(QQuickView):
def __init__(self, parent=None):
super().__init__(parent)
# Load the QML scene from file
self.setSource(QUrl('List.qml'))
#connect signal and source
list = self.rootObject().findChild(QQuickItem, 'myList')
list.mySignal.connect(self.mySlot)
def mySlot(self, index):
print(index)
# Main Function
if __name__ == '__main__':
# Create main app
app = QApplication(sys.argv)
# Create QML view
view = MyView()
view.show()
# Execute the application and exit
sys.exit(app.exec_())
List.qml:
import QtQuick 2.0
import QtQuick.Window 2.2
Item {
width: 500
height: 500
ListView {
anchors.fill: parent
id: list
objectName: "myList"
signal mySignal(int index)
delegate: Item {
width: parent.width * 0.8
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
MouseArea{
anchors.fill: parent
onClicked: list.mySignal(index)
}
}
Text {
text: name
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
spacing: 10
}
}
model: ListModel {
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
}
}

QtQuick 2 - Make custom palette object and throw it as property to another custom widget (for assigning color properties)

I trying to make custom button and few other elements styled as KDE 5 'Breeze' theme. I considered to make separated palette object (called BreezePalette.qml that contains a lot of readonly color properties) for all of this widgets (because I do not want them to be styled in any other way, that's thy they called Breeze). The main concept is to make palette as property of widgets and create one palette in main.qml where I can change property theme to light or dark. It looks to me rational, because I planning only include all subset of .qml files into project, without any other additional files to Qt itself (that making it portable and easy to deploy). Here is that I have, can someone let me know how can I forward palete as a property?
main.qml
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.1
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
menuBar: MenuBar{
Menu{
title: "File"
MenuItem{
text: "Exit"
onTriggered: Qt.quit()
}
}
}
BreezeButton{
x: 106
y: 82
palette: brPalette
onClicked: {
Qt.quit()
}
caption: "Button"
}
BreezePalette{
id: brPalette
theme: "light"
}
}
BreezePalette.qml
import QtQuick 2.2
QtObject {
id: palette
property string theme: "light"
readonly property color base: if (theme == "light"){
"#eff0f1"
} else if (theme == "dark"){
"#31363b"
}
readonly property color focus: "#3daee9"
readonly property color buttonText: if (theme == "light"){
"#31363b"
} else if (theme == "dark"){
"#eff0f1"
}
}
BreezeButton.qml
import QtQuick 2.2
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
Item {
id: root
implicitHeight: bodyText.font.pixelSize + 32
implicitWidth: bodyText.width + 32
property string caption: "Button"
property string iconSource
property int fontSize: 18
//I've tried to throw BreezePalette as a property to BreezeButton, but looks like my skills ended there (I have no any experience with js or qml before. I started learn it only few weeks)
property BreezePalette palette
signal clicked
Rectangle {
id: body
border {
width: 1
color: "#808e8e"
}
anchors{
fill: parent
}
gradient: Gradient {
id: bodyGradient
GradientStop { position: 0.4; color: "#4c4c4c" }
GradientStop { position: 0.9; color: "#31363b" }
}
MouseArea{
id: bodyMouseArea
z: bodyText.z + 1
anchors {
fill: parent
}
hoverEnabled: true
onEntered: {
body.border.color = "#3daee9"
}
onExited: {
body.border.color = "#7f8c8d"
}
onPressed: {
body.color = "#3daee9" // this one works, but I need to switching theme as you can see n `BreezePalette.qml`
//This one not working as expected, but seeing my properties as I need
//body.color = palette.focus
body.gradient = null
}
onReleased: {
body.color = "#4d4d4d"
body.gradient = bodyGradient
}
onClicked: {
root.clicked()
}
}
Text {
id: bodyText
anchors {
verticalCenter: body.verticalCenter
horizontalCenter: body.horizontalCenter
}
font.pointSize: fontSize
color: "#fcfcfc"
text: caption
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
}
Since stackexchange designed for sharing knowledge (or maybe even for ask for something you don't know well) I see it's rational to post it there because I need knowledge of experts. If you have any other point of view regarding this question I'll be glad to hear that. Appreciated any help.
Thanks
Svyatoslav
UPDATE:
Just found an answer, this code snippet working as well
property BreezePalette palette: BreezePalette
So, my second answer is - is that good to user this method? It's provide me thing I need, exactly as was expected.
Quite a late answer, but there is a module to have breeze theme.
qml-module-qtquick-controls-styles-breeze

QML toggle PropertyChanges onclick

I try to toggle my navigation with a toggle function. I want to change "x" position.
So here is what i got so far. But don't work. I try to use a toggle function to chnage state on click. I set two different state one that the navigation is visible and one that the navigation is hidden.
I get this error "ReferenceError: toggle is not defined"
Item {
id: toggleswitch
width: 200
height: 200
property bool on: false
function toggle() {
if (toggleswitch.state == "on")
toggleswitch.state = "off";
else
toggleswitch.state = "on";
}
Rectangle {
id: open
width: parent.width
height: 35
color: "#33000000"
Text {
anchors.centerIn: parent
text: "open"
color: "white"
font.family: "Helvetica"
font.pixelSize: 25
}
MouseArea { anchors.fill: parent; onClicked: toggle() }
}
states: [
State {
name: "on"
PropertyChanges { target: navigation; x: 0 }
PropertyChanges { target: toggleswitch; on: true }
},
State {
name: "off"
PropertyChanges { target: navigation; x: -300 }
PropertyChanges { target: toggleswitch; on: false }
}
]
}
Some small slider example:
import QtQuick 2.2
Rectangle {
width: 360
height: 360
Rectangle {
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
}
id: slider
state: "close"
states: [
State {
name: "close"
PropertyChanges {
target: slider
width: 50
}
},
State {
name: "open"
PropertyChanges {
target: slider
width: 360
}
}
]
transitions: [
Transition {
NumberAnimation {
target: slider
property: "width"
duration: 500
easing.type: Easing.InOutBack
}
}
]
color: "green"
}
MouseArea {
anchors.fill: parent
onClicked: {
if (slider.state == "close")
slider.state = "open";
else
slider.state = "close";
}
}
}
transitions is optional here
You can say to QML which object is your function.
Item {
id: toggleswitch
width: 200
height: 200
state: "off" //INIT YOUR STATE !!
property bool on: false
function toggle() {
if (toggleswitch.state == "on")
toggleswitch.state = "off";
else
toggleswitch.state = "on";
}
Rectangle {
id: open
width: parent.width
height: 35
color: "#33000000"
Text {
anchors.centerIn: parent
text: "open"
color: "white"
font.family: "Helvetica"
font.pixelSize: 25
}
MouseArea { anchors.fill: parent; onClicked: toggleswitch.toggle() } //here
}
states: [
State {
name: "on"
PropertyChanges { target: navigation; x: 0 }
PropertyChanges { target: toggleswitch; on: true }
},
State {
name: "off"
PropertyChanges { target: navigation; x: -300 }
PropertyChanges { target: toggleswitch; on: false }
}
]
What I would do here is not manipulate the state directly but toggle on the property directly, and bind the states to that property.
To me it feels more readable, semantical and reduce the coupling between the object and its visual states.
This also has the advantage of having states always coherent with the on property and provides a better abstraction. When using this component you can freely change the on property programmatically and the component display will update accordingly.
That's what I would probably end up with :
Item {
id: toggleswitch
width: 200
height: 200
property bool on: false
function toggle() {
on = !on //simpler toggle function
}
Rectangle {
id: open
width: parent.width
height: 35
color: "#33000000"
Text {
anchors.centerIn: parent
text: "open"
color: "white"
font.family: "Helvetica"
font.pixelSize: 25
}
MouseArea { anchors.fill: parent; onClicked: toggleswitch.toggle() }
}
states: [
State {
name: "on"
when: toggleswith.on
PropertyChanges { target: navigation; x: 0 }
},
State {
name: "off"
when: !toggleswith.on
PropertyChanges { target: navigation; x: -300 }
}
]

Resources