Slots and signals from different classes



  • Hello everyone,

    I have two different classes that I am trying to connect. 'browseTab' has a button in it that, the slot to execute when that button is clicked is in the 'mainView' class. My program compiles, but the signal from the browseTab button does not seem to be connected to the mainView slot. How can I call a signal in one class and have the slot be in another class? I have google around and I saw a bunch of stuff about this, but it wasn't very helpful.

    code:

    browseTab.h:
    @
    #ifndef BROWSETAB_H
    #define BROWSETAB_H

    #include <QWidget>
    #include <QLineEdit>
    #include <QWebView>
    #include <QToolBar>

    #include "mainview.h"

    class browseTab : public QWidget
    {
    Q_OBJECT
    public:
    explicit browseTab(QWidget *parent = 0);

    signals:

    protected slots:
    void makeSearchURL();
    void makeSearch();
    void changeText();
    void changeTabText();

    private:
    QWebView *webView;
    QToolBar *navBar;
    QLineEdit *URLbar;
    QLineEdit *SearchBar;
    QToolButton *addTabButton;

    };

    #endif // BROWSETAB_H
    @

    browseTab.cpp:
    @
    addTabButton = new QToolButton;
    addTabButton->setText("New Tab");
    connect(addTabButton, SIGNAL(clicked()), SLOT(newTab()));
    @

    mainView.h:
    @
    #ifndef MAINVIEW_H
    #define MAINVIEW_H

    #include <QMainWindow>
    #include <QToolButton>
    #include <QMessageBox>

    #include "apptab.h"
    #include "browsetab.h"
    #include "novablastreceiver.h"
    #include "novablastsender.h"

    class mainView : public QMainWindow
    {
    Q_OBJECT

    public:
    mainView(QWidget *parent = 0);
    ~mainView();

    signals:

    public slots:
    void newTab();

    protected slots:
    void newWindow();
    //void newTab();
    void closeTab(int index);
    void newAppTab();

    void setFullscreen();
    void setMaximized();
    void setWindowed();
    
    void startNBSender();
    void startNBReceiver();
    

    private:
    QTabWidget *tabWidget;
    QToolButton *newTabButton;
    QToolButton *newAppTabButton;
    QToolButton *menuButton;
    QAction *NBSenderAction;
    QAction *NBReceiverAction;
    QAction *FullscreenAction;
    QAction *MaximizedAction;
    QAction *WindowedAction;
    QAction *NewWindowAction;
    QAction *NewTabAction;
    QAction *AppsAction;
    QAction *BookmarksAction;
    QAction *HistoryAction;
    appTab *Apps;
    QMenu *menuButtonMenu;
    QMenu *toolMenu;
    QMenu *viewMenu;
    QWidget *mainWidget;
    QDialog *receiverDialog;
    QDialog *senderDialog;
    Receiver *newNBReceiver;
    Sender *newNBSender;

    };

    #endif // MAINVIEW_H
    @

    mainView.cpp:
    @
    void mainView::newTab()
    {
    tabWidget->addTab(new browseTab, tr("Search"));
    }
    @

    example code would be great!

    thanks!



  • You have to create a pointer to object of main view to connect the newTab(); slot. If not how to identify newTab() method of which class or which object.

    @connect(addTabButton, SIGNAL(clicked()),mainView_object_pointer, SLOT(newTab()));@



  • Thanks! how do I create a pointer to it?



  • In browseTab.h under the

    @private:
    mainview *mainView_object_pointer;
    @



  • oh okay. Thanks a lot!



  • ok so when I do that, It says 'unknown type name:"mainView"'. What am I doing wrong?



  • Okay so ive gotten my program to compile. but when I click the addTabButton, it does nothing. The compiler outputs: "QObject::connect: Cannot connect QToolButton::clicked() to (null)::newTab()"

    here is the code:

    browseTab.h:
    @#ifndef BROWSETAB_H
    #define BROWSETAB_H

    #include <QWidget>
    #include <QPointer>
    #include <QLineEdit>
    #include <QWebView>
    #include <QToolBar>

    #include "mainview.h"
    #include <mainview.h>

    class mainView;

    class browseTab : public QWidget
    {
    Q_OBJECT
    public:
    explicit browseTab(QWidget *parent = 0);

    signals:

    protected slots:
    void makeSearchURL();
    void makeSearch();
    void changeText();
    void changeTabText();

    private:
    QWebView *webView;
    QToolBar *navBar;
    QLineEdit *URLbar;
    QLineEdit *SearchBar;
    QToolButton *addTabButton;
    mainView *mainView_object_pointer;

    };

    #endif // BROWSETAB_H
    @

    browsetab.cpp:

    @#include "browsetab.h"
    #include "mainview.h"

    #include <QtWidgets>

    browseTab::browseTab(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer()
    {
    addTabButton = new QToolButton;
    addTabButton->setText("+");
    connect(addTabButton, SIGNAL(clicked()), mainView_object_pointer, SLOT(newTab()));
    }
    @

    mainview.h:

    @#ifndef MAINVIEW_H
    #define MAINVIEW_H

    #include <QMainWindow>
    #include <QToolButton>
    #include <QMessageBox>

    #include "apptab.h"
    #include "browsetab.h"
    #include "novablastreceiver.h"
    #include "novablastsender.h"

    class mainView : public QMainWindow
    {
    Q_OBJECT

    public:
    mainView(QWidget *parent = 0);
    ~mainView();

    signals:

    public slots:
    void newTab();

    protected slots:
    void newWindow();
    void closeTab(int index);
    void newAppTab();

    void setFullscreen();
    void setMaximized();
    void setWindowed();
    
    void startNBSender();
    void startNBReceiver();
    

    private:
    QTabWidget *tabWidget;
    QToolButton *newTabButton;
    QToolButton *newAppTabButton;
    QToolButton *menuButton;
    QAction *NBSenderAction;
    QAction *NBReceiverAction;
    QAction *FullscreenAction;
    QAction *MaximizedAction;
    QAction *WindowedAction;
    QAction *NewWindowAction;
    QAction *NewTabAction;
    QAction *AppsAction;
    QAction *BookmarksAction;
    QAction *HistoryAction;
    appTab *Apps;
    QMenu *menuButtonMenu;
    QMenu *toolMenu;
    QMenu *viewMenu;
    QWidget *mainWidget;
    QDialog *receiverDialog;
    QDialog *senderDialog;
    Receiver *newNBReceiver;
    Sender *newNBSender;

    };

    #endif // MAINVIEW_H
    @

    mainview.cpp:

    @#include <QtWidgets>

    #include "mainview.h"

    mainView::mainView(QWidget *parent)
    : QMainWindow(parent)
    {
    void mainView::newTab()
    {
    tabWidget->addTab(new browseTab, tr("Search"));
    }
    }
    @

    How can I make the addTabButton actually call the newTab() slot in main view.cpp

    It doesn't seem to work



  • i am pretty new too, but, I don't see where you assign your pointer to the mainview.



  • if you are doing the "connect" call inside one of your mainView's functions, you can call it like this:

    @connect(addTabButton, SIGNAL(clicked()), this, SLOT(newTab()));@

    It should work...



  • The connect is being called from browseTab, and the slot I want executed is in mainView. Help would be greatly appreciated!



  • Change your browsetab.cpp to:

    @#include "browsetab.h"
    #include "mainview.h"

    #include <QtWidgets>

    browseTab::browseTab(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer(parent->parent())
    {
    addTabButton = new QToolButton;
    addTabButton->setText("+");
    connect(addTabButton, SIGNAL(clicked()), mainView_object_pointer, SLOT(newTab()));
    }@

    And when creating the tab, change to this:

    @
    #include <QtWidgets>

    #include "mainview.h"

    mainView::mainView(QWidget *parent)
    : QMainWindow(parent)
    {

    //you should create tabWidget passing this as a parameter
    tabWidget = new QTabWidget(this);

    }

    void mainView::newTab()
    {
    tabWidget->addTab(new browseTab(tabWidget), tr("Search"));
    }
    @

    dont forget that when creating your tabWidget object (in mainView constructor?)you need to pass 'this' pointer for the mainView in the constructor,

    hope this helps...



  • Okay, although it compiles and runs, the button in the browseTab still won't create a new tab.

    It gives me this error: "QObject::connect: Cannot connect QToolButton::clicked() to (null)::newTab()"

    How do I fix this?
    remember the addTab button is in browseTab, and newTab() is in mainView



  • Are you sure you changed the way your QTabWidget is being created to:
    @tabWidget = new QTabWidget(this);@

    Just to give you a brief explanation:

    1. you need to create your "tabWidget" with "this" (mainView) as a parent so you can access it on "browseTab" constructor
    2. in "addTab" you need to create your "browseTab" object with "tabWidget" as a parent so you can access it on "browseTab" constructor
    3. you need to set "mainView_object_pointer" to "browseTab" parent's parent
    4. you need to connect "clicked" signal from "addTabButton" to slot "newTab" on "mainView_object_pointer"

    if you are following this, then your "mainView_object_pointer" can't be null as you are saying in the error message.



  • Ok so I think my problem is number 2. How can I make browseTab with tabWidget as a parent? Thanks for the help!



  • In your "newTab" function create your new "browseTab" object with "tabWidget" as a parameter.

    @void mainView::newTab()
    {
    tabWidget->addTab(new browseTab(tabWidget), tr("Search"));
    }@



  • Okay Ive tried that and now I get an error:

    "error: cannot initialize a member subobject of type 'mainView *' with an rvalue of type 'QObject *'
    mainView_object_pointer(parent->parent())"



  • In browseTab.h where you have:
    @mainview *mainView_object_pointer;@

    change to:
    @QObject *mainView_object_pointer;@



  • hmmmm, just did that. The program appears to compile just fine and starts to run (the icon on the dock starts to bounce), it crashes and says "the program has unexpectedly finished" which is obviously not very helpful. I am running Qt Creator on OS X 10.9 if that matters. What do I do?



  • You can send me the code if you want to for me to check it out, Will it run on windows or does it have any macosx dependencies?



  • browseTab.h:
    @#ifndef BROWSETAB_H
    #define BROWSETAB_H

    #include <QWidget>
    #include <QPointer>
    #include <QLineEdit>
    #include <QWebView>
    #include <QToolBar>
    #include <QObject>

    #include "mainview.h"
    #include <mainview.h>

    class mainView;

    class browseTab : public QWidget
    {
    Q_OBJECT
    public:
    explicit browseTab(QWidget *parent = 0);

    signals:

    protected slots:
    //void makeSearchURL();
    void makeSearch();
    void changeText();
    void changeTabText();

    private:
    QWebView *webView;
    QToolBar *navBar;
    //QLineEdit *URLbar;
    QLineEdit *SearchBar;
    QToolButton *addTabButton;
    QObject *mainView_object_pointer;

    };

    #endif // BROWSETAB_H
    @

    browseTab.cpp:
    @#include "browsetab.h"
    #include "mainview.h"

    #include <QtWidgets>

    browseTab::browseTab(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer(parent->parent())
    {
    QString url = "http://www.google.com";

    webView = new QWebView;
    webView->load(url);
    connect(webView, SIGNAL(loadFinished(bool)), SLOT(changeText()));
    connect(webView, SIGNAL(loadFinished(bool)), SLOT(changeTabText()));
    

    /*
    URLbar = new QLineEdit(this);
    URLbar->setStyleSheet(
    "background-color:white;"
    "color:black;"
    "border:1px solid rgba(47, 74, 135);"
    );
    connect(URLbar, SIGNAL(returnPressed()), SLOT(makeSearchURL()));
    */
    SearchBar = new QLineEdit(this);
    SearchBar->setStyleSheet(
    "background-color:white;"
    "color:black;"
    "border:1px solid black;"
    "margin-top:0px;"
    "margin-bottom:0px;"
    );
    connect(SearchBar, SIGNAL(returnPressed()), SLOT(makeSearch()));

    addTabButton = new QToolButton;
    addTabButton->setText("+");
    connect(addTabButton, SIGNAL(clicked()), mainView_object_pointer, SLOT(newTab()));
    
    QToolBar *navBar = new QToolBar;
    navBar->setStyleSheet(
                "height:20px;"
                );
    navBar->addAction(webView->pageAction(QWebPage::Back));
    navBar->addAction(webView->pageAction(QWebPage::Forward));
    navBar->addAction(webView->pageAction(QWebPage::Reload));
    navBar->addAction(webView->pageAction(QWebPage::Stop));
    //navBar->addWidget(URLbar);
    navBar->addWidget(SearchBar);
    navBar->addWidget(addTabButton);
    
    QVBoxLayout *browseTabLayout = new QVBoxLayout;
    browseTabLayout->addWidget(navBar);
    browseTabLayout->addWidget(webView);
    setLayout(browseTabLayout);
    

    }

    //browseTab-- SLOTS

    void browseTab::changeText()
    {
    SearchBar->setText(webView->url().toString());
    }

    void browseTab::changeTabText()
    {

    }
    /*
    void browseTab::makeSearchURL()
    {
    webView->setUrl(URLbar->text());
    }
    */
    void browseTab::makeSearch()
    {
    QString input = SearchBar->text();
    QUrl query = SearchBar->text();
    QString google = "/google";
    QString newsfly = "/newsfly";

    if(input.startsWith("http://"))
    {
        webView->setUrl(query);
    }
    
    else
    {
        if(input.startsWith("%"))
        {
            if(input == google)
            {
                webView->setUrl(QUrl(QString("http://www.google.com/")));
            }
    
            if(input == newsfly)
            {
                webView->setUrl(QUrl(QString("http://www.newsfly.x10.mx/")));
            }
        }
    
        else
        {
            webView->setUrl(QUrl(QString("http://www.google.com/search?fs&q=")+(SearchBar-&gt;text())));
        }
    }
    

    }

    @

    mainview.h:
    @#ifndef MAINVIEW_H
    #define MAINVIEW_H

    #include <QMainWindow>
    #include <QToolButton>
    #include <QMessageBox>

    #include "apptab.h"
    #include "browsetab.h"
    //#include "novablastreceiver.h"
    //#include "novablastsender.h"

    class mainView : public QMainWindow
    {
    Q_OBJECT

    public:
    mainView(QWidget *parent = 0);
    ~mainView();

    signals:

    public slots:
    void newTab();

    protected slots:
    void newWindow();
    void closeTab(int index);
    void newAppTab();
    void setFullscreen();
    void setMaximized();
    void setWindowed();
    //void startNBSender();
    //void startNBReceiver();

    private:
    QTabWidget *tabWidget;
    QToolButton *newTabButton;
    QToolButton *newAppTabButton;
    QToolButton *menuButton;
    QAction *NBSenderAction;
    QAction *NBReceiverAction;
    QAction *FullscreenAction;
    QAction *MaximizedAction;
    QAction *WindowedAction;
    QAction *NewWindowAction;
    QAction *NewTabAction;
    QAction *AppsAction;
    QAction *BookmarksAction;
    QAction *HistoryAction;
    appTab *Apps;
    QMenu *menuButtonMenu;
    QMenu *toolMenu;
    QMenu *viewMenu;
    QWidget *mainWidget;
    QDialog *receiverDialog;
    QDialog *senderDialog;
    //Receiver *newNBReceiver;
    //Sender *newNBSender;

    };

    #endif // MAINVIEW_H
    @

    fair warning: there is a lot of code to sift through, but much of it is commented out, and you appear to be a great programmer so you shouldn't have any trouble. Thanks for your time!



  • mainview.cpp:
    @#include <QtWidgets>

    #include "mainview.h"

    mainView::mainView(QWidget parent)
    : QMainWindow(parent)
    {
    /

    NBSenderAction = new QAction(tr("Start NovaBlast Sender"), this);
    connect(NBSenderAction, SIGNAL(triggered()), SLOT(startNBSender()));

    NBReceiverAction = new QAction(tr("Start NovaBlast Receiver"), this);
    connect(NBReceiverAction, SIGNAL(triggered()), SLOT(startNBReceiver()));
    

    */
    QMenu *toolMenu = new QMenu("Tools");
    //toolMenu->addAction(NBSenderAction);
    //toolMenu->addAction(NBReceiverAction);

    FullscreenAction = new QAction(tr("Fullscreen"), this);
    connect(FullscreenAction, SIGNAL(triggered()), SLOT(setFullscreen()));
    
    MaximizedAction = new QAction(tr("Maximize"), this);
    connect(MaximizedAction, SIGNAL(triggered()), SLOT(setMaximized()));
    
    WindowedAction = new QAction(tr("Window"), this);
    connect(WindowedAction, SIGNAL(triggered()), SLOT(setWindowed()));
    
    QMenu *viewMenu = new QMenu("View");
    viewMenu->addAction(FullscreenAction);
    viewMenu->addAction(MaximizedAction);
    viewMenu->addAction(WindowedAction);
    
    NewWindowAction = new QAction(tr("New Window"), this);
    connect(NewWindowAction, SIGNAL(triggered()), SLOT(newWindow()));
    
    NewTabAction = new QAction(tr("New Tab"), this);
    connect(NewTabAction, SIGNAL(triggered()), SLOT(newTab()));
    
    AppsAction = new QAction(tr("Apps"), this);
    connect(AppsAction, SIGNAL(triggered()), SLOT(newAppTab()));
    
    BookmarksAction = new QAction(tr("Bookmarks"), this);
    
    HistoryAction = new QAction(tr("History"), this);
    
    //menuButtonMenu contains the above QActions, and viewMenu.
    QMenu *menuButtonMenu = new QMenu("Menu");
    menuButtonMenu->addAction(NewWindowAction);
    menuButtonMenu->addAction(NewTabAction);
    menuButtonMenu->addAction(AppsAction);
    menuButtonMenu->addAction(BookmarksAction);
    menuButtonMenu->addAction(HistoryAction);
    menuButtonMenu->addSeparator();
    menuButtonMenu->addMenu(viewMenu);
    menuButtonMenu->addMenu(toolMenu);
    
    //newTabButton creates a new browseTab.
    newTabButton = new QToolButton;
    newTabButton->setText("+");
    newTabButton->setStyleSheet(
                 "background-color:rgba(229, 239, 251);"
                 "color:black;"
                 "border:1px solid black;"
                 "margin-bottom:0px;"
                 );
    connect(newTabButton, SIGNAL(released()), SLOT(newTab()));
    
    //newAppTabButton creates a new appMenu tab.
    newAppTabButton = new QToolButton;
    newAppTabButton->setText("Apps");
    newAppTabButton->setStyleSheet(
                "background-color:rgba(229, 239, 251);"
                "color:black;"
                "border:1px solid black;"
                "margin-bottom:0px;"
                );
    connect(newAppTabButton, SIGNAL(released()), SLOT(newAppTab()));
    
    //menuButton contains menuButtonMenu.
    menuButton = new QToolButton;
    menuButton->setText("|||");
    menuButton->setStyleSheet(
                "background-color:rgba(229, 239, 251);"
                "color:black;"
                "border:1px solid black;"
                "border-top:0px;"
                "border-left:1px solid black;"
                "border-right:1px solid black;"
                "border-bottom:1px solid black;"
                "margin-bottom:0px;"
                "float:left;"
                "width:50px;"
                );
    menuButton->setPopupMode(QToolButton::InstantPopup);
    menuButton->setMenu(menuButtonMenu);
    
    //creates a tabWidget containing a BrowseTab.
    tabWidget = new QTabWidget(this);
    tabWidget->addTab(new browseTab, tr("Search"));
    tabWidget->setTabsClosable(true);
    tabWidget->setTabShape(QTabWidget::Rounded);
    tabWidget->setStyleSheet(
                "color:black;"
                "QTabBar::tab { height: 5px; width: 100px; }"
                );
    connect(tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(closeTab(int)));
    
    //contains several buttons.
    QHBoxLayout *topRowLayout = new QHBoxLayout;
    topRowLayout->addWidget(menuButton);
    topRowLayout->addWidget(newTabButton);
    topRowLayout->addWidget(newAppTabButton);
    
    //contains a tabWidget with topRowLayout on top.
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(topRowLayout);
    mainLayout->addWidget(tabWidget);
    setLayout(mainLayout);
    
    //contains mainLayout.
    mainWidget = new QWidget;
    mainWidget->setLayout(mainLayout);
    
    setUnifiedTitleAndToolBarOnMac(true);
    setCentralWidget(mainWidget);
    

    }

    mainView::~mainView()
    {
    }

    //mainView--SLOTS
    void mainView::setFullscreen()
    {
    this->setWindowState(Qt::WindowFullScreen);
    }

    void mainView::setMaximized()
    {
    this->setWindowState(Qt::WindowMaximized);
    }

    void mainView::setWindowed()
    {
    this->setWindowState(Qt::WindowMinimized);
    }

    void mainView::newWindow()
    {
    mainView newWindow;
    newWindow.show();
    }

    void mainView::newTab()
    {
    tabWidget->addTab(new browseTab(tabWidget), tr("Search"));
    }

    void mainView::closeTab(int index)
    {
    tabWidget->removeTab(tabWidget->currentIndex());
    }

    void mainView::newAppTab()
    {
    tabWidget->addTab(new appTab, tr("App Menu"));
    }@



  • where you have in your mainView constructor:
    @tabWidget->addTab(new browseTab, tr("Search"))@

    please change it to:
    @tabWidget->addTab(new browseTab(tabWidget), tr("Search"));@

    just as in mainView::newTab()

    hope it works.

    best,
    --rb



  • Okay I have partial success! When the program starts it automatically creates a tab, when i press the addTab button inside this tab it creates another tab, but the addTab button in these new tabs doesn't work. What do I do? Thanks!



  • Ok. It seems you have a different hierarchy for these objects. Let's keep it simple. In browseTab::browseTab change the code to:
    @
    browseTab::browseTab(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer(parent)
    {
    @

    In mainview.cpp, change everything from:
    @new browseTab(tabWidget)@
    to
    @new browseTab(this)@

    It should work fine.



  • Success! It works, but I don't quite understand how.
    Thanks for all of your help!



  • sorry to resurrect this thread, but I am having a similar problem again. I have created two new classes: sideBar and sideBar_appView. the mainView class has a QDockWidget in it that contains sideBar. Inside sideBar there is a QTabWidget that creates a new tab populated by sideBar_appView. Within sideBar_appView there is a button that is supposed to call mainView::newAppTab. However it does nothing when clicked.

    code:

    sidebar.h:
    @#ifndef SIDEBAR_H
    #define SIDEBAR_H

    #include "sidebar_appview.h"
    #include "mainview.h"
    #include <mainview.h>
    #include <QPointer>
    #include <QObject>
    #include <QWidget>
    #include <QWebView>
    #include <QVBoxLayout>
    #include <QTabWidget>
    #include <QTextEdit>

    class mainView;

    class sideBar : public QWidget
    {
    Q_OBJECT
    public:
    explicit sideBar(QWidget *parent = 0);

    signals:

    public slots:

    private:
    //sideBar_appView *appView;
    QTabWidget *tabs;
    QTextEdit *settingsView;
    QObject *mainView_object_pointer;
    };

    #endif // SIDEBAR_H@

    sidebar.cpp:
    @#include "sidebar.h"
    #include "mainview.h"

    #include <QtWidgets>

    sideBar::sideBar(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer(parent)
    {
    QString url = "http://www.google.com";

    settingsView = new QTextEdit;
    
    tabs = new QTabWidget;
    tabs->setTabPosition(QTabWidget::West);
    tabs->setStyleSheet(
                "QTabBar::tab { width: 25px; }"
                );
    tabs->addTab(new sideBar_appView(this), tr("Apps"));
    tabs->addTab(settingsView, tr("Settings"));
    
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(tabs);
    setLayout(layout);
    

    }
    @

    sidebar_appview.h
    @#ifndef SIDEBAR_APPVIEW_H
    #define SIDEBAR_APPVIEW_H

    #include <QPointer>
    #include <QObject>
    #include <QWidget>
    #include <QToolButton>
    #include <QVBoxLayout>
    #include "mainview.h"
    #include <mainview.h>
    //#include "sidebar.h"
    //#include <sidebar.h>

    class mainView;

    class sideBar_appView : public QWidget
    {
    Q_OBJECT
    public:
    explicit sideBar_appView(QWidget *parent = 0);

    signals:

    public slots:

    private:
    QToolButton *runAntivirusButton;
    QToolButton *viewAllAppsButton;

    QObject *mainView_object_pointer;
    

    };

    #endif // SIDEBAR_APPVIEW_H
    @

    sidebar_appview.cpp:
    @#include "sidebar_appview.h"
    #include "mainview.h"
    //#include "sidebar.h"

    #include <QtWidgets>

    sideBar_appView::sideBar_appView(QWidget *parent) :
    QWidget(parent),
    mainView_object_pointer(parent)
    {
    runAntivirusButton = new QToolButton;
    runAntivirusButton->setText("Run Antivirus");

    viewAllAppsButton = new QToolButton;
    viewAllAppsButton->setText("All Apps ->");
    connect(viewAllAppsButton, SIGNAL(clicked()), mainView_object_pointer, SLOT(newAppTab()));
    
    QVBoxLayout *appViewLayout = new QVBoxLayout;
    appViewLayout->setMargin(0);
    appViewLayout->addWidget(runAntivirusButton);
    appViewLayout->addWidget(viewAllAppsButton);
    setLayout(appViewLayout);
    

    }@



  • mainview.h:
    @#ifndef MAINVIEW_H
    #define MAINVIEW_H

    #include <QMainWindow>
    #include <QToolButton>
    #include <QMessageBox>

    #include "apptab.h"
    #include "browsetab.h"
    #include "sidebar.h"
    #include "sidebar_appview.h"

    class mainView : public QMainWindow
    {
    Q_OBJECT

    public:
    mainView(QWidget *parent = 0);
    ~mainView();

    signals:

    public slots:
    void newTab();
    void newAppTab();

    protected slots:
    void newWindow();
    void closeTab(int index);
    //void newAppTab();
    void setFullscreen();
    void setMaximized();
    void setWindowed();

    private:
    QTabWidget *tabWidget;
    //sideBar *sidebarContents;
    QDockWidget *sidebar;

    QToolButton *newTabButton;
    QToolButton *newAppTabButton;
    QToolButton *menuButton;
    QAction *NBSenderAction;
    QAction *NBReceiverAction;
    QAction *FullscreenAction;
    QAction *MaximizedAction;
    QAction *WindowedAction;
    QAction *NewWindowAction;
    QAction *NewTabAction;
    QAction *AppsAction;
    QAction *BookmarksAction;
    QAction *HistoryAction;
    appTab *Apps;
    QMenu *menuButtonMenu;
    QMenu *toolMenu;
    QMenu *viewMenu;
    QWidget *mainWidget;
    QDialog *receiverDialog;
    QDialog *senderDialog;
    

    };

    #endif // MAINVIEW_H
    @

    mainview.cpp:
    @#include <QtWidgets>

    #include "mainview.h"

    mainView::mainView(QWidget *parent)
    : QMainWindow(parent)
    {
    //creates a tabWidget containing a BrowseTab.
    tabWidget = new QTabWidget(this);
    tabWidget->addTab(new browseTab(this), tr("Search"));
    tabWidget->setTabsClosable(true);
    tabWidget->setTabShape(QTabWidget::Rounded);
    tabWidget->setStyleSheet(
    "QTabBar::tab { height: 25px; }"
    );
    connect(tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(closeTab(int)));

    sidebar = new QDockWidget;
    sidebar->setFloating(false);
    sidebar->setAllowedAreas(Qt::RightDockWidgetArea);
    sidebar->setStyleSheet(
                "width:100px;"
                "max-width:200px;"
                );
    //sidebar->setWidget(sidebarContents);
    sidebar->setWidget(new sideBar(this));
    
    //contains a tabWidget with topRowLayout on top.
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setMargin(0);
    mainLayout->addWidget(sidebar);
    mainLayout->addWidget(tabWidget);
    setLayout(mainLayout);
    

    @



  • I think I am confused about how the slots and signals system works between classes. I have read the documentation extensively, but I still don't understand it. Could someone explain how it works and how to get slots and signals from unrelated classes to work? It would really be appreciated!


  • Moderators

    Hi,

    A slot is a function. When a signal is emitted, Qt calls the functions that are connected to that signal.

    When you make a signal-slot connection, you also give Qt 2 pointers:

    • A pointer to the object that emits the signal (called the "sender")
    • A pointer to the object that should run its member function when the signal is emitted (called the "receiver")

    Example:
    @
    // Class header
    class MyObject : public QObject {
    ...

    signals:
    void mySignal();

    public slots:
    void mySlot();
    }
    @

    @
    // Logic
    MyObject *obj1 = new MyObject();
    MyObject *obj2 = new MyObject();

    connect(obj1, SIGNAL(mySignal()),
    obj2, SLOT(mySlot()));
    @

    Every time obj1 emits mySignal(), Qt calls obj2->mySlot(). However, nothing will happen if obj2 emits mySignal(), because that signal is not connected to any slots.



  • I understand the basic concept of slots and signals, but I do not understand how to connect a signal and slot that are in different classes


  • Moderators

    [quote author="nicky j" date="1390198966"]I understand the basic concept of slots and signals, but I do not understand how to connect a signal and slot that are in different classes[/quote]Pass the object pointers, signal name, and slot name to connect().

    @
    connect(pointerToSender, SIGNAL(signalName()),
    pointerToReceiver, SLOT(slotName()));
    @



  • I tried that with the code i posted above, but it does not work. I am trying to send a signal from sideBar_appView.cpp and have it call a slot in mainView.cpp. What am I doing wrong?


  • Moderators

    mainView_object_pointer is a pointer to a QObject. QObject does not have a slot called newAppTab(). (When you run your program in Qt Creator, you will get a warning message that gives you this hint -- open the "Application Output" tab at the bottom).

    Solution: You need to use a pointer to a mainView.

    P.S. It is also a better design to make the connection in the parent, not in the child. The child is not supposed to know about the parent.



  • How do I set up the connection in the parent, not in the child? On that same note, how do I determine who is the parent and who is the child?


  • Moderators

    [quote author="nicky j" date="1390258400"]How do I set up the connection in the parent, not in the child?[/quote]Note: I only suggested this as a "best practice". You don't strictly have to do this; your code will work once you change the type of 'mainView_object_pointer' and assign it.

    Anyway, call connect() in the parent's constructor instead of the child's constructor. However, since the parent doesn't have direct access to the child's button, the child will need to emit a signal when the button is clicked:
    @
    // sidebar_appview.cpp
    connect(viewAllAppsButton, SIGNAL(clicked()), this. SIGNAL(newAppTabRequested()));
    @

    You can now connect sidebar_appView->newTabRequested() to a slot, and that slot will be called when viewAllAppsButton is clicked.

    [quote]On that same note, how do I determine who is the parent and who is the child? [/quote]Major hint: What parameters do your widget constructors take?



  • So than how can I create a parent that has multiple children?
    Example code would be nice!



  • How can I establish a clear hierarchy between several classes and have signals call slots in other classes. the mainView_object_pointer works, but I have no idea why or how.


  • Moderators

    [quote]On that same note, how do I determine who is the parent and who is the child?

    ...

    How can I establish a clear hierarchy between several classes[/quote]This is a conceptual thing. Drawing class diagrams can help you design your hierarchy.

    Basically, the children should be contained inside the parent. E.g. if you have a MainWindow that contains a few buttons, the MainWindow should be the parent of the buttons.

    [quote]So than how can I create a parent that has multiple children?
    Example code would be nice![/quote]You set the parent through the constructor. That's what I was trying to hint at before: The last parameter for all QObject constructors is called "parent" (this shows up in the documentation, and in your IDE's auto-complete feature).
    @
    QWidget* w1 = new QWidget();
    QWidget* w2= new QWidget(w1);
    QWidget* w3 = new QWidget(w1);
    @
    Here, w1 has no parent. w2 and w3 have w1 as their parent.

    Alternatively, you can use the "setParent()":http://qt-project.org/doc/qt-5/qobject.html#setParent function.

    [quote]How can I... have signals call slots in other classes. the mainView_object_pointer works, but I have no idea why or how.[/quote]I'd like to better understand what you know and what you don't know. Could you please describe, in your own words: How do signals and slots work within the same class? (let's forget the case of multiple classes for now)



  • Ok that was really helpful, thanks!

    How I think slots & signals work:
    when a certain action is performed (e.g. triggered, clicked), a SIGNAL is emitted. This signal corresponds to a certain SLOT. I believe a slot is similar to a method/function. Therefore, when an action takes place, a signal is emitted and the code in the corresponding slot is executed. I know my understanding is pretty simplistic and/or flawed. In the connect() function, you must declare: the thing emitting the signal, the type of signal, where the slot is located, and the name of the slot.

    Please correct me if I'm wrong.


  • Moderators

    You're welcome. :)

    [quote]when a certain action is performed (e.g. triggered, clicked), a SIGNAL is emitted.[/quote]Yes, that is one of the major uses of signals+slots: to allow functions to be called easily when the user clicks the mouse, presses a key, etc.

    Signals+slots can do a lot more than that still. You can emit signals whenever you want. You can signal when you finish processing something, when you encounter an error, when a timer expires, etc.

    Heck, you can even make an object emit signals at random times for fun.

    [quote]This signal corresponds to a certain SLOT. I believe a slot is similar to a method/function. Therefore, when an action takes place, a signal is emitted and the code in the corresponding slot is executed.[/quote]You've gotten the gist of it correct.

    Slots ARE functions. Any function in your program can be turned into a slot. After you connect a signal to a function, that function will be called each time the signal is emitted.

    However, the relationship doesn't need to be one-to-one. A signal can be connected to multiple slots: When the signal is emitted, all those functions will be called one by one. A slot can also be connected to multiple signals: If any of the signals are emitted, the slot (function) will be called. You can see a diagram of these multi-connections "here":http://qt-project.org/doc/qt-5/signalsandslots.html.

    [quote]In the connect() function, you must declare: the thing emitting the signal, the type of signal, where the slot is located, and the name of the slot.[/quote]Correct. The connection function is:
    @
    connect(thingEmittingTheSignal, SIGNAL(typeOfSignal()),
    whereTheSlotIsLocated, SLOT(nameOfSlot()));
    @

    With this "formula" it is easy to connect signals to slots in the same class, or across different classes.

    @
    QPushButton* b1 = new QPushButton();
    QPushButton* b2 = new QPushButton();

    b1->show(); // Show b1 only, keep b2 hidden

    // Connect different objects
    connect(b1, SIGNAL(clicked()),
    b2, SLOT(show()));

    // Connect the same object
    connect(b2, SIGNAL(clicked()),
    b2, SLOT(hide()));
    @

    Notice that QPushButton::show() is a slot, but can also be called directly as b1->show().

    When b1 is clicked, b2->show() is called.
    When b2 is clicked, b2->hide() is called.

    Note: 'this' is an object pointer, just like 'b1' and 'b2' in this example.

    Has your original question been answered yet?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.