将类的实例传递给另一个构造函数,该构造函数将其对象添加到由传递的实例拥有的列表中

时间:2014-02-13 11:59:32

标签: c++ qt qt5

正如标题所说,我想创建一个类Note的对象,并将其指针添加到Traymenu类的对象列表中。我想错过整个事情,请看看我如何在traymenus的newNote中调用Note的构造函数以及我在note.h中做了什么。

traymenu.h:

#ifndef TRAYMENU_H
#define TRAYMENU_H

#include <QSystemTrayIcon>
#include <QIcon>
#include <QPixmap>
#include <QMenu> //in use for context menu
#include <QList>

#include "note.h"

class Traymenu : public QSystemTrayIcon
{
public:
    Traymenu();
    ~Traymenu();
    void createMainContextMenu();
    void newNote(QWidget, Traymenu);
    void exitProgram();

private:
    QSystemTrayIcon mainIcon;
    QMenu mainContextMenu;
    QList<Note> notelist; //List that holds references to Note objects
                          //template argument 1 is invalid

};
#endif // TRAYMENU_H

traymenu.cpp:

#include "traymenu.h"
#include <QDebug>

Traymenu::Traymenu(){
    mainIcon.setIcon(QIcon(QPixmap("C:\\program.png")));
    mainIcon.setVisible(true);
    mainIcon.show();

    createMainContextMenu();
}

Traymenu::~Traymenu(){
}

void Traymenu::newNote(){
    Note(Traymenu *this); //HOW TO PASS THE TRAYMENU INSTANC TO NOTE???
}

void Traymenu::exitProgram(){
    delete this; //deletes traymenu object (icon disappears)
}

void Traymenu::createMainContextMenu(){
    QAction *actionNewNote = mainContextMenu.addAction("Neue Notiz");
    mainContextMenu.addSeparator();
    QAction *actionExitProgram = mainContextMenu.addAction("Programm beenden");

    actionNewNote->setIcon(QIcon("C:\\new.ico"));
    actionNewNote->setIconVisibleInMenu(true);

    //Qt5 new signal connection: http://qt-project.org/wiki/New_Signal_Slot_Syntax
    QObject::connect(actionNewNote,&QAction::triggered,this,&Traymenu::newNote);
    QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);

    mainIcon.setContextMenu(&mainContextMenu);
}

note.h:

#ifndef NOTE_H
#define NOTE_H

#include <QWidget>
#include "traymenu.h"

namespace Ui{
class Note;
}

class Note : public QWidget
{
public:
    Note(QWidget *parent = 0, Traymenu *trayMenuIn);
    ~Note();
    void appendNoteToNotelist();

private:
    Q_OBJECT
    Ui::Note *ui;
    Traymenu *pTraymenu = &trayMenuIn; //trayMenuIn was not declared in this scope
                                       //Why declare a formal parameter?
};
#endif // NOTE_H

note.cpp:

#include "note.h"
#include "ui_note.h"

Note::Note(QWidget *parent, Traymenu *trayMenuIn) :
    QWidget(parent),
    ui(new Ui::Note)
{
    ui->setupUi(this);
    Note::appendNoteToNotelist();
}

Note::~Note()
{
    delete ui;
}

void Note::appendNoteToNotelist(){
    pTraymenu.append(&ui);
}

1 个答案:

答案 0 :(得分:2)

我列出了每个问题,然后是错误的说明性摘要。

  • QObjects不可复制。你无法在任何地方传递他们的实例。您无法将其实例存储在大多数容器中。 std::list是一个值得注意的例子。 QWidgets也是QObjects。您只能通过指针或引用传递QObject。要将QObject存储在容器中,必须存储智能指针,例如<{1}}或std::unique_ptrstd::shared_ptr到堆上创建的实例。

    QSharedPointer
  • 在方法中调用void newNote(QWidget, Traymenu); 应该非常谨慎;除了特殊情况,这是错的。如果你是C ++的新手,经验法则是:它总是错的。如果要删除您确定在堆上的对象实例,可以调用delete this。一旦控件返回到事件循环,它将执行删除。

  • 退出应用程序的典型方法是调用deleteLater

    QCoreApplication::quit()
  • 带有默认值的参数必须位于没有默认值的参数之后。

    QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);
    
  • 在函数/方法调用中传递参数时,不需要再次提供类型。

    Note(QWidget *parent = 0, Traymenu *trayMenuIn);
    
  • 当保持对生命周期控制不佳的QObject的引用时,应使用Note(Traymenu *this); 来避免悬空指针引用。当对象在其他地方被删除时,QPointer将自身重置为零,从而为您提供干净的崩溃(与未定义且可能非常误导的行为相反)。

    QPointer
  • 类成员的初始化应该在默认成员初始值设定项和/或初始化列表中完成。您的代码与正式参数无关:

    Traymenu *pTraymenu
    

在完成所有这些修复以及其他一些修复后,代码如下所示。你可以将它编译为一个独立的单个文件 - 它可以工作,虽然你从不显示笔记,所以它们仍然是不可见的。

Traymenu *pTraymenu = &trayMenuIn;
// https://github.com/KubaO/stackoverflown/tree/master/questions/note-tray-21753641
#include <QtWidgets>
#include <list>

// Note.h

namespace Ui{
class Note {
public:
   void setupUi(QWidget *) {} // dummy for sscce.org
};
}

class TrayMenu;
class Note : public QWidget
{
   Q_OBJECT
public:
   Note(TrayMenu *trayMenu, QWidget *parent = {});
private:
   Ui::Note m_ui;
   QPointer<TrayMenu> m_traymenu;
};

// TrayMenu.h

class Note;
class TrayMenu : public QObject {
   Q_OBJECT
public:
   TrayMenu();
   void createMainContextMenu();
   void newNote();
private:
   QSystemTrayIcon m_mainIcon;
   QMenu m_mainContextMenu;
   std::list<Note> m_notes;
};