首页 \ 问答 \ 使用信号和插槽在Qt中与MainWindow通信QDialog(Using Signals and Slots to Comunicate a QDialog with MainWindow in Qt)

使用信号和插槽在Qt中与MainWindow通信QDialog(Using Signals and Slots to Comunicate a QDialog with MainWindow in Qt)

好的,我认为是时候得到一些帮助,我一直在练习Qt的信号和插槽,我得到了库存。 我想要的是能够在单击QDialog中的按钮时更改主窗口中的标签。 我一直在寻找,显然唯一的方法是基本上使用信号和插槽,这是我的...

我有一个mainwindow.ui,带有一个名为“pushButton_OpenWindow”的按钮和一个QLabel label_ShowText“,我还有一个包含名为lineEdit_ExternalInput的QLineEdit的externaldialog.ui”和一个名为“pushButton_SendText”的QPushButton,我想要的是更改“label_ShowText” “无论什么价值”lineEdit_ExternalInput“当点击pushButton_SendText”但它不起作用时,当我点击按钮时没有任何错误发生,没有任何警告。

这是不起作用的代码......

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_OpenWindow_clicked();
    void textValue(const QString &newText);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "externaldialog.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ExternalDialog *externalDialog = new ExternalDialog;
    // connecting signals and slots
    QObject::connect(externalDialog, SIGNAL(textChanged(QString)), this, SLOT(textValue(QString)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_OpenWindow_clicked()
{
    ExternalDialog mDialog;
    mDialog.setModal(true);
    mDialog.exec();
}

void MainWindow::textValue(const QString &newText)
{
    ui->label_ShowText->setText(newText);
    qDebug()<<"Message from textValue Function \n";
}

externaldialog.h

#ifndef EXTERNALDIALOG_H
#define EXTERNALDIALOG_H

#include <QDialog>

namespace Ui {
class ExternalDialog;
}

class ExternalDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ExternalDialog(QWidget *parent = 0);
    ~ExternalDialog();

private:
    Ui::ExternalDialog *ui;

signals:
     void textChanged(const QString&);
public slots:
     void on_pushButton_SendText_clicked();
};

#endif // EXTERNALDIALOG_H

externaldialog.cpp

#include "externaldialog.h"
#include "ui_externaldialog.h"
#include <QDebug>


ExternalDialog::ExternalDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ExternalDialog)
{
    ui->setupUi(this);

}

ExternalDialog::~ExternalDialog()
{
    delete ui;
}


void ExternalDialog::on_pushButton_SendText_clicked()
{
    emit textChanged(ui->lineEdit_ExternalInput->text());
    qDebug()<<"Sent Message";
}

main.cpp中

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

知道我做错了什么吗? 任何建议将不胜感激。 对不起,我发布了整个代码,但有时最好看到整个图片。

非常感谢


Ok I think is time to get some help, I have been practicing with signals and slots in Qt and I got stocked. What I want is to be able to change a label in mainwindow when a button in a QDialog is clicked. I have been searching and apparently the only way to do this is basically using signals and slots, here is what I have...

I have a mainwindow.ui with a button called "pushButton_OpenWindow" and a QLabel label_ShowText", I also have a externaldialog.ui that contains a QLineEdit called lineEdit_ExternalInput" and a QPushButton called "pushButton_SendText", and what I want is to change "label_ShowText" to whatever value "lineEdit_ExternalInput" is when pushButton_SendText" is clicked but it doesn't work, when I click the button nothing happens no errors, no warnings nothing.

