正如标题所说,我想创建一个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);
}
注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
注.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);
}
我列出了每个问题,然后是一个错误的说明片段。
-
QObjects不可复制。你不能把它们的实例传递到任何地方。您不能将它们的实例存储在大多数容器中。CCD_ 1就是一个显著的例子。Q桥也是QObject。只能通过指针或引用传递QObjects。要将QObjects存储在容器中,必须存储指向堆上创建的实例的智能指针,例如
std::unique_ptr
、std::shared_ptr
或QSharedPointer
。void newNote(QWidget, Traymenu);
-
在方法内部调用
delete this
时应格外小心;除非有特殊情况,否则这是错误的。如果你是C++的新手,经验法则是:它总是错误的。如果您想删除一个确信在堆上的对象实例,可以调用deleteLater
。一旦控件返回到事件循环,它将执行删除操作。 -
退出应用程序的典型方式是调用
QCoreApplication::quit()
。QObject::connect(actionExitProgram,&QAction::triggered,this,&Traymenu::exitProgram);
-
具有默认值的参数必须位于没有默认值的后面。
Note(QWidget *parent = 0, Traymenu *trayMenuIn);
-
在函数/方法调用中传递参数时,不需要再次提供类型。
Note(Traymenu *this);
-
当保存对生存期没有得到很好控制的QObjects的引用时,应该使用
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;
};
// 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"