Calling QML ancestor method from descendant method of same name - qt

I am trying to improve upon the SoundEffect class included with QML. My new "MySoundEffect.qml" is show below. However, I cannot figure out how to call the identically named "play" method of the SoundEffect class from within my own method. My attempt below fails:
import QtQuick 2.0
import QtMultimedia 5.12
SoundEffect {
function play() {
console.log("Play clicked in my sound effect")
SoundEffect.play()
}
}
The obvious answer is pick a new name for my method, but I'm hoping there is a way to achieve this.

The answered linked by JarMan - answers why it's not possible as I asked. However, wrapping the ancestor class allows me too make the change transparently to rest of program:
import QtQuick 2.0
import QtMultimedia 5.12
Item {
property alias source : effect.source
property alias loops : effect.loops
property alias volume : effect.volume
property alias muted : effect.muted
SoundEffect {
id: effect
}
function play() {
effect.play()
}
}

Related

Should I add class attributes to Angular component selector tags

I'd like to add class directly to selector in Angular 5. Something like this:
<myapp-selector class="myclass"></myapp-selector>
I've been searching for a while now, and I found some solutions like using host of #Component. But I can't find a definitive answer on the concrete question.
Is it safe and is it considered a bad practice?
The best approach would be apply stlye/class inside your component as container, But you can add classes to the component as well.
I guess this depends really on what you're trying to achieve.
Simply adding a class to a component, is done by just adding it to the tag statically, just as you've already mentioned.
Adding a class conditionally can be done in multiple ways, one of which is using #HostBinding() or the component's host property
#Component({
...
})
class SomeComponent {
#HostBinding('class.someClassName') shouldAddClass: boolean;
}
Or
#Component({
host: {
'[class.active]': 'somePropertyName'
}
})
class SomeComponent {
somePropertyName: boolean;
}
Now, the active class will be added when the property is true and remove when it's false.
Another alternative is using [ngClass] directive, which essentially does the same, just that the consumer of the component decides when class are being added and removed:
<some-component [ngClass]="{ active: somePropertyThatsEitherTrueOrFalse }">

How to change the background-color of a Gtk.InfoBar to yellow?

The default background color seems to be blue (from the Adwaita theme), even if I set the type of message to Warning. I prefer using CSS.
example.py:
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
w = Gtk.Window()
ib = Gtk.InfoBar()
w.add(ib)
w.connect("delete-event", Gtk.main_quit)
provider = Gtk.CssProvider()
provider.load_from_path("style.css")
w.get_style_context()\
.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
w.show_all()
Gtk.main()
style.css:
infobar {
background-color: yellow;
}
Screenshot:
I use Python 2.7.13 and GTK+ 3.22 on Windows 10 with all the updates installed and through MSYS2 with all the updates installed with pacman -Syyu.
From the Python Gtk API:
Gtk.InfoBar has a single CSS node with name infobar. The node may get
one of the style classes .info, .warning, .error or .question,
depending on the message type.
By default, Gtk.InfoBar message type is Gtk.MessageType.INFO and your style.css file should be, eg.:
infobar.info {
background-color: yellow;
}
This way you can be more specific to the message type your are setting but infobar by itself will also work. The advantage is that you can have custom settings for each message type using infobar.<messagetype>.
EDIT:
change the widget that will receive the css class to the Gtk.InfoBar instance:
ib.get_style_context()\
.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
EDIT 2:
To add a CssProvider (StyleProvider) as a whole to the application you have the Gdk.Screen class method Gdk.Screen.add_provider_for_screen (more info here)
Changing your code to reflect these changes, you'll have:
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
w = Gtk.Window()
ib = Gtk.InfoBar()
w.add(ib)
w.connect("delete-event", Gtk.main_quit)
provider = Gtk.CssProvider()
provider.load_from_path("style.css")
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
w.show_all()
Gtk.main()

Qt Quick Controls Styles ReferenceError