Here is the code that doesn't work...

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_OpenWindow_clicked();
    void textValue(const QString &newText);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "externaldialog.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ExternalDialog *externalDialog = new ExternalDialog;
    // connecting signals and slots
    QObject::connect(externalDialog, SIGNAL(textChanged(QString)), this, SLOT(textValue(QString)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_OpenWindow_clicked()
{
    ExternalDialog mDialog;
    mDialog.setModal(true);
    mDialog.exec();
}

void MainWindow::textValue(const QString &newText)
{
    ui->label_ShowText->setText(newText);
    qDebug()<<"Message from textValue Function \n";
}

externaldialog.h

#ifndef EXTERNALDIALOG_H
#define EXTERNALDIALOG_H

#include <QDialog>

namespace Ui {
class ExternalDialog;
}

class ExternalDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ExternalDialog(QWidget *parent = 0);
    ~ExternalDialog();

private:
    Ui::ExternalDialog *ui;

signals:
     void textChanged(const QString&);
public slots:
     void on_pushButton_SendText_clicked();
};

#endif // EXTERNALDIALOG_H

externaldialog.cpp

#include "externaldialog.h"
#include "ui_externaldialog.h"
#include <QDebug>


ExternalDialog::ExternalDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ExternalDialog)
{
    ui->setupUi(this);

}

ExternalDialog::~ExternalDialog()
{
    delete ui;
}


void ExternalDialog::on_pushButton_SendText_clicked()
{
    emit textChanged(ui->lineEdit_ExternalInput->text());
    qDebug()<<"Sent Message";
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Any idea what I'm I doing wrong? Any suggestion will be appreciated. Sorry I posted the whole code but sometimes is better to see the whole picture.

Thanks a lot


原文:
更新时间:2022-09-15 07:09

最满意答案

好吧,似乎我将成为第一个为自己的问题找到答案的人:)

(1)首先, http://www.muitovar.com/gtk2hs/chap7-2.html上的示例对我不起作用,因为你在gtk2hs中有两个eventButton函数,你必须使用Graphics.UI.Gtk.Gdk.Events的一个Graphics.UI.Gtk.Gdk.Events 。 所以你必须在文件的开头添加:

import Graphics.UI.Gtk.Gdk.Events as Ev

然后添加Ev. eventButtonRightButtoneventSent前缀。 它现在会工作:)

(2)如何响应treeView行的右键单击:

解决了上述问题后,我偶然发现了这个例子,其中显示了如何响应在treeView中选择行。 所以我混合了这两个解决方案,并提出了类似的东西(大多数代码来自treeview示例,我的一些调整):

module Main where

 {- an example how to select from a list
   not satisfactory yet:
       - there should be a simpler way to render a simple list
       - i could not convert the model i got back to a list 
           from which to get the value

       - the interface offers a great number of functions 
           and it is very difficult to find which ones are 
           really needed for simple tasks
  -}

import Graphics.UI.Gtk
import Graphics.UI.Gtk.ModelView as Model
import Graphics.UI.Gtk.Gdk.Events as Ev

main :: IO ()
main = do
   initGUI       -- is start
   window <- windowNew

   list <- listStoreNew ["Vince", "Jhen", "Chris", "Sharon"]

   treeview <- Model.treeViewNewWithModel list
   Model.treeViewSetHeadersVisible treeview True

           -- there should be a simpler way to render a list as the following!
   col <- Model.treeViewColumnNew
   Model.treeViewColumnSetTitle col "colTitle"
   renderer <- Model.cellRendererTextNew
   Model.cellLayoutPackStart col renderer False
   Model.cellLayoutSetAttributes col renderer list
           $ \ind -> [Model.cellText := ind]
   Model.treeViewAppendColumn treeview col

   --tree <- Model.treeViewGetSelection treeview
   --Model.treeSelectionSetMode tree  SelectionSingle
   --Model.onSelectionChanged tree (oneSelection list tree)

   set window [ windowDefaultWidth := 100
               , windowDefaultHeight := 200
               , containerChild := treeview
              ]

   -- here comes the right-click popup       

   eda <- actionNew "EDA" "Edit" Nothing Nothing
   pra <- actionNew "PRA" "Process" Nothing Nothing
   rma <- actionNew "RMA" "Remove" Nothing Nothing
   saa <- actionNew "SAA" "Save" Nothing Nothing

   agr <- actionGroupNew "AGR1" 
   mapM_ (actionGroupAddAction agr) [eda,pra,rma,saa]

   uiman <- uiManagerNew
   uiManagerAddUiFromString uiman uiDecl
   uiManagerInsertActionGroup uiman agr 0

   maybePopup <- uiManagerGetWidget uiman "/ui/popup"
   let pop = case maybePopup of 
            (Just x) -> x
            Nothing -> error "Cannot get popup from string"

   onButtonPress treeview (\x -> if (Ev.eventButton x) == Ev.RightButton
                                 then do 
                               menuPopup (castToMenu pop) Nothing
                               return (Ev.eventSent x)
                                 else return (Ev.eventSent x))

   mapM_ (prAct treeview list) [eda,pra,rma,saa]    


   onDestroy window mainQuit
   widgetShowAll window
   mainGUI
   return ()

