How to make visible both icon and text on QML ToolButton - qt

I am creating desktop application using QML and QtQuick.Components. I want to place on the toolbar buttons like the standard MacOS settings dialogs do:
I use ToolBar and ToolButton, but I can't find the way to do it. For instance with the following code it shows icons only:
ApplicationWindow {
// ...
toolBar: ToolBar {
RowLayout {
ToolButton {
text: qsTr("Main")
iconSource: "main.png"
}
ToolButton {
text: qsTr("System")
iconSource: "system.png"
}
ToolButton {
text: qsTr("Items Book")
iconSource: "itemsbook.png"
}
}
}
}
And it seems like ToolButton can show either text or icon:
Text {
id: textitem
text: button.text
anchors.centerIn: parent
visible: button.iconSource == "" // <=========
}

A simple yet a powerful approach is to create own QML component.
Create a custom QML component / file:
File -> New File or Project -> Qt -> QML File (choose latest version).
Now enter file name, for example MyToolButton.
Note that it will be also used as
component name.
Add there neccesary imports and code:
MyToolButton.qml (customize for your needs)
import QtQuick 2.0
import QtQuick.Controls 1.4
ToolButton
{
Image {
source: parent.iconSource
fillMode: Image.PreserveAspectFit // For not stretching image (optional)
anchors.fill: parent
anchors.margins: 2 // Leaving space between image and borders (optional)
anchors.bottomMargin:10 // Leaving space for text in bottom
}
Text {
text: parent.text
anchors.bottom: parent.bottom // Placing text in bottom
anchors.margins: 2 // Leaving space between text and borders (optional)
anchors.horizontalCenter: parent.horizontalCenter // Centering text
renderType: Text.NativeRendering // Rendering type (optional)
}
}
Main.QML (where you want to use it):
import QtQuick 2.0
import QtQuick.Controls 1.4
// Usual toolbar declaration
ToolBar {
id: mainToolBar
RowLayout {
// Create MyToolButton. Note that component name (MyToolButton) is the same as file name.
MyToolButton {
id:tbQuit
// Way 1: Add here any icon
iconSource: "qrc:///images/quit.png"
text:qsTr("&Quit")
// Way 2, my favourite: Convert your Action into Button!
action: actQuit
}
}
}
Action {
id: actQuit
text: qsTr("&Quit")
onTriggered: Qt.quit()
shortcut: "Alt+Q"
iconSource: "qrc:///Images/Exit.png"
}
Notes:
It requires QtQuick.Controls 1.4 and should work on Qt 5.2+. (Worked fine on Qt 5.5).
Don't forget to add imports.
Code parts marked as (optional) can be skipped.
Replace ToolButton with Button and it will work as a Button.
Hope it helps!

Have you try to add your own Text control like this:
ApplicationWindow {
// ...
toolBar: ToolBar {
RowLayout {
ToolButton {
text: qsTr("Main")
iconSource: "main.png"
Text {
text: parent.text
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
ToolButton {
text: qsTr("System")
iconSource: "system.png"
Text {
text: parent.text
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
ToolButton {
text: qsTr("Items Book")
iconSource: "itemsbook.png"
Text {
text: parent.text
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
And set the ToolButton height with the right value (image + text height)

Related

Material Style In Qml Does Not Load Colors

i used methods here to use material design in my QtQuick project and used Accent and Themes from here controls loading in material style correctly in normal qml files , but in qml files loaded by loader result is like this:
this loader is in main.qml :
Loader{
id:myLoader
anchors.fill: parent
source: "LoginPage.qml"
}
and here is my dynamic qml file
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.3
import QtGraphicalEffects 1.0
Rectangle{
Material.theme: Material.Dark
Material.accent: Material.Teal
property string error_msg: ""
id: loginPage
Button {
id: button
width: 80
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 0
font.family: "B Nazanin"
enabled: webView.loadProgress == 100 ? true:false
KeyNavigation.tab: button1
Material.accent: Material.Orange
onClicked: {
login()
}
}
}
The dark there is presumed to have a dark background. It will not set your window background for you, it only affects GUI controls. And the button in particular doesn't use use the accent color, just the foreground color, unless toggle is enabled, in which case it will use the accent color to signify that.
Material.theme: Material.Dark
Material.accent: Material.Teal
Rectangle {
anchors.fill: r2
color: "#262626"
}
Row {
id: r1
Button {
text: "test"
checkable: true
Material.accent: Material.Orange
}
Button {
text: "test"
checkable: true
}
}
Rectangle {
anchors.fill: r2
}
Row {
id: r2
anchors.top: r1.bottom
Button {
text: "test"
checkable: true
Material.accent: Material.Orange
}
Button {
text: "test"
checkable: true
}
}
As you see, on a white background, the dark theme button looks blurry and washed out. If you want to set the button color, that would be the Material.background whereas the text would be Material.foreground.
I had a similar problem.
Just use ApplicationWindow as your root element and it will work.
And additionally you have to load Material before instantiating QML.
QGuiApplication application(argc, argv);
QQmlApplicationEngine engine;
QQuickStyle::setStyle("Material");

get cursor position in WebEngineView qml

I have a program in Qt and a WebEngineView in it .I want to when my user clicked on a inputbox in webEngine a keyboard have been loaded and the inputbox get its contents from my keyboard (i wrote my own keyboard) but i can't do it .i try codes in bellow but don't work
WebEngineView {
anchors.fill:parent
id:webEng
url: "https://example.com"
visible: true
MouseArea {
id : mousearea
anchors.fill: parent
onClicked: {
mykeyboard.visible=true;
}
}
}
This is not a complete answer but this code could help:
import QtQuick 2.10
import QtWebView 1.1
import QtQuick.Controls 1.4
import QtWebEngine 1.7
Item {
width: 1280
height: 720
WebView { // or WebEngineView {
id: webview
width: 1280
height: 720
url: "http://google.com"
visible: true
onLoadingChanged: {
if (loadRequest.status === WebView.LoadSucceededStatus) {
console.log("Loaded!!")
webview.runJavaScript('
var input = document.getElementById("lst-ib");
input.addEventListener("click", function() {
alert("Clicked!");
});
'
)
}
}
}
Rectangle {
id: myDummyKeyboard
anchors.bottom: parent.bottom
width: parent.width
height: 100
color: "gray"
visible: true
border.width: 20
Button {
anchors.centerIn: parent
text: "Dummy"
onClicked: {
webview.runJavaScript('document.getElementById("lst-ib").value += "' + text + '"');
}
}
}
}
The part in the WebView (or WebEnginView) allows to display an alert when the input is clicked. But, something is missing, to link it to a QML handler. The solution is maybe to use WebChannel or maybe WebEngineScript as said by #folibis in the comments.
The part defined by myDummyKeyboard allows to add a string into the input when the user is clicking the button in the rectangle (fake keyboard).

How should I start QML files?

I have 4 QML files: MainMenu.qml, AppArea.qml, Result.qml and main.qml.
When my app starts, I want to see first page as MainMenu.qml fullscreen. There is a button (on MainMenu.qml) to start AppArea.qml. When I click the the button, I want to start AppArea.qml as fullscreen new window.
There is a button (on AppArea.qml), when I click that button, I want to show Result.qml but I want to see Result.qml on AppArea.qml, I mean when Result.qml come outs, AppArea.qml will not disappear but Result.qml will appear on AppArea.qml.
There is a button on Result.qml. When I click the button, the Repeater in AppArea.qml will regenerate, because maybe model of Repeater changing like 1, 2, 3, 4.... There is a button on AppArea.qml, when I click the button, I want to open MainMenu.qml as a fullscreen new window like AppArea.qml.
Actually you can think basic: My app is a game like this:
How way should I choose for these jobs?
In addition to the mentioned post, in your case you are using the component from qml file, so you need to load the component first, your main.qml can be like this:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
id: mainWindow
title: "Main window"
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: mainMenuLoader
}
Component.onCompleted: {
mainMenuLoader.source="mainMenu.qml"
var mainMenu = mainMenuLoader.item.createObject(mainWindow);
mainWindow.hide()
}
}
and your mainMenu.qml can look like this:
import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Controls 2.2
Component {
id: mainMenu
Window {
id:mmenu
title: "Main Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: appAreaLoader
}
Text {
text: "This is mainMenu"
}
Button{
id: loadAppArea
anchors.centerIn: parent
text: "Start Game"
onClicked: {
appAreaLoader.source="appArea.qml"
var appArea = appAreaLoader.item.createObject(mainMenu);
hide()
}
}
}
}
you will need to do the same for successive windows ...etc.
While for result, you need to use a MouseArea:
appArea.qml:
Component {
id: appMenu
Window {
id:appMenuWindow
title: "App Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id:anotherLoader
visible: true
anchors.left: appMenuText.left
anchors.top: appMenuText.bottom
width: parent.width/3
height: parent.height/3
}
Text {
id: appMenuText
text: "This is App Area"
anchors.centerIn: parent
}
Button{
id: loadResult
text: "Show Result"
onClicked: {
anotherLoader.source = "result.qml"
anotherLoader.visible=true
}
}
Button{
anchors.right: parent.right
id: loadMainMenu
text: "Open main Menu"
onClicked: {
hide()
//mmenu.show()
anotherLoader.setSource("main.qml")
}
}
}
}
result.qml:
Rectangle{
color: "green"
Text {
anchors.centerIn: parent
id: resultxt
text: qsTr("This is result, Click to close")
}
MouseArea {
anchors.fill: parent
onClicked: { anotherLoader.visible = false
}
}
}

How to implement swipeview QtQuick 2.5

I have QT 5.5 and it won't support SwipeView. I tried doing with listView but I am not getting what I expected. I want a similar functionality code in QT 5.5 like the code given below which is written in QT 5.6. Please help
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Window 2.0
Window {
visible: true
width: 200
height: 400
title: qsTr("Hello World")
id: page
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: 0
Page {
Label {
text: qsTr("First page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Second page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Third page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fourth page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fifth page")
anchors.centerIn: parent
}
}
}
Rectangle
{
id:minus
width:parent.width/2
height:100
anchors.left:parent.left
anchors.bottom:parent.bottom
color:"red"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex>0)
swipeView.currentIndex--
}
}
}
Rectangle
{
id:plus
width:parent.width/2
height:100
anchors.right:parent.right
anchors.bottom:parent.bottom
color:"green"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex<4)
swipeView.currentIndex++
}
}
}
}
If you cannot update your Qt version, you can indeed approximate a SwipeView using a ListView, a VisualItemModel, and a default qml property.
SwipeView.qml
ListView
{
id: root
// Allow to add pages as you would for a QtQuick.Controls 2 SwipeView
// Each item you declare in your SwipeView will be reparented to itemModel
default property alias items: itemModel.children
// SwipeView is horizontal
orientation: Qt.Horizontal
// Hide out of bounds pages
clip: true
// Do not stop between two pages
snapMode: ListView.SnapToItem
// Update currentIndex as you swipe through the pages
highlightRangeMode: ListView.StrictlyEnforceRange
model: VisualItemModel {
id: itemModel
// Used to bind the pages size to the swipeView size
onChildrenChanged: {
for(var i=0;i<children.length; i++)
{
children[i].width = Qt.binding(function(){return root.width})
children[i].height = Qt.binding(function(){return root.height})
}
}
}
}
Page.qml
Item {
property string title
Rectangle
{
anchors.fill: parent
border.width: 1
}
Text
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 20
text: title
}
}
PageIndicator.qml
Row
{
id: root
property int count
property int currentIndex
property Component delegate: bullet
property bool interactive
spacing: 5
Component
{
id: bullet
Rectangle
{
height: 10
width: height
radius: height/2
color:"black"
opacity: currentIndex==index?0.8:0.2
}
}
Repeater
{
model: root.count
Loader
{
property int index: model.index
sourceComponent: delegate
}
}
}
main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
ApplicationWindow
{
id: window
visible: true
width: 300
height: 300
SwipeView
{
id: swipeView
anchors.fill: parent
Page
{
title: "Page 1"
}
Page
{
title: "Page 2"
}
Page
{
title: "Page 3"
}
}
PageIndicator
{
id: pageIndicator
anchors.bottom: swipeView.bottom
anchors.bottomMargin: 10
anchors.horizontalCenter: swipeView.horizontalCenter
count: swipeView.count
currentIndex: swipeView.currentIndex
}
}
Qt Quick Controls 2 was introduced in Qt 5.7:
Qt Quick Controls 2 provides a set of controls that can be used to build complete interfaces in Qt Quick. The module was introduced in Qt 5.7.
Qt Labs Controls was introduced in Qt 5.6, so the code that you referenced would have to use the Qt.labs.controls 1.0 import in order to run with Qt 5.6.
You need to use a newer Qt version (5.6 or newer).

How to change the page to the next or previous item of a SwipeView by clicking on the right and left arrow respectively?

I have a SwipeView that loads its internal elements through a Repeater and a Loader.
I would like to swipe between the items forward and backward by just clicking the arrows on the right and left of the SwipeView.
How can I implement this behavior in QML?
SwipeView {
id: __swipeView
Layout.fillHeight: true
Layout.fillWidth: true
Repeater {
model: 3
Loader {
source: "qrc:/../SwipeDelegate.qml"
}
}
}
Within your delegate, you can access the SwipeView via the SwipeView attached property, and then increment or decrement the current index as necessary:
import QtQuick 2.6
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
SwipeView {
anchors.fill: parent
Repeater {
model: 3
Item {
id: delegate
Button {
text: "<"
enabled: index > 0
onClicked: delegate.SwipeView.view.decrementCurrentIndex()
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
Label {
text: "Page " + (index + 1)
anchors.centerIn: parent
}
Button {
text: ">"
enabled: index < delegate.SwipeView.view.count - 1
onClicked: delegate.SwipeView.view.incrementCurrentIndex()
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
It's important to use the functions as opposed to setting currentIndex directly, for the reasons described here.

Resources