我一直在寻找实现Qt应用程序“编辑”菜单的方法。 “编辑”菜单包含“复制”,“剪切”,“粘贴”等项目,并且需要转发到当前活动的窗口小部件。
我似乎无法找到一种标准或优雅的方式来做到这一点。根据这个问题,这是不可能的:
How to implement the "Edit" menu with "Undo", "Cut", "Paste" and "Copy"?
我最近有想法在显示“编辑”菜单时在当前活动小部件上触发上下文菜单事件,通过:
// create menus in MainWindow constructor
...
edit_menu = menuBar()->addMenu(tr("&Edit"));
connect(edit_menu, SIGNAL(aboutToShow()), this, SLOT(showEditMenu()));
...
// custom slot to handle the edit menu
void MainWindow::showEditMenu()
{
QWidget* w = QApplication::focusWidget();
// show the context menu of current focus widget in the menubar spot
QPoint global_pos = edit_menu->mapToGlobal(edit_menu->rect().bottomLeft());
QPoint pos = w->mapFromGlobal(global_pos);
QApplication::sendEvent(w, new QContextMenuEvent(QContextMenuEvent::Keyboard, pos, global_pos));
}
这显示当前小部件的上下文菜单很棒,但有一些问题。例如,它将焦点从菜单栏上移开,或者如果您先点击不同的菜单栏项目,则菜单栏会有焦点等。
一个部分解决方案是从窗口小部件中获取上下文菜单,并将其项目动态复制到编辑菜单中。有没有办法做到这一点?
在Qt中构建编辑菜单有更好的方法吗?
感谢您的帮助。
答案 0 :(得分:1)
好吧,如果你只需要创建菜单,你总是可以从小部件的actions
采取行动。要为小部件创建编辑操作,您可以执行以下操作:
void MainWindow::addActions (QWidget* widget)
{
QAction * copyAction = new QAction("copy",widget);
if(connect(copyAction,SIGNAL(triggered()),widget,SLOT(copy())))
{
widget->addAction(copyAction);
qDebug()<<"success connection";
}
}
和
foreach (QObject * obj, centralWidget()->children())
{
QWidget * w = dynamic_cast<QWidget*>(obj);
if (w)
addActions(w);
}
然后你总是可以用焦点小部件的动作更新编辑菜单的动作
这可能不优雅,但它比不可能的更好。示例中的主要不良假设是复制槽名为copy
答案 1 :(得分:1)
我认为一个优雅的解决方案是为您需要具有复制/粘贴/ ...功能的小部件提供基类,并让它们在激活时注册自己的某个父类,并在停用时注册。然后,可以将操作连接到主窗口中的插槽,该插槽将它们转发到已注册的窗口小部件。如果当前没有注册窗口小部件,您甚至可以使菜单项变灰(例如,因为活动窗口小部件没有所需的功能)。
注册/取消注册(未经测试)的示例:
class ActionWidget;
class ActionWidgetManager
{
public:
ActionWidgetManager() : actionWidget_(0){}
void registerWidget(ActionWidget* widget){ actionWidget_ = widget; }
void unregisterWidget(ActionWidget* widget)
{ if (actionWidget_ == widget) actionWidget_ = 0; }
bool hasActiveWidget() const{ return actionWidget_ != 0; }
ActionWidget* getActiveWidget(){ return actionWidget_; }
private:
ActionWidget* actionWidget_;
};
class ActionWidget : public QWidget
{
public:
ActionWidget(ActionWidgetManager* manager, QWidget* parent=0)
: manager_(manager), QWidget(parent) {}
~ActionWidget(){ manager_->unregisterWidget(this); }
void Widget::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
if(event->type() == QEvent::ActivationChange){
if(isActiveWindow()) {
manager_->registerWidget(this);
}
else {
manager_->unregisterWidget(this);
}
}
}
virtual void doCopy() = 0;
virtual void doPaste() = 0;
virtual void doUndo() = 0;
virtual void doCut() = 0;
private:
ActionWidgetManager* manager_;
};
使用信号和插槽等效的东西。