uiDecl = "<ui> \
\          <popup>\
\            <menuitem action=\"EDA\" />\
\            <menuitem action=\"PRA\" />\
\            <menuitem action=\"RMA\" />\
\            <separator />\
\            <menuitem action=\"SAA\" />\
\          </popup>\
\        </ui>"   

-- Handle the right-click. You can write a function that'll respond to various 
-- actions, like for example: handleAction "EDA" = do something, etc.    

prAct treeview list a = onActionActivate a $ do 
        name <- actionGetName a
            -- getting the selected row

        tree <- Model.treeViewGetSelection treeview

        -- you can also use treeSelectionGetSelected to get the Iter object
            -- and then convert it to Int by using listStoreIterToIndex and so get
            -- the ListStore item at given index

          sel <- Model.treeSelectionGetSelectedRows tree
        let s = head  (head sel)
        v <- Model.listStoreGetValue list s
        putStrLn ("Action Name: " ++ name ++ " | Item: " ++ v)

我希望它对某人有帮助:)

干杯


Okay it seems I'm going be the first one to find answer for my own question :)

(1) First of all the example at http://www.muitovar.com/gtk2hs/chap7-2.html didn't work for me because you have two eventButton functions in gtk2hs and you have to use the one from Graphics.UI.Gtk.Gdk.Events. So you have to add at the beginning of the file:

import Graphics.UI.Gtk.Gdk.Events as Ev

and then add Ev. prefix to eventButton, RightButton and eventSent. It'll work now :)

(2) How to respond to right clicks on treeView row:

Having solved the aforementioned problem I stumbled upon this example, where it's shown how to respond to selecting a row in treeView. So I mixed those two solutions and came up with something like this (most of the code comes from the treeview example with some of my tweaks):

module Main where

 {- an example how to select from a list
   not satisfactory yet:
       - there should be a simpler way to render a simple list
       - i could not convert the model i got back to a list 
           from which to get the value

       - the interface offers a great number of functions 
           and it is very difficult to find which ones are 
           really needed for simple tasks
  -}

import Graphics.UI.Gtk
import Graphics.UI.Gtk.ModelView as Model
import Graphics.UI.Gtk.Gdk.Events as Ev

