简体   繁体   中英

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

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);
}

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, eg 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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM