2013-04-02 70 views
3

我想封裝表視圖行爲,並開始將表視圖標題信號連接到子類中定義的表視圖插槽。我可以在沒有繼承的情況下獲得我正在尋找的行爲,但是這會破壞目的。當我嘗試子類化時,會遇到可怕的「沒有匹配的函數調用來連接,所有組件最終都是QObject,所以我認爲這不是問題(但是,那麼也許這就是問題所在)。我連接到'hideColumn()',但我最終想連接到我自己的插槽(例如'my_sectionClicked(int)'。Qt子類化和「沒有匹配函數的調用連接」

下面的代碼是從「C++ GUI Programming with Qt的4" ,由茉莉布蘭切特和Mark Summerfield的不同之處了 「MyTableView」 另外,我做。

MyTableView.h

#ifndef MYTABLEVIEW_HPP 
#define MYTABLEVIEW_HPP 

#include <QTableView> 

class MyTableView : public QTableView 
{ 
    Q_OBJECT 

public: 
    explicit MyTableView(QWidget *parent = 0); 

public slots: 
    void my_sectionClicked(int logicalIndex); 

private slots: 

public: 

private: 
    QHeaderView *m_rowHeader; 

}; 

#endif // MYTABLEVIEW_HPP 

MyTableV iew.cpp

// Qt Includes 
#include <QDebug> 
#include <QMenu> 

// Local Includes 
#include "MyTableView.h" 

MyTableView::MyTableView(QWidget *parent) : QTableView(parent) 
{ 
    m_rowHeader = horizontalHeader(); 
    connect(m_rowHeader, SIGNAL(sectionClicked(int)), this, SLOT(hideColumn(int))); 
} 

void MyTableView::my_sectionClicked(int logicalIndex) 
{ 
    qDebug().nospace() << "Column " << logicalIndex << " selected." << "\n"; 
} 

currencymodel.h

#ifndef CURRENCYMODEL_H 
#define CURRENCYMODEL_H 

#include <QAbstractTableModel> 
#include <QMap> 

class CurrencyModel : public QAbstractTableModel 
{ 
public: 
    CurrencyModel(QObject *parent = 0); 

    void setCurrencyMap(const QMap<QString, double> &map); 
    int rowCount(const QModelIndex &parent) const; 
    int columnCount(const QModelIndex &parent) const; 
    QVariant data(const QModelIndex &index, int role) const; 
    QVariant headerData(int section, Qt::Orientation orientation, 
     int role) const; 

private: 
    QString currencyAt(int offset) const; 

    QMap<QString, double> currencyMap; 
}; 

#endif 

currencymodel.cpp

#include <QtCore> 

#include "currencymodel.h" 

CurrencyModel::CurrencyModel(QObject *parent) 
    : QAbstractTableModel(parent) 
{ 
} 

void CurrencyModel::setCurrencyMap(const QMap<QString, double> &map) 
{ 
    currencyMap = map; 
    reset(); // Forces views to refresh data 
} 

int CurrencyModel::rowCount(const QModelIndex & /* parent */) const 
{ 
    return currencyMap.count(); 
} 

int CurrencyModel::columnCount(const QModelIndex & /* parent */) const 
{ 
    return currencyMap.count(); 
} 

QVariant CurrencyModel::data(const QModelIndex &index, int role) const 
{ 
    if (!index.isValid()) 
     return QVariant(); 

    if (role == Qt::TextAlignmentRole) 
    { 
     return int(Qt::AlignRight | Qt::AlignVCenter); 
    } 
    else if (role == Qt::DisplayRole) 
    { 
     QString rowCurrency = currencyAt(index.row()); 
     QString columnCurrency = currencyAt(index.column()); 

     if (currencyMap.value(rowCurrency) == 0.0) 
      return "####"; 

     double amount = currencyMap.value(columnCurrency) 
        /currencyMap.value(rowCurrency); 

     return QString("%1").arg(amount, 0, 'f', 4); 
    } 

    return QVariant(); 
} 

QVariant CurrencyModel::headerData(int section, 
    Qt::Orientation /* orientation */, 
    int role) const 
{ 
    if (role != Qt::DisplayRole) 
     return QVariant(); 
    return currencyAt(section); 
} 

QString CurrencyModel::currencyAt(int offset) const 
{ 
    return (currencyMap.begin() + offset).key(); 
} 

mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 
#include <QtGui> 

#include "MyTableView.h" 
#include "currencymodel.h" 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    MainWindow(); 

protected: 

private slots: 
    void on_sectionClicked(int locicalIndex); 

private: 
    QMap<QString, double> currencyMap; 
    CurrencyModel currencyModel; 
    QTableView tableView; 
    QHeaderView *m_rowHeader; 
}; 

#endif 

mainwindow.cpp

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

MainWindow::MainWindow() 
{ 
    currencyMap.insert("AUD", 1.3259); 
    currencyMap.insert("CHF", 1.2970); 
    currencyMap.insert("CZK", 24.510); 
    currencyMap.insert("DKK", 6.2168); 
    currencyMap.insert("EUR", 0.8333); 
    currencyMap.insert("GBP", 0.5661); 
    currencyMap.insert("HKD", 7.7562); 
    currencyMap.insert("JPY", 112.92); 
    currencyMap.insert("NOK", 6.5200); 
    currencyMap.insert("NZD", 1.4697); 
    currencyMap.insert("SEK", 7.8180); 
    currencyMap.insert("SGD", 1.6901); 
    currencyMap.insert("USD", 1.0000); 

    currencyModel.setCurrencyMap(currencyMap); 

    /* 
    THIS WORKS!!! 

    m_rowHeader = tableView.horizontalHeader(); 
    connect(m_rowHeader, SIGNAL(sectionClicked(int)), 
     &(tableView), SLOT(hideColumn(int))); 
    */ 

    tableView.setModel(&currencyModel); 
    tableView.setAlternatingRowColors(true); 

    tableView.setWindowTitle(QObject::tr("Currencies")); 
    tableView.show(); 
} 

void MainWindow::on_sectionClicked(int logicalIndex) 
{ 
    qDebug().nospace() << "Column " << logicalIndex << " selected." << "\n"; 
} 

的main.cpp

#include "mainwindow.h" 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    MainWindow mainWin; 
    return app.exec(); 
} 

我得到的錯誤是:

g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/opt/QtSDK/Desktop/Qt/4.8.1/gcc/mkspecs/default -I. -I/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtCore -I/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtGui -I/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include -I. -I. -o MyTableView.o MyTableView.cpp 
MyTableView.cpp: In constructor ‘MyTableView::MyTableView(QWidget*)’: 
MyTableView.cpp:11: error: no matching function for call to ‘MyTableView::connect(QHeaderView*&, const char [21], MyTableView* const, const char [17])’ 
/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType) 
/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtCore/qobject.h:217: note:     static bool QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType) 
/opt/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtCore/qobject.h:337: note:     bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const 
make: *** [MyTableView.o] Error 1 
+0

my_sectionClicked在哪裏使用? –

+0

tl; dr。只發布相關的代碼。 – cmannett85

+0

@VaibhavDesai有一次,與'hideColumn(int)'的連接是到'my_sectionClicked(int)'的連接。我將它改爲現有的Qt插槽,作爲排除故障時的一個過程。 –

回答

9

當你傳遞已經向前聲明的類這樣的問題通常是造成的,但不#include'd

就您的情況而言,您的MyTableView.cpp文件中可能需要#include <QHeaderView>

問題是你可以將指針傳遞給已經轉發聲明的對象,但是編譯器不知道你的類最終來自QObject,所以不允許使用你的子類指針作爲QObject指針在調用connect()函數時。

+0

謝謝!雖然,這似乎是一個症狀,似乎反對Herb Sutter和Andrei Alexandrescu在其「C++編碼標準; 101規則,指南和最佳實踐」中的建議。我提到了關於最小化定義依賴和避免循環依賴的「項目22」的開頭句子,「......當前向聲明做時,不要包含**定義。」 –

+1

在這種情況下,它**不會**;) – Chris