main :: IO ()
main = do
   initGUI       -- is start
   window <- windowNew

   list <- listStoreNew ["Vince", "Jhen", "Chris", "Sharon"]

   treeview <- Model.treeViewNewWithModel list
   Model.treeViewSetHeadersVisible treeview True

           -- there should be a simpler way to render a list as the following!
   col <- Model.treeViewColumnNew
   Model.treeViewColumnSetTitle col "colTitle"
   renderer <- Model.cellRendererTextNew
   Model.cellLayoutPackStart col renderer False
   Model.cellLayoutSetAttributes col renderer list
           $ \ind -> [Model.cellText := ind]
   Model.treeViewAppendColumn treeview col

   --tree <- Model.treeViewGetSelection treeview
   --Model.treeSelectionSetMode tree  SelectionSingle
   --Model.onSelectionChanged tree (oneSelection list tree)

   set window [ windowDefaultWidth := 100
               , windowDefaultHeight := 200
               , containerChild := treeview
              ]

   -- here comes the right-click popup       

   eda <- actionNew "EDA" "Edit" Nothing Nothing
   pra <- actionNew "PRA" "Process" Nothing Nothing
   rma <- actionNew "RMA" "Remove" Nothing Nothing
   saa <- actionNew "SAA" "Save" Nothing Nothing

   agr <- actionGroupNew "AGR1" 
   mapM_ (actionGroupAddAction agr) [eda,pra,rma,saa]

   uiman <- uiManagerNew
   uiManagerAddUiFromString uiman uiDecl
   uiManagerInsertActionGroup uiman agr 0

   maybePopup <- uiManagerGetWidget uiman "/ui/popup"
   let pop = case maybePopup of 
            (Just x) -> x
            Nothing -> error "Cannot get popup from string"

   onButtonPress treeview (\x -> if (Ev.eventButton x) == Ev.RightButton
                                 then do 
                               menuPopup (castToMenu pop) Nothing
                               return (Ev.eventSent x)
                                 else return (Ev.eventSent x))

   mapM_ (prAct treeview list) [eda,pra,rma,saa]    


   onDestroy window mainQuit
   widgetShowAll window
   mainGUI
   return ()

uiDecl = "<ui> \
\          <popup>\
\            <menuitem action=\"EDA\" />\
\            <menuitem action=\"PRA\" />\
\            <menuitem action=\"RMA\" />\
\            <separator />\
\            <menuitem action=\"SAA\" />\
\          </popup>\
\        </ui>"   

-- Handle the right-click. You can write a function that'll respond to various 
-- actions, like for example: handleAction "EDA" = do something, etc.    

prAct treeview list a = onActionActivate a $ do 
        name <- actionGetName a
            -- getting the selected row

        tree <- Model.treeViewGetSelection treeview

        -- you can also use treeSelectionGetSelected to get the Iter object
            -- and then convert it to Int by using listStoreIterToIndex and so get
            -- the ListStore item at given index

          sel <- Model.treeSelectionGetSelectedRows tree
        let s = head  (head sel)
        v <- Model.listStoreGetValue list s
        putStrLn ("Action Name: " ++ name ++ " | Item: " ++ v)

I hope it'll be helpful for someone :)

Cheers

相关问答

更多
  • 使用带有Haskell和Gtk2Hs的编号行的SourceView的极简主义代码是: import Graphics.UI.Gtk import Graphics.UI.Gtk.SourceView main :: IO () main= do initGUI window <- windowNew set window [ windowTitle := "SourceView" , windowDefaultWidth := 100 ...
  • 您在Gtk2hsSetup.hs中遇到了一个错误,该错误和解决方法在此处介绍。 我建议将自己添加到trac上的该票上,以便在修复程序可用时通知您。 You're hitting a bug in Gtk2hsSetup.hs, the bug and a workaround is described here. I would recommend adding yourself to that ticket on the trac so that you'll be notified when a fix ...
  • 这个怎么样: window `on` keyPressEvent $ tryEvent $ do 'F':n_ <- eventKeyName let (n, ""):_ = reads n_ liftIO . notebookSetCurrentPage notebook $ n - 1 这是无可救药的部分:有两个部分模式匹配可以抛出异常。 但那没关系,因为这就是tryEvent的用途。 在撰写本文时,所有其他答案都涉及注册许多事件处理程序,而这一个只注册一个。 这应该具有(轻微 ...
  • 我找到了解决问题的方法: 在主程序中,我创建了一个要执行的操作列表的IORef: actionsIO <- newIORef [action_to_do_1,action_to_do_2] 我为文本输入创建了自定义组合小部件 ent <- textEntry window canvas state modele parser info actionsIO 在里面,我执行这样的动作列表: actions <- readIORef actionsIO sequence_ actions 我创建了我的树视图 ...
  • 你可以问你的顶级窗口它想要多大,并使它变得那么大: refresh window = do Requisition w h <- widgetSizeRequest window windowResize window w h 要使用它,请将其粘贴在按钮的单击处理程序中: onClicked button (containerRemove box e2 >> refresh window) You can ask your top-level window how big it want ...
  • 这里有两个来自我的应用的例子。 在main中,我将GTK小部件绑定到变量,并将其绑定到我在其他模块中实现的回调函数。 - 要加载Glade文件: gui <- builderNew builderAddFromFile gui "myGUI.glade" - 关闭申请: - 将窗口“mainWindow”(在Glade文件中定义)绑定到变量 mainWindow <- builderGetObject gui castToWindow "mainWindow" - 将菜单项“menu_Quit”(在Gl ...
  • 获取这些参数的原则是模式匹配,如下所示: case rect of Rectangle x y w h -> "The width is " ++ show w ++ " and the height is " ++ show h 这将为case表达式中的w和h指定宽度和高度。 在特定的设置中,这可能会缩短(通过直接在函数的参数上进行模式匹配,通过将rect值分配给模式等),但像这样的模式匹配是主要原则。 The principle behind getting those parameters ou ...
  • 在将Haskell绑定安装到它们之前,必须安装gtk C库。 如果需要有关如何执行此操作的说明 ,请访问安装说明并查看操作系统部分。 You must install the gtk C libraries before you install the Haskell bindings to them. Visit the installation instructions and check the section for your operating system if you need instruc ...
  • 不幸的是,目前没有纯Haskell方法(正确地)实现Widget类型。 您需要在C中实现您的小部件,然后通过FFI导入它。 有很多例子 - 基本上所有gtk + / gtk2hs都是数百个这样做的例子的集合。 Unfortunately, there is currently no pure-Haskell way to (correctly) implement the Widget type class. You'll need to implement your widget in C, then i ...
  • 好吧,似乎我将成为第一个为自己的问题找到答案的人:) (1)首先, http://www.muitovar.com/gtk2hs/chap7-2.html上的示例对我不起作用,因为你在gtk2hs中有两个eventButton函数,你必须使用Graphics.UI.Gtk.Gdk.Events的一个Graphics.UI.Gtk.Gdk.Events 。 所以你必须在文件的开头添加: import Graphics.UI.Gtk.Gdk.Events as Ev 然后添加Ev. eventButton , ...

相关文章

更多

最新问答

更多
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)
  • 是否可以嵌套hazelcast IMaps?(Is it possible to nest hazelcast IMaps? And whick side effects can I expect? Is it a good Idea anyway?)
  • UIViewAnimationOptionRepeat在两个动画之间暂停(UIViewAnimationOptionRepeat pausing in between two animations)
  • 在x-kendo-template中使用Razor查询(Using Razor query within x-kendo-template)
  • 在BeautifulSoup中替换文本而不转义(Replace text without escaping in BeautifulSoup)
  • 如何在存根或模拟不存在的方法时配置Rspec以引发错误?(How can I configure Rspec to raise error when stubbing or mocking non-existing methods?)
  • asp用javascript(asp with javascript)
  • “%()s”在sql查询中的含义是什么?(What does “%()s” means in sql query?)
  • 如何为其编辑的内容提供自定义UITableViewCell上下文?(How to give a custom UITableViewCell context of what it is editing?)
  • c ++十进制到二进制,然后使用操作,然后回到十进制(c++ Decimal to binary, then use operation, then back to decimal)
  • 以编程方式创建视频?(Create videos programmatically?)
  • 无法在BeautifulSoup中正确解析数据(Unable to parse data correctly in BeautifulSoup)
  • webform和mvc的区别 知乎
  • 如何使用wadl2java生成REST服务模板,其中POST / PUT方法具有参数?(How do you generate REST service template with wadl2java where POST/PUT methods have parameters?)
  • 我无法理解我的travis构建有什么问题(I am having trouble understanding what is wrong with my travis build)
  • iOS9 Scope Bar出现在Search Bar后面或旁边(iOS9 Scope Bar appears either behind or beside Search Bar)
  • 为什么开机慢上面还显示;Inetrnet,Explorer
  • 有关调用远程WCF服务的超时问题(Timeout Question about Invoking a Remote WCF Service)