我正在开发一个用于信号生成设备的GUI应用程序,它将支持多个通道,类似于控制台混频器的信道样式。在菜单栏中,用户应该能够在三种类型的信号之间配置通道的使用。每种类型都将在主窗口的不同选项卡中包含各个通道的和。"Configuration.qml"包含信号处理程序,"TabArea.qml"包含javascript函数create_PWM(countPWM).。
简而言之,我的mainWindow由组件设备、MenuBar、工具和TabArea组成。在MenuBar内部,我在名称配置下动态创建一个对话框组件。存在一个从tableModel检索默认信息的表。用户可以修改模型,当单击Save按钮时,考虑到模型数据,我希望在相应的选项卡上描述通道。
\\MainWindow.qml
Item {
id: mainWindow
width: 1200
height: 800
Rectangle {
id: background
color: "#d7dfda"
anchors.fill: parent
MenuBar {
id: menuBar
anchors {
left: parent.left
top: parent.top
}
height: 40
}
Tools {
id: toolBar
y: menuBar.height
height: implicitHeight
anchors {
left: parent.left
right: parent.right
top: menuBar.bottom
bottom: devices.top
}
channelsPWM: tabs.channelsPWM
channelsFrequency: tabs.channelsFrequency
}
Devices {
id: devices
anchors {
// top: menuBar.down
top: toolBar.bottom
left: parent.left
right: tabs.left
}
height: 3 * parent.height / 8
// y: menuBar.height
y: toolBar.height
}
TabArea {
id: tabs
// y: menuBar.height
y: toolBar.height
x: parent.width / 8
anchors {
// top: menuBar.bottom
top: toolBar.bottom
}
width: 3 * parent.width / 4
height: 3 * parent.height / 4
}
}
}
\\MenuBar.qml
Item {
id: menuToolBar
Button {
id: fileButton
text: "File"
anchors.left: parent.left
anchors.top: parent.top
height: 40
onClicked: fileMenu.open()
onHoveredChanged: hovered? fileButton.font.bold = true : fileButton.font.bold = false
Menu {
id: fileMenu
y: parent.height
MenuItem {
text: "New Project Ctrl+N"
onTriggered: newDialog.open()
}
MenuItem {
text: "Open Project Ctrl+O"
onTriggered: openDialog.open()
}
}
}
Button {
id: editButton
y: 0
text: "Edit"
anchors.left: fileButton.right
anchors.leftMargin: 0
anchors.top: parent.top
height: fileButton.height
onHoveredChanged: hovered? editButton.font.bold = true : editButton.font.bold = false
onClicked: editMenu.open()
Menu {
id: editMenu
y: parent.height
MenuItem {
text: "Undo Ctrl+Z"
}
MenuItem {
text: "Cut Ctrl+X"
}
MenuItem {
text: "Copy Ctrl+C"
}
MenuItem {
text: "Paste Ctrl+V"
}
}
}
Button {
id: configurationButton
text: "Configuration"
anchors.left: editButton.right
anchors.top: parent.top
height: editButton.height
onHoveredChanged: hovered? configurationButton.font.bold = true : configurationButton.font.bold = false
onClicked: {
var component = Qt.createComponent("Configuration.qml");
if( component.status !== Component.Ready )
{
if( component.status === Component.Error )
console.debug("Error:"+ component.errorString() );
return; // or maybe throw
}
var dialog =component.createObject(configurationButton);
dialog.channelConfigDialog.open();
}
}
Button {
id: helpButton
y: 0
text: "Help"
anchors.left: configurationButton.right
anchors.leftMargin: 0
anchors.top: parent.top
height: fileButton.height
onHoveredChanged: hovered? helpButton.font.bold = true : helpButton.font.bold = false
onClicked: helpMenu.open()
Menu {
id: helpMenu
y: parent.height
MenuItem {
text: "Contents"
}
MenuItem {
text: "Index"
}
MenuItem {
text: "Context Help F1"
}
}
}
/**
More Buttons for Menu implementation can be added here
**/
FileDialog {
id: openDialog
title: "Please choose a Project."
/**
The backend behavior needs to be added here in order to determine
what the application's actions will be for the selected files etc.
e.g. onAccepted: {}
onRejected: {}
**/
}}
\\Configuration.qml
Item{
property alias channelConfigDialog: channelConfigDialog
Dialog {
id: channelConfigDialog
modality: Qt.WindowModal
title: "Channel Configuration."
height: 500
width: 500
standardButtons: Dialog.Save | Dialog.Cancel
property int totalChannels: 30
ListModel {
id: tableModel
Component.onCompleted: {
for (var i=0;i<channelConfigDialog.totalChannels;i++){
append({"name": "Channel"+(i+1), "use": "PWM", "data": "Raw", "conversion": ""});
}
}
}
Component {
id: usageComboDel
Item{
anchors.fill: parent
ComboBox {
id: usageCombo
model:
ListModel{
id: usageModel
ListElement {
text: "PWM"
}
ListElement {
text: "Frequency"
}
ListElement {
text: "BLDC"
}
}
currentIndex: 0
height: 16
anchors.fill: parent
onCurrentTextChanged: {
tableModel.setProperty(styleData.row,"use",currentText);
}
}
Component{
id: dataTypeComboDel
Item{
id: itemDataTypeComboDel
anchors.fill: parent
ComboBox {
id: dataTypeCombo
model: ["Raw", "Phys"]
currentIndex: 0
height: 16
anchors.fill: parent
onCurrentTextChanged: {
tableModel.setProperty(styleData.row,"data",currentText);
sample()
}
}
function sample(){
for (var i=0;i<tableConfig.rowCount;i++){
var temp = tableModel.get(i).name;
console.log(temp);
console.log(tableModel.get(i).use + ", " + tableModel.get(i).data);
}
}
}
}
Component{
id: conversionRuleComboDel
Item{
id: itemConversionRuleComboDel
anchors.fill: parent
ComboBox {
id: conversionRuleCombo
model: ["","Linear", "Ranges", "Quadtratic", "Logarithmic", "Mathematical function"]
currentIndex: -1
height: 16
anchors.fill: parent
onCurrentTextChanged: {
tableModel.setProperty(styleData.row,"conversion",currentText);
}
}
}
}
TableView {
id: tableConfig
model: tableModel
anchors.fill: parent
TableViewColumn{
role: "name"
title: "Channels"
width: tableConfig.width/ tableConfig.columnCount
}
TableViewColumn{
id: usageCol
property alias delagata: usageComboDel
title: "Usage"
delegate: usageComboDel
width: tableConfig.width/tableConfig.columnCount
}
TableViewColumn{
title: "Data Type"
delegate: dataTypeComboDel
width: tableConfig.width/tableConfig.columnCount
}
TableViewColumn{
id: conversionRuleClmn
title: "Coversion Rule"
delegate: conversionRuleComboDel
width: tableConfig.width/tableConfig.columnCount
}
}
onAccepted: {
var countPWM = 0;
var countFrequency = 0;
for (var i=0; i<tableModel.count; i++){
if ( tableModel.get(i).use === "PWM" ){
countPWM++;
}
else if (tableModel.get(i).use === "Frequency"){
countFrequency++;
}
}
TabArea.channelsPWM.create_PWM(countPWM);
}
}
}
\\TabArea.qml
Item{
id: tabAreaRoot
property alias channelsPWM: channelsPWM
property alias channelsFrequency: channelsFrequency
TabBar {
id: tabBar
TabButton {
text: qsTr("PWM Output")
width: implicitWidth
}
TabButton {
text: qsTr("Frequency Output")
width: implicitWidth
}
TabButton {
text: qsTr("BLDC Emulation")
width: implicitWidth
}
}
StackLayout {
id: tabLayout
anchors.top: tabBar.bottom
currentIndex: tabBar.currentIndex
width: parent.width
height: parent.height
Rectangle {
color: background.color
border.width: 2
ScrollView{
id: scrollPWM
anchors.fill: parent
contentItem: channelsPWM.children
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn
RowLayout{
id: channelsPWM
spacing: 0
Layout.fillHeight: true
Layout.fillWidth: true
function create_PWM(countPWM){
for (var i=0;i<countPWM;i++){
var component = Qt.createComponent("PWM.qml");
if( component.status !== Component.Ready )
{
if( component.status === Component.Error )
console.debug("Error:"+ component.errorString() );
return; // or maybe throw
}
var channels =component.createObject(channelsPWM, { "id": "channelPWM"+(i+1), "channelText.text": "Channel"+(i+1)});
}
}
}
}
}/* Each tab will be a row layout containing column positioners for each channel */
Rectangle {
color: background.color
border.width: 2
ScrollView{
id: scrollFrequency
anchors.fill: parent
contentItem: channelsFrequency.children
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn
RowLayout{
id: channelsFrequency
spacing: 0
Layout.fillHeight: true
Layout.fillWidth: true
function create_Frequency(countFrequency){
for (var i=0;i<countFrequency;i++){
var component = Qt.createComponent("Frequency.qml");
if( component.status !== Component.Ready )
{
if( component.status === Component.Error )
console.debug("Error:"+ component.errorString() );
return; // or maybe throw
}
var channels =component.createObject(channelsFrequency, { "id": "channelFrequency"+(i+1), "channelText.text": "Channel"+(i+1)});
}
}
}
}
}
Rectangle {
color: background.color
border.width: 2
}
}}
两个qml文件都在同一个目录中声明。因此,TabArea组件在onAccepted处理程序中是可见的。此外,id: channelsPWM被声明为tabAreaRoot项的属性,因此也可在组件之外调用。
问题是,当我试图在create_PWM处理程序中调用onActivated时,会得到以下信息:
qrc:/Configuration.qml:181: TypeError: Cannot call method 'create_PWM' of undefined我理解这是因为channelsPWM在信号处理程序中是“不可见的”。但这是为什么?如前所述,即使在我输入TabArea.channelsPWM时也是如此。等等,QtCreator编辑器向我展示了可用的选项,这意味着这个id是由当前作用域获取的。
我还试图“绕过”这个问题,将create_PWM放在单独的js文件中,当已激活()信号被省略时,从那里调用它。在这种情况下,我没有得到TypeError ,但是所需的通道不是在所需的位置创建的。
我还检查了在处理程序中调用之前,没有销毁id channelsPWM的对象。(我想无论如何检查一下是好的)
事情可能会变得更加混乱,因为我希望根据用户的配置动态创建这些通道。因此,如果我得到这个wright,创建它们的函数需要与通道的RowLayout父函数放在同一个qml中。
提前谢谢你。
发布于 2018-01-29 11:06:15
问题解决了。
看起来,我不能直接从动态创建的对象与任何其他qml文件交换数据,除了,它的主qml文件。
因此,我必须在MenuBar.qml中创建一个方法,并将其连接到Configuration.qml中的自定义信号,就像描述的这里一样。这样,我将countPWM参数传递给父项configurationButton,然后使用在MainWindow.qml中实例化的create_PWM(countPWM)对象从那里调用create_PWM(countPWM)。因此,新创建的PWM通道将是现有对象的子对象,并放置在正确的选项卡中。
\\MenuBar.qml
(rest of code)
function sendParams(counter){
tabs.channelsPWM.create_PWM(counter);
}
\\Configuration.qml
(rest of code)
signal saved(int counter)
onSaved: {
console.log("I just sent the counter");
}
onAccepted: {
var countPWM = 0;
var countFrequency = 0;
for (var i=0; i<tableModel.count; i++){
if ( tableModel.get(i).use === "PWM" ){
countPWM++;
}
else if (tableModel.get(i).use === "Frequency"){
countFrequency++;
}
}
saved.connect(parent.sendParams);
saved(countPWM);
}https://stackoverflow.com/questions/48458995
复制相似问题