I want to isolate the style of my components in a file like "ComponentStyle.qml" (Qt5)
ComponentSyle.qml
Item {
id:root
Component {
id: touchStyle
ButtonStyle {
....
}
}
Component {
id: switchStyle
SwitchStyle {
....
}
}
}
So, in my main.qml, I want to use the style like :
main.qml
...
Button {
style: touchStyle
text: "Press me"
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
}
But, it wont work ! I have some errors :
file:///C:/Qt/5.2.0/msvc2012/qml/QtQuick/Controls/Switch.qml:133: TypeError: Type error
file:///C:/Qt/5.2.0/msvc2012/qml/QtQuick/Controls/Button.qml:92: TypeError: Cannot read property 'width' of null
main.qml:60: ReferenceError: touchStyle is not defined*
Is someone can help me ? Thanks a lot !
Unfortunately I think I would have to see more of your ComponentStyle.qml but I think you're missing properties.
You should use these two links to get an overall idea of how to format you code for themes and styles.
Styling - Has great examples on styling text and buttons very applicable to your case.
QmlStyling - Lists different approaches and techniques for implementing styling.
I hope that helps.

How to both define a js function in a separate file yet attach it to a QML element

I can do this:
SomeElement{
id: something
function someFunction(){...}
....
OtherElement{
property int whatever: something.someFunction()
However, I'd like all my JS functions defined in a separate file. The problem is that this decouples the functions from being attached to any one element, as far as I can tell. I can no longer refer to a function as a property on another element to call it.
Is it possible for a function to be attached to a QML element but still have it defined in another file? Would there be some syntax to "forward" or "alias" the function from the element so one could still call this "member function" on the element, and thus this function could be able to access other properties on its parent element?
You can try to import js file as some module and use its function with module name prefix. So, they will be in separate 'namespace' from you QML object's functions
Documentation about it: http://qt-project.org/doc/qt-5.0/qtqml/qtqml-javascript-imports.html
Is it possible for a function to be attached to a QML element but
still have it defined in another file? Would there be some syntax to
"forward" or "alias" the function from the element so one could still
call this "member function" on the element, and thus this function
could be able to access other properties on its parent element?
Not directly, but easily fake-able:
// foo.js
function printDimensions(item) {
console.log(item.width, "x", item.height)
}
// in qml
import "foo.js" as Foo
// ..
Item {
id: someItem
function printDimensions() { Foo.printDimensions(someItem) }
}
// ..
Rectangle {
id: anotherItem
function printDimensions() { Foo.printDimensions(anotherItem) }
}
This way you can attach the function to different objects via a simple wrapper.

CSS styles are not applied to elements added to JavaFX component tree

I have applied CSS style to JavaFX components and it looks like everything is working fine except one situation: when I add JavaFX components to component tree on-the-fly their CSS styles are not applied.
For example following code:
package test;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.MouseEvent;
import javafx.util.Math;
import javafx.scene.paint.Color;
function getRect(): Rectangle {
return Rectangle {
x: 230 * Math.random()
y: 60 * Math.random()
width: 20, height: 20
styleClass: "abc"
}
}
def stage: Stage = Stage {
scene: Scene {
width: 250, height: 80
stylesheets: "{__DIR__}main.css"
content: [
Rectangle {
x: 0, y: 0, width: 250, height: 80
fill: Color.WHITE
onMouseClicked: function (evt: MouseEvent): Void {
insert getRect() into stage.scene.content;
}
}
getRect()
]
}
}
with following stylesheet:
.abc {
fill: red;
}
in main.css file (both in test package) display red square on white background, but after clicking the main rectangle black (not red) squares are added to scene.
I noticed that:
Components added dynamically look just like style information was not applied.
If you set their style in JavaFX code then everything works fine.
After changing stylesheets property (so that it points to another valid stylesheet) the objects already added render properly.
Does anyone know the solution to this problem? I could of course put all the properties into JavaFX code or provide another stylesheet (for every existing stylesheed) that would contain the same data and change stylesheet right after adding any component, but I would like to find some elegant solution.
Thanks in advance.
It's a bug in 1.2. It is fixed in the next release.

Resources