Signal, como saber qual objeto o enviou



  • Eu estou a muito tempo procurando como solucionar este problema, e não consegui nada, mas hoje tive de encontrar esse forum em português, pois não entendo muito bem inglês.
    Então, a parte do código em que se encontra meu problema...
    @QPushButton *PButton_Abas[num_Abas];

    for(int x=0;x<num_Abas;x++){
    
        NomeAbas[x]=in.readLine();
    
        PButton_Abas[x] = new QPushButton(ui->ScWidget);
        PButton_Abas[x]->setText(NomeAbas[x]);
        HBLayout->addWidget(PButton_Abas[x]);
    
        this->connect(PButton_Abas[x],SIGNAL(clicked()),this,SLOT(AbreAba(x)));
    }@ 
    

    meu problema é com esse connect, compila tudo certo mas ocorre erro em tempo de execução...
    "QObject::connect: Incompatible sender/receiver arguments
    QPushButton::clicked() --> MainWindow::AbreAba(int)"

    Alguma sugestão?

    Desde já agradeço a paciência.



  • Eu pensei em modificar o QPushButton, adicionando outro sinal o qual daria o nome do botão pressionado, mas sem sucesso, eu compilei tudo certinho mas o botão na aparece.



  • Bom, eu consegui resolver este problema mas agora estou com outro.
    Para resolver este problema eu criei um widget(me corrijam caso esteja falando besteira pois sou novato por aqui)...

    mybutton.h
    @#ifndef MYBUTTON_H
    #define MYBUTTON_H

    #include <QWidget>
    #include <QtGui>

    class MyButton : public QWidget
    {
    Q_OBJECT
    public:
    explicit MyButton(QWidget *parent = 0);
    void setText(QString text);

    signals:
    void MyClicked(QString);

    public slots:
    void Call_signal();

    private:
    QPushButton *PB;

    };

    #endif // MYBUTTON_H@

    mybutton.cpp
    @#include "mybutton.h"

    MyButton::MyButton(QWidget *parent) :
    QWidget(parent)
    {
    PB = new QPushButton(this);
    PB->show();
    this->connect(PB,SIGNAL(clicked()),this,SLOT(Call_signal()));
    }

    void MyButton::Call_signal()
    {
    emit MyClicked(PB->text());
    }

    void MyButton::setText(QString text)
    {
    PB->setText(text);
    PB->adjustSize();
    }@

    e na parte onde eu estava tendo problema eu substitui QPushButton por MyButton, ate aí tudo bem compilou só que os botões não ajustaram ao QHBoxLayout como antes, ficou assim...

    !http://img201.imageshack.us/img201/8392/capturar.gif(...)!

    Mas onde eu coloquei a linha azul devia estar uma barra de rolagem.

    alguém me sugere algo?



  • Olá

    [quote author="Waltton.scm" date="1325017968"]
    meu problema é com esse connect, compila tudo certo mas ocorre erro em tempo de execução…
    [/quote]

    Isso ocorre pois não é feita verificação de tipos dos argumentos de signals/slots em tempo de compilação. No processo de compilação, é feita a conversão pelo "moc (meta object compiler)":http://doc.qt.nokia.com/4.8-snapshot/moc.html#moc e são verificados se os argumentos do connect satisfazem a assinatura deste método. Aqui, por exemplo, aconteceria erro na compilação se você esquecesse das macros SIGNAL ou SLOT.

    Resumidamente, o que essa conversão feita pelo moc faz é gerar uma tabela para relacionar os signals de um objeto (sender/emissor) com os slots de outro (receiver/receptor). Esse erro na execução acontece pois aí é que aparecem os problemas dos argumentos dos signals/slots.

    Aliás, fazer essa verificação em tempo de compilação é uma das mudanças propostas para o no Qt5.

    [quote author="Waltton.scm" date="1325017968"]
    @
    this->connect(PButton_Abas[x],SIGNAL(clicked()),this,SLOT(AbreAba(x)));
    @
    [/quote]

    Aqui, deveria ser:

    @
    this->connect(PButton_Abas[x], SIGNAL(clicked()), this, SLOT(AbreAba(int)));
    @

    Note que ao informar ao connect os signals e slots envolvidos, você deve utilizar o tipo do argumento, não a variável x. Creio que houve engano apenas na hora de postar aqui, pois dessa forma o creio erro na execução seria outro ("no such slot").

    "Incompatible sender/receiver" aconteceu pois, como citado anteriormente, a resolução dos argumentos do slot ocorre quando da execução. Nesse caso, quando um sinal clicked() é emitido, sua aplicação tenta encontrar o slot AbreAba(int) e aí não sabe quem de onde tirar quem é esse argumento int.

    Daí você diz: "Mas e se eu quiser que o argumento int do meu método AbreAba tenha um valor padrão?"

    É possível sim. nesse caso a declaração do slot ficaria, por exemplo:
    @
    void AbreAba(int x=0);
    @

    E o connect:

    @
    this->connect(PButton_Abas[x], SIGNAL(clicked()), this, SLOT(AbreAba()));
    @

    Assim, não haveria erro de execução algum, mas seria inútil nesse seu cenário pois todo botão clicado geraria um AbreAba com valor 0. A título de curiosidade, se você observar na documentação, o "sinal clicked tem um argumento bool":http://doc.qt.nokia.com/4.8-snapshot/qabstractbutton.html#clicked, com valor default false.

    Vou separar as respostas em outros posts pra tentar dar uma organizada melhor :-)



  • O código do seu segundo post é uma solução possível, mas por que não herdar direto de QPushButton? :-)

    mybutton.h:
    @
    #ifndef MYBUTTON_H
    #define MYBUTTON_H

    #include <QPushButton>

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

    signals:
    void myClicked(QString);

    public slots:
    void callSignal();
    };

    #endif // MYBUTTON_H
    @

    mybutton.cpp:
    @

    #include "mybutton.h"

    MyButton::MyButton(QWidget *parent) :
    QPushButton(parent)
    {
    connect(this, SIGNAL(clicked()), SLOT(callSignal()));
    }

    void MyButton::callSignal() {
    emit myClicked(text());
    }
    @



  • Agora vamos à questão sobre a barra de rolagem.

    Apenas colocar botões dentro de um layout não fará aparecer uma barra de rolagem. Para isso, você precisa de uma "QScrollArea":http://developer.qt.nokia.com/doc/qt-4.8/qscrollarea.html.

    Segue um exemplo que poderia ser aplicado ao seu caso. Assuma que MyWidget é o widget que contém seus botões colocados no QHBoxLayout.

    @
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    MyWidget w;
    QScrollArea sc;
    sc.setWidget(&w);
    
    QMainWindow mw;
    mw.setCentralWidget(&sc);
    mw.show();
    
    return a.exec&#40;&#41;;
    

    }
    @

    Agora, algumas perguntas/pensamentos:

    • O que você tem em mente com essa relação de botões e abas? Ficou a sensação de que está tentando fazer algo como o que "QTabWidget":http://developer.qt.nokia.com/doc/qt-4.8/qtabwidget.html já faz.
    • Se não for esse o objetivo, em termos de UX ("experiência do usuário"), é mesmo uma boa idéia essa combinação de vários botões x barra de rolagem?

    Espero ter ajudado,
    Anselmo



  • Bem, eu estou tentando criar um fórum, deve pensar, cara louco, todos me aconselharam fazer na web msm, mas eu quero fazer com Qt( através de FTP), por mais que eu não consiga deixa-lo funcionando eu ja adquiri e continuo adquirindo um bom conhecimento no Qt que é o objetivo principal.
    Quanto a tentar herdar direto o QPushButton, eu tentei mas acho qui fiz alguma coisa errada, vou tentar fazer de novo herdando direto o QPushButton.

    Obrigado pela atenção, sou iniciante e tudo que sei aprendi só na internet, como eu não sei inglês, muitas vesses fica difícil.

    Qualquer resultado novo eu posto aqui.



  • Eu consegui colocar a barra de rolagem, fazendo a classe MyButton herdar direto da QPushButton.
    !http://img860.imageshack.us/img860/2622/capturarq.gif(^^)!



  • Mais um problema, bem parecido com esse anterior da barra de rolagem, vou postar duas imagens, uma onde não precisa da barra de rolagem e fica certinho...

    !http://img819.imageshack.us/img819/1702/cap01z.gif(...)!

    e outra onde precisa e fica um widget sobre o outro...

    !http://img69.imageshack.us/img69/2057/cap02.gif(...)!

    o problema me parece ser o mesmo, o outro eu resolvi fazendo a classe MyButton herdar direto da QPushButton, mas dessa vez não tem como pois o widget que eu insiro no Layout é o pai de um conjunto de outros widgets.



  • Onde deveria aparecer essa barra de rolagem, dentro da primeira célula da coluna tópico? Aquilo é o widget que você está disse estar tentando inserir?



  • a barra de rolagem aparece pois eu coloquei ScrollBarAlwaysOn...
    !http://img15.imageshack.us/img15/209/cap01.gif(..)!

    !http://img195.imageshack.us/img195/2057/cap02.gif(..)!

    ela aparece mas não funciona, os widgets vão se "apertando" e se sobrepondo, deveria ficar todos como na primeira imagem.



  • Opa,

    Coloca o trecho de código em que vc faz isso, fica mais fácil ajudar do que olhando só as imagens.



  • eu consegui concertar isso, eu coloquei no frame o tamanho minimo aí quando coloco muitos eles não diminuem de tamanho.
    Desculpa o incomodo dessa vez. :/



  • Não precisa pedir desculpas :-)



  • é facil amigo

    vc sempre tem o objeto em

    #include <QObject>

    QObject::sender()

    ai para converter para a classe que vc precisa vc faz

    QPushButton b=return static_cast<QPushButton>( QObject::sender() );

    espero ter ajudado


Log in to reply
 

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