Автоматически заполнять меню «Редактировать» в строке меню с текущим контекстным меню виджета фокуса - PullRequest
1 голос
/ 28 июля 2011

Я искал способы реализовать меню «Правка» приложения Qt.Меню «Редактировать» содержит такие элементы, как «Копировать», «Вырезать», «Вставить» и т. Д., Которые необходимо переслать в текущий активный виджет.

Не получается найти стандарт илиэлегантный способ сделать это.По этому вопросу это невозможно:

Как реализовать меню «Правка» с помощью «Отменить», «Вырезать», «Вставить» и «Копировать»?

У меня недавно была идея вызвать событие контекстного меню на текущем активном виджете, когда отображается меню «Редактировать», с помощью:

// 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?

Спасибо за вашу помощь.

Ответы [ 2 ]

1 голос
/ 30 июля 2011

Я полагаю, что элегантным решением было бы иметь базовый класс для виджетов, который вам нужен, чтобы иметь функцию копирования / вставки / ..., и чтобы они регистрировались в некотором родительском классе после активации и отмены регистрации при деактивации.Затем действия можно просто подключить к слотам в главном окне, которое перенаправляет их в зарегистрированный виджет.Вы могли бы даже выделить пункты меню серым цветом, если виджет в настоящее время не зарегистрирован (например, потому что активный виджет не имеет требуемой функциональности).

Пример для регистрации / отмены регистрации (непроверенный):

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

Или что-то эквивалентное, используя сигналы и слоты.

1 голос
/ 29 июля 2011

хорошо, если вам просто нужно создать меню, вы всегда можете выполнить действия из 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...