48208


`Qt Creator 4.7.0` を用いて、上記タイトルの本を読みながら、コードの実行を試みています。3個目の例なのですが、エラーが出ます。

`Rapid Dialog Design`という章  
`gotocelldialog`を作成する事が目的です。

`Example`ファイルは[こちら](http://www.informit.com/store/c-plus-plus-gui-programming-
with-qt4-9780132354165)からダウンロード可能です。  
`pdf`ファイルは[こちら](https://www.researchgate.net/publication/215458943_C_GUI_programming_with_Qt_4)から無料公開されているようです。

デバッグを開始するとこうなります。  
一応本の指示に従ってコードを書いて、UIファイルも作っているつもり  
なのですが、エラーが出ます。  
もしかするとバージョンの違いでしょうか？  
ご丁寧に、Qt Creatorは或る程度自動でコードを付与してくれて、  
とても助かりますが、本の内容とずれているように思えるところがあり、  
これは正しいかどうかわからないです。  
`Qt`のバージョンは、`5.9.6`です。  
**生じるエラー**  
[![わけがわからない](https://i.stack.imgur.com/wVucr.png)](https://i.stack.imgur.com/wVucr.png)  
`gotocell.pro` file

[code]

    #-------------------------------------------------
    #
    # Project created by QtCreator 2018-09-08T09:20:46
    #
    #-------------------------------------------------
    
    QT       += core gui widgets
    
    TARGET = gotocell
    TEMPLATE = app
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    CONFIG += c++11
    
    SOURCES += \
            main.cpp \
            gotocelldialog.cpp
    
    HEADERS += \
            gotocelldialog.h
    
    FORMS += \
            gotocelldialog.ui \
    
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
[/code]

**gotocelldialog.h**

[code]

    #ifndef GOTOCELLDIALOG_H
    #define GOTOCELLDIALOG_H    
    #include <QDialog>
    #include <QLabel>
    #include <QLineEdit>
    #include <QSpacerItem>
    #include <QPushButton>
    #include "ui_gotocelldialog.h"    
    namespace Ui {
    class GoToCellDialog;    
    }    
    class GoToCellDialog : public QDialog, public Ui::GoToCellDialog
    {
        Q_OBJECT    
    public:
        explicit GoToCellDialog(QWidget *parent = nullptr);
        ~GoToCellDialog();    
    private:
        Ui::GoToCellDialog *ui;
    private slots:
        void on_lineEdit_textChanged();
    };    
    #endif // GOTOCELLDIALOG_H
    
[/code]

**gotocelldialog.cpp**

[code]

    #include "gotocelldialog.h"
    #include "ui_gotocelldialog.h"
    #include <QtGui>
    GoToCellDialog::GoToCellDialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::GoToCellDialog)
    {
        ui->setupUi(this);
        QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
        lineEdit->setValidator(new QRegExpValidator(regExp,this));
        connect(okButton,SIGNAL(clicked()),this,SLOT(accept()));
        connect(cancelButton,SIGNAL(clicked()),this,SLOT(reject()));
    }
    void GoToCellDialog::on_lineEdit_textChanged()
    {
        okButton->setEnabled(lineEdit->hasAcceptableInput());
    }
    
    GoToCellDialog::~GoToCellDialog()
    {
        delete ui;
    }
    
[/code]

**main.cpp**

[code]

    #include <QApplication>
    #include "gotocelldialog.h"
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        GoToCellDialog *dialog = new GoToCellDialog;
        dialog->show();
    
        return a.exec();
    }
    
[/code]

**gotocelldialog.ui**

[code]

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>GoToCellDialog</class>
     <widget class="QDialog" name="GoToCellDialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>249</width>
        <height>115</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Go to Cell</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout">
         <item>
          <widget class="QLabel" name="label">
           <property name="text">
            <string>&amp;Cell Location</string>
           </property>
           <property name="buddy">
            <cstring>lineEdit</cstring>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QLineEdit" name="lineEdit"/>
         </item>
        </layout>
       </item>
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_2">
         <item>
          <spacer name="horizontalSpacer">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
            </size>
           </property>
          </spacer>
         </item>
         <item>
          <widget class="QPushButton" name="okButton">
           <property name="enabled">
            <bool>false</bool>
           </property>
           <property name="text">
            <string>OK</string>
           </property>
           <property name="default">
            <bool>true</bool>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QPushButton" name="cancelButton">
           <property name="text">
            <string>Cancel</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections>
      <connection>
       <sender>lineEdit</sender>
       <signal>textChanged(QString)</signal>
       <receiver>GoToCellDialog</receiver>
       <slot>on_lineEdit_textChanged()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>160</x>
         <y>27</y>
        </hint>
        <hint type="destinationlabel">
         <x>127</x>
         <y>55</y>
        </hint>
       </hints>
      </connection>
     </connections>
     <slots>
      <slot>on_lineEdit_textChanged()</slot>
     </slots>
    </ui>
    
[/code]


CC BY-SA 4.0
2018-09-08T02:46:01.570
48204
2018-09-08T08:23:49.990
2018-09-08T06:21:02.050
24284
24284
question
c++ qt qt-creator
C++ GUI Programming with Qt 4　GoToCellDialog 作成時にエラーが発生します。


ご提示いただいた例では、`gotocelldialog.ui`から`ui_gotocelldialog.h`が自動生成され、`gotocelldialog.h`によってインクルードされます。

UIを定義している`Ui::GoToCellDialog`というクラスを、その動作を実装するための`GoToCellDialog`クラスから利用するには、「継承」または「集約」のどちらかの方法で、UIのクラスを実装のクラスに取り込んでやる必要があります。両方ではなく、どちらか一方しか選べません。

そこで、`gotocelldialog.h`を見てみると、次の記述があります。

[code]

    class GoToCellDialog : public QDialog, public Ui::GoToCellDialog
    
[/code]

これはクラスの継承です。さらに下の方を見ると、

[code]

    private:
        Ui::GoToCellDialog *ui;
    
[/code]

これは集約です。繰り返しますが、継承か集約のどちらか一方しか使用できません。

`GoToCellDialog`クラスのコンストラクタで、次のように

[code]

        ui(new Ui::GoToCellDialog)
    {
        ui->setupUi(this);
    
[/code]

`ui`ポインタが初期化されていますが、続く3行では、

[code]

        lineEdit->setValidator(new QRegExpValidator(regExp,this));
        connect(okButton,SIGNAL(clicked()),this,SLOT(accept()));
        connect(cancelButton,SIGNAL(clicked()),this,SLOT(reject()));
    
[/code]

のように、`ui`ポインタではなく、継承した方の未構築のUIオブジェクトに対して、初期設定をしようとしており、ここでエラーになります。

修正方法としては、まず、クラスの定義で、UIクラスの継承を止めます。

[code]

    class GoToCellDialog : public QDialog, public Ui::GoToCellDialog
    
[/code]

↓

[code]

    class GoToCellDialog : public QDialog
    
[/code]

実装側では、`ui`ポインタを利用してUIオブジェクトにアクセスします。

[code]

    ui->lineEdit->setValidator(new QRegExpValidator(regExp,this));
    connect(ui->okButton,SIGNAL(clicked()),this,SLOT(accept()));
    connect(ui->cancelButton,SIGNAL(clicked()),this,SLOT(reject()));
    
    ui->okButton->setEnabled(ui->lineEdit->hasAcceptableInput());
    
[/code]

* * *

別解として、集約を使わずに継承でやりたい場合、次はそのまま残し、

[code]

    class GoToCellDialog : public QDialog, public Ui::GoToCellDialog
    
[/code]

次は削除、

[code]

    private:
        Ui::GoToCellDialog *ui;
    
[/code]

次も削除、

[code]

        ui(new Ui::GoToCellDialog)
    
[/code]

次も削除、

[code]

        ui->setupUi(this);
    
[/code]

次も削除、

[code]

        delete ui;
    
[/code]

以上どちらの方法でも結構ですが、最近は、集約（`ui`ポインタを使う方）が主流だと思います。


CC BY-SA 4.0
2018-09-08T04:30:41.897
48208
2018-09-08T04:46:11.307
2018-09-08T04:46:11.307
3337
3337
48204
answer


＃すでに回答承認されていますが、QtCreatorの観点で回答加えます。

QtCreatorでは、クラスへの(フォームの)UIクラスの埋め込み方をカスタマイズできます。

「オプション」メニューの「ツール」「オプション」で表示される「オプション画面」から、「C++」「Qtクラス生成」タブを選択すると「UIクラスの埋め込み方法」を選択することができます。  
選択肢は、

  * ポインタ型のメンバとして集約 (※初期値)
  * 集約
  * 多重継承

の3つです。「多重継承」を選択すると、参照している書籍のコード例と整合が取りやすくなるかと思います。

＃書籍のコード例は全般的に「多重継承」で実装しているように見受けましたので。


CC BY-SA 4.0
2018-09-08T08:23:49.990
48209
2018-09-08T08:23:49.990
20098
48204
answer