Pass instance of class to a another constructor that adds its object to a list owned by passed instance

北慕城南 提交于 2019-12-25 02:36:27

问题


As the title says I want to create an object of class Note and add its pointer to a list of the object of class Traymenu. I am missing the whole thing I guess, please take a look on how I call the Note's constructor in traymenus's newNote and what I am doing in 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:


I list each problem followed by an illustrative snippet of your mistake.

  • QObjects are not copyable. You can't pass their instances anywhere. You can't store their instances in most containers. std::list is a notable example. QWidgets are QObjects, too. You can only pass QObjects by pointer, or by reference. To store QObjects in containers, you must store a smart pointer, e.g. std::unique_ptr or std::shared_ptr or QSharedPointer to an instance created on the heap.

    void newNote(QWidget, Traymenu);
    
  • Calling delete this inside a method should be done with utmost care; except for special circumstances it's just wrong. If you're new to C++, the rule of thumb is: it's always wrong. If you want to delete an object instance that you're sure is on the heap, you can call deleteLater. It will perform the deletion once the control returns to the event loop.

  • The typical way of exiting an application is by calling QCoreApplication::quit().

    QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);
    
  • Parameters with default values must come after parameters without default values.

    Note(QWidget *parent = 0, Traymenu *trayMenuIn);
    
  • When you pass a parameter in a function/method call, you don't need to provide the types again.

    Note(Traymenu *this);
    
  • When holding references to QObjects whose lifetime is not well controlled, you should use QPointer to avoid dangling pointer references. A QPointer resets itself to zero when the object is deleted elsewhere, thus giving you a clean crash (as opposed to undefined and possibly very misleading behavior).

    Traymenu *pTraymenu
    
  • Initialization of class members should be done in default member initializers, and/or an initialization list. Your code below has nothing to do with formal parameters:

    Traymenu *pTraymenu = &trayMenuIn;
    

After all those fixes, and some others, the code looks like below. You could compile it as a self-contained, single file - it works, although you never show the notes, so they remain invisible.

// 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;
};
// TrayMenu.cpp

template <int N> auto decode64(const char (&arg)[N], int rows) {
   auto const raw = QByteArray::fromBase64(QByteArray::fromRawData(arg, N-1));
   QImage img((const quint8 *)raw.data(), rows, rows, raw.size()/rows, QImage::Format_MonoLSB);
   img = std::move(img).convertToFormat(QImage::Format_Indexed8);
   img.setColor(1, qRgba(0, 0, 0, 0)); // make transparent
   return img;
}

// convert baseline_language_black_18dp.png -flatten -negate -monochrome mono:-|base64 -b80
static const char language_d64[] =
      "/////w//////D/////8P/z/A/w//DwD+D/8BAPwP/wEA+A9/IEbgDz8cjuEPPxyPww8fHg+HDw+PHw8P"
      "DwAAAA8PAAAADw8AAAAPx8c/Pg7Hzz8+DsfHHz4Ox4c/Pg7Hxz8/DsfHPz4ODwAAAA4PAAAADw8AAAAP"
      "H48fjw8fHg+HDz8cj4MPPxiH4Q9/IMbgD/8AAPAP/wMA/A//DwD/D/8/4P8P/////w//////D/////8P";
static const auto language_icon = decode64(language_d64, 36);

// convert baseline_note_add_black_18dp.png -flatten -negate -monochrome mono:-|base64 -b80
static const char note_add_d64[] =
      "/////w//////D/////8PfwDA/w8/AMD/Dz8AAP8PPwAY/w8/ADD8Dz8AePwPPwDw8A8/APjhDz8A8OMP"
      "PwDwxw8/AJDCDz8AAMAPPwAAwA8/AATADz8AD8APPwAGwA8/AA/ADz8ABsAPP/D/wA8/8P/ADz/w/8AP"
      "PwAOwA8/AAfADz8ADsAPPwAGwA8/AAbADz8AAMAPPwAAwA8/AADAD38AAOAP/////w//////D/////8P";
static const auto note_add_icon = decode64(note_add_d64, 36);

TrayMenu::TrayMenu() {
   m_mainIcon.setIcon(QPixmap::fromImage(language_icon));
   m_mainIcon.setVisible(true);
   m_mainIcon.show();
   createMainContextMenu();
}

void TrayMenu::newNote() {
   m_notes.emplace_back(this);
   m_notes.back().show();
}

void TrayMenu::createMainContextMenu() {
   auto *actionNewNote = m_mainContextMenu.addAction("Neue Notiz");
   m_mainContextMenu.addSeparator();
   auto *actionExitProgram = m_mainContextMenu.addAction("Programm beenden");

   actionNewNote->setIcon(QPixmap::fromImage(note_add_icon));
   actionNewNote->setIconVisibleInMenu(true);

   QObject::connect(actionNewNote, &QAction::triggered, this, &TrayMenu::newNote);
   QObject::connect(actionExitProgram, &QAction::triggered, QCoreApplication::quit);

   m_mainIcon.setContextMenu(&m_mainContextMenu);
}

// Note.cpp

Note::Note(TrayMenu *trayMenu, QWidget *parent) :
   QWidget(parent),
   m_traymenu(trayMenu)
{
   m_ui.setupUi(this);
}

// main.cpp

int main(int argc, char ** argv) {
   QApplication app(argc, argv);
   TrayMenu menu;
   return app.exec();
}
#include "main.moc"


来源:https://stackoverflow.com/questions/21753641/pass-instance-of-class-to-a-another-constructor-that-adds-its-object-to-a-list-o

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!