可点击的QLabel类"乘法定义"函数

时间:2016-05-09 20:21:52

标签: c++ qt

我无法使用插槽/信号从VC ++转移到Qt风格的编程。我想创建一个带有图像的按钮,当单击该按钮时,将其更改为另一个图像,并在释放后更改回原始图像。我创建了一个名为ClickableQLabel的类,它继承自QLabel,但它告诉我某些函数是重新定义的。具体来说,是那些emit

MainProgram.cpp

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

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

    return a.exec();
}

MainProgram.h

#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H

#include <QMainWindow>
#include "clickableqlabel.h"

namespace Ui {
class MainProgram;
}

class MainProgram : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainProgram *ui;
};

#endif // MAINPROGRAM_H

clickableqlabel.h

#ifndef CLICKABLEQLABEL_H
#define CLICKABLEQLABEL_H

#include <QLabel>
#include <QMouseEvent>

using namespace Qt;

class ClickableQLabel : public QLabel {
    Q_OBJECT
    QPixmap pushed;
    QPixmap unpushed;
public:
    ClickableQLabel(QWidget *parent = 0);
    void mousePressEvent(QMouseEvent *eve );
    void mouseReleaseEvent(QMouseEvent *eve );
    void setPushed(QPixmap &p);
    void setUnpushed(QPixmap &p);

signals:
    void leftButtonPressed(ClickableQLabel* sender);
    void leftButtonReleased(ClickableQLabel* sender);
};

#endif // CLICKABLEQLABEL_H

clickableqlabel.cpp

#include "clickableqlabel.h"

ClickableQLabel::ClickableQLabel(QWidget *parent) : QLabel(parent){
    // set up qlabel
}


void ClickableQLabel::setPushed(QPixmap &p){
    pushed = p;
}

void ClickableQLabel::setUnpushed(QPixmap &p){
    unpushed = p;
}

void ClickableQLabel::leftButtonPressed(ClickableQLabel* sender){
    if(!pushed.isNull())
        sender->setPixmap(pushed.scaledToWidth(sender->width()));
}

void ClickableQLabel::leftButtonReleased(ClickableQLabel* sender){
    if(!unpushed.isNull())
        sender->setPixmap(unpushed.scaledToWidth(sender->width()));
}

void ClickableQLabel::mousePressEvent(QMouseEvent *eve ){
    if(eve->button() == Qt::LeftButton){
        emit leftButtonPressed(this);
    }
}

void ClickableQLabel::mouseReleaseEvent(QMouseEvent *eve ){
    if(eve->button() == Qt::LeftButton){
        emit leftButtonReleased(this);
    }
}

我收到的是以下3个错误:

moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonPressed(class ClickableQLabel *)" (?leftButtonPressed@ClickableQLabel@@QEAAXPEAV1@@Z) already defined in clickableqlabel.obj
moc_clickableqlabel.obj:-1: error: LNK2005: "public: void __cdecl ClickableQLabel::leftButtonReleased(class ClickableQLabel *)" (?leftButtonReleased@ClickableQLabel@@QEAAXPEAV1@@Z) already defined in clickableqlabel.obj
debug\CodeVault.exe:-1: error: LNK1169: one or more multiply defined symbols found

导致错误的两个函数是clickableqlabel.h文件中的两个信号。我该如何设置connect功能以及在哪里?

3 个答案:

答案 0 :(得分:3)

您不应该为信号提供实施方案。您只需在类标题中声明信号。 Qt moc提供了一个实现,负责在信号发出时调用信号的插槽connect,参见this。因为你提供了一个实现,而Qt moc提供了另一个实现,你最终会得到两个不同的实现,并且链接器会抱怨。

因此,为了在发出信号时执行某些代码,您可以将其放在连接到该信号的某个插槽中,或者您可以在发出信号之前手动执行它。 。

另外需要注意的是,您的信号有一个名为sender的参数。通常没有必要这样做,QObject::sender()提供类似的功能。

  

我应该如何设置连接功能以及在哪里?

例如,当您在ClickableQLabel窗口中实例化MainProgram时(可以在ClickableQLabel表单文件中使用.ui执行此操作),您可以{{1它的信号传递到connect的插槽,就像这样。

mainprogram.h

MainProgram

然后在构造函数#ifndef MAINPROGRAM_H #define MAINPROGRAM_H #include <QMainWindow> #include "clickableqlabel.h" namespace Ui { class MainProgram; } class MainProgram : public QMainWindow { Q_OBJECT public: explicit MainProgram(QWidget *parent = 0); ~MainProgram(); public slots: void labelPressed(); void labelReleased(); private: Ui::MainProgram *ui; }; #endif // MAINPROGRAM_H 中,connectClickableQLabel的广告位发出信号,如下所示:

MainProgram

其中connect(clickableLabel, SIGNAL(leftButtonPressed()), this, SLOT(labelPressed())); 是您的clickableLabel对象。

答案 1 :(得分:2)

您不应该明确定义信号&#34;功能&#34; - 简单地发出它们(就像在mousePressEvent()mouseReleaseEvent()函数中一样)。

如果您想要执行某些操作(例如setPixmap),您可以在连接到这些信号的插槽函数中执行此操作,也可以直接在mousePressEventmouseReleaseEvent函数中执行此操作。 / p>

不相关,但您可能还需要执行qRegisterMetaType<ClickableQLabel>()之类的操作,以便将该数据类型与信号/插槽机制一起使用。

答案 2 :(得分:0)

您无需子类化QLabel来实现此目的:在onLabelButtonClicked类中添加MainWindow广告位(方法),该广告连接到QPushButton { {1}}信号,并根据需要调用setText / setIcon。

如果你想重新使用这个可点击的元素,你当然可以把它封装在一个类中,但是在定义新的widget时,Qt只需要子类化和处理raw-events;如果您只是编写标准功能(单击,调整外观),那么主窗口/对话框类中的插槽通常就足够了。