Qt designer如何实现Recent Files动作?
How to implement Recent Files action with Qt designer?
我知道如果我手写的话我可以使用for循环但是我怎么能用Qt设计器呢?或者我应该将这两种方式混合在一起以达到目标吗?
感谢
当我尝试实现最近的文件时,我想到了这样的解决方案:
我在启动时创建菜单项并将它们设置为不可见:
separatorAct = ui.menu_File->addSeparator();
for (int i = 0; i < MAXRECENTFILE; ++i) {
RecentProjects[i] = new QAction(this);
RecentProjects[i]->setVisible(false);
connect(RecentProjects[i], SIGNAL(triggered()), this, SLOT(OpenRecentFile()));
ui.menu_File->addAction(RecentProjects[i]);
}
然后我更新最近的文件条目(存储在文件中):
void BulbCalculator::UpdateRecentFileActions() {
QSettings settings("GRYS","BulbCalculator");;
QStringList files = settings.value("RecentProject").toStringList();
int numRecentFiles = qMin(files.size(), MAXRECENTFILE);
for (int i = 0; i < numRecentFiles; ++i) {
QString text = tr("&%1 %2").arg(i + 1).arg(StrippedName(files[i]));
RecentProjects[i]->setText(text);
RecentProjects[i]->setData(files[i]);
RecentProjects[i]->setVisible(true);
}
for (int j = numRecentFiles; j < MAXRECENTFILE; ++j) {
RecentProjects[j]->setVisible(false);
}
separatorAct->setVisible(numRecentFiles > 0);
}
插槽OpenRecentFile
实现起来非常简单
void BulbCalculator::OpenRecentFile() {
QAction *action = qobject_cast<QAction *>(sender());
if (action) {
this->BcStatus->CurFile = action->data().toString();
LoadFile();
//LoadFile(action->data().toString());
}
}
希望对您有所帮助
我制作了一个 class 来解析 QMainWindow 的菜单栏中名为“”的文本项。此项将被隐藏,并添加或更新最近最常用的文件。
header:
#pragma once
#include <QObject>
#include <list>
#include <vector>
class QMainWindow;
class QAction;
class GFQtRecentFileMenu : public QObject {
Q_OBJECT
public:
explicit GFQtRecentFileMenu(QObject* parent = nullptr);
void updateRecentFileList(QMainWindow* pMW, const std::vector<QString>& files);
void removeAddedEntries();
private:
std::list<QAction*> m_AddedActions;
std::vector<QString> m_filenames;
public slots:
void onRmuMenuItem();
};
实施:
#include "gfqtrecentfilemenu.h"
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include "gfappframework.h"
class QMenuBarIterator {
QMenuBar* i_barP;
QMenu* m_RMU_menu;
QAction* m_RMU_action;
bool investigate(QAction* pA) {
if (pA->text() == QString("<RMU>")) { // HERE'S THE MENU TEXT PLACEHOLDER
m_RMU_action = pA;
return true;
}
return false;
}
bool iterate_sub(QMenu* m) {
for (QAction* action: m->actions()) { // sub menus of File, Edit, ...
if (investigate(action)) {return true;}
if (action->menu()) {
if (iterate_sub(action->menu())) {
m_RMU_menu = action->menu();
return true;
}
}
}
return false;
}
public:
QMenuBarIterator(QMenuBar* barP) : i_barP(barP), m_RMU_menu(nullptr), m_RMU_action(nullptr) {}
bool iterate() {
QList<QMenu*> menuBar = i_barP->findChildren<QMenu*>();
for (QMenu* m: menuBar) { // File, Edit, ..., Help
if (investigate(m->menuAction()) || iterate_sub(m)) {
m_RMU_menu = m;
return true;
}
}
return false;
}
QAction* action() {return m_RMU_action;}
QMenu* menu() {return m_RMU_menu;}
};
GFQtRecentFileMenu::GFQtRecentFileMenu(QObject* parent) : QObject(parent) {
}
void GFQtRecentFileMenu::updateRecentFileList(QMainWindow* pMW, const std::vector<QString>& files) {
removeAddedEntries();
m_filenames = files;
QMenuBarIterator mbi(pMW->menuBar());
if (mbi.iterate()) {
QAction* pA = mbi.action();
auto* pmenu = mbi.menu();
pA->setVisible(false); // hide the dummy, but keep in place. We're adding menu items at this position!
int index = 0;
for (auto& f: files) {
QAction* pA = pmenu->addAction(f);
pA->setData(index++);
m_AddedActions.push_back(pA);
connect(pA, SIGNAL(triggered()), this, SLOT(onRmuMenuItem()));
}
}
}
void GFQtRecentFileMenu::removeAddedEntries() {
for (auto* a : m_AddedActions) { delete a; }
m_AddedActions.clear();
}
void GFQtRecentFileMenu::onRmuMenuItem() {
auto* action= qobject_cast<QAction*>(sender());
if (action != nullptr) {
int index = action->data().toInt();
if (index >= 0 && index < int(m_filenames.size())) {
// open the document now - however you do that...
GetMyApplication().openDocument(m_filenames[index]);
}
qDebug() << m_filenames[i] << " clicked";
}
}
我知道如果我手写的话我可以使用for循环但是我怎么能用Qt设计器呢?或者我应该将这两种方式混合在一起以达到目标吗?
感谢
当我尝试实现最近的文件时,我想到了这样的解决方案:
我在启动时创建菜单项并将它们设置为不可见:
separatorAct = ui.menu_File->addSeparator();
for (int i = 0; i < MAXRECENTFILE; ++i) {
RecentProjects[i] = new QAction(this);
RecentProjects[i]->setVisible(false);
connect(RecentProjects[i], SIGNAL(triggered()), this, SLOT(OpenRecentFile()));
ui.menu_File->addAction(RecentProjects[i]);
}
然后我更新最近的文件条目(存储在文件中):
void BulbCalculator::UpdateRecentFileActions() {
QSettings settings("GRYS","BulbCalculator");;
QStringList files = settings.value("RecentProject").toStringList();
int numRecentFiles = qMin(files.size(), MAXRECENTFILE);
for (int i = 0; i < numRecentFiles; ++i) {
QString text = tr("&%1 %2").arg(i + 1).arg(StrippedName(files[i]));
RecentProjects[i]->setText(text);
RecentProjects[i]->setData(files[i]);
RecentProjects[i]->setVisible(true);
}
for (int j = numRecentFiles; j < MAXRECENTFILE; ++j) {
RecentProjects[j]->setVisible(false);
}
separatorAct->setVisible(numRecentFiles > 0);
}
插槽OpenRecentFile
实现起来非常简单
void BulbCalculator::OpenRecentFile() {
QAction *action = qobject_cast<QAction *>(sender());
if (action) {
this->BcStatus->CurFile = action->data().toString();
LoadFile();
//LoadFile(action->data().toString());
}
}
希望对您有所帮助
我制作了一个 class 来解析 QMainWindow 的菜单栏中名为“
header:
#pragma once
#include <QObject>
#include <list>
#include <vector>
class QMainWindow;
class QAction;
class GFQtRecentFileMenu : public QObject {
Q_OBJECT
public:
explicit GFQtRecentFileMenu(QObject* parent = nullptr);
void updateRecentFileList(QMainWindow* pMW, const std::vector<QString>& files);
void removeAddedEntries();
private:
std::list<QAction*> m_AddedActions;
std::vector<QString> m_filenames;
public slots:
void onRmuMenuItem();
};
实施:
#include "gfqtrecentfilemenu.h"
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include "gfappframework.h"
class QMenuBarIterator {
QMenuBar* i_barP;
QMenu* m_RMU_menu;
QAction* m_RMU_action;
bool investigate(QAction* pA) {
if (pA->text() == QString("<RMU>")) { // HERE'S THE MENU TEXT PLACEHOLDER
m_RMU_action = pA;
return true;
}
return false;
}
bool iterate_sub(QMenu* m) {
for (QAction* action: m->actions()) { // sub menus of File, Edit, ...
if (investigate(action)) {return true;}
if (action->menu()) {
if (iterate_sub(action->menu())) {
m_RMU_menu = action->menu();
return true;
}
}
}
return false;
}
public:
QMenuBarIterator(QMenuBar* barP) : i_barP(barP), m_RMU_menu(nullptr), m_RMU_action(nullptr) {}
bool iterate() {
QList<QMenu*> menuBar = i_barP->findChildren<QMenu*>();
for (QMenu* m: menuBar) { // File, Edit, ..., Help
if (investigate(m->menuAction()) || iterate_sub(m)) {
m_RMU_menu = m;
return true;
}
}
return false;
}
QAction* action() {return m_RMU_action;}
QMenu* menu() {return m_RMU_menu;}
};
GFQtRecentFileMenu::GFQtRecentFileMenu(QObject* parent) : QObject(parent) {
}
void GFQtRecentFileMenu::updateRecentFileList(QMainWindow* pMW, const std::vector<QString>& files) {
removeAddedEntries();
m_filenames = files;
QMenuBarIterator mbi(pMW->menuBar());
if (mbi.iterate()) {
QAction* pA = mbi.action();
auto* pmenu = mbi.menu();
pA->setVisible(false); // hide the dummy, but keep in place. We're adding menu items at this position!
int index = 0;
for (auto& f: files) {
QAction* pA = pmenu->addAction(f);
pA->setData(index++);
m_AddedActions.push_back(pA);
connect(pA, SIGNAL(triggered()), this, SLOT(onRmuMenuItem()));
}
}
}
void GFQtRecentFileMenu::removeAddedEntries() {
for (auto* a : m_AddedActions) { delete a; }
m_AddedActions.clear();
}
void GFQtRecentFileMenu::onRmuMenuItem() {
auto* action= qobject_cast<QAction*>(sender());
if (action != nullptr) {
int index = action->data().toInt();
if (index >= 0 && index < int(m_filenames.size())) {
// open the document now - however you do that...
GetMyApplication().openDocument(m_filenames[index]);
}
qDebug() << m_filenames[i] << " clicked";
}
}