Signals and slots with multiple widgets, chat example



  • Hi, i've never really done gui work before and I chose to try and write a little chat program to teach myself. I understand some things about signals and slots but other things I'm not really sure about.

    Basically the way I've structured my chat is, the main is the friends list, then I used a dialogue box to get the settings, and a widget for a chat window to talk with someone. The chat window is going to be able to open multiple times per conversation. I'm guessing I need to implement some sort of protocol to route the messages from the main window, but I don't know how to handle getting the text being sent back. I can make All the windows share the socket that's open to the server but I was planning on making a signal, on send, grab the text from the text input and send it.

    Where I'm kind of lost is if i have multiple widgets with a send signal how do i know which widget set the signal? I also built the dialog/chat/friends to all have a separate class, so i have 3 classes.



  • You can use sender() method in your slot. Or you can transfer some id via one of signal params.



  • Just for the records there is "QSignalMapper":http://doc.qt.nokia.com/latest/qsignalmapper.html which allows for automatic mapping of signals from various sources (which, however, might not necessarily cover your use case).



  • Sorry if this is basic stuff, i know there is plenty of documentation but if I don't know what I'm looking for then its very hard to find in documentation,

    thanks for the info, when you say transfer the id via one of the signal params do you mean when using the connect macro? This isn't really filled in yet, but could i do something like this

    @void ChatClient::OpenChat(QString strName)
    {
    CChatWindow *elChato = new CChatWindow;
    elChato->setWindowTitle(strName);

    connect( elChato,
    SIGNAL ( send(QByteArray byMsg) ),
    this ,
    SLOT( SendMsg(QByteArray byMsg) ) );

    QPair<QString,CChatWindow*> newChat;
    m_mapChats.insert(strName, elChato);

    }@

    @class CChatWindow : public QWidget
    {
    Q_OBJECT

    public:
    CChatWindow(void);
    ~CChatWindow(void);

    public slots:

    signals:
    void Send(QByteArray byMsg);

    private:

    Ui::chatWindow win;
    };@



  • Not sure that I understood what you want to do with this code. At first remove params names from connect.
    You can add additional param to signal and slot and pass some unique id at emitting for example. Or you can use QSignalMapper as Lukas suggested



  • Basically all i want is to open a chat window, map the send signal from my cchatwindow to send a message from the chat window back to the main window to send the msg. Or i can send an ID back, search for the the specific window in a list, then get the msg.

    so in my chat window i hit send, the slot implementation would basically read the contents of the text, and send the byte array back to the main window which is kind of what I'd like to do. I kind of changed my mind about the ID, it seems easier to send the entire message.

    @void CChatWindow::SendMsg()
    {
    QString msg = win.textIn->toPlainText();
    QByteArray byArray;
    byArray.append(msg);

    emit Send(byArray);
    win.textIn->clear();
    }@



  • Ok i think i've got that to work, the next thing i'm wondering is, should I try and use all signals and slots, right now I'm finding the widget ID using a class method to print directly to the output window.

    Is there a way to set a signal to a specific object. For instance in my example, I have the receiver that gets a message, then I'd set a signal to let the chat windows know there is a new message, how do i filter out that specific chat window I want?



  • You cannot emit a signal to a specifc slot, but keep in mind that slots are ordinary methods which can be called through a signal, but don't have to. So instead of sending a signal to a slot just call the slot directly.

    If you are crossing thread boundaries or you want to call the slot through the event loop for any other reason you can invoke the slot using the meta object system and "QMetaObect::invokeMethod()":http://doc.qt.nokia.com/latest/qmetaobject.html#invokeMethod which is basically the same as sending a signal to a specific slot / object.


Log in to reply
 

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