2012-02-22 18 views
12

QMenuBar'daki öğeleri otomatik olarak açmam (göster veya aç) gerektiren bir projede çalışıyorum.Bir menüdeki Qt'deki eylemler nasıl yinelenir?

en sonraki menü çubuğu var diyelim:

File  Edit  Help 
    -op1  -op1  -op1 
    -op2  -op2  -op2 

bir eylem (yani eylemin asociated menüyü göster) Kullandığım ayarlamak için:

menuBar->setActiveAction(mymenuactionpointer); 

bildiğim gibi, ben kullanabilirsiniz aşağıdaki biri QMenuBar elemanlarına işaretçiler bir listesini almak için:

QMenuBar::actions(); 

veya

QList<Object*> lst1 = QMenuBar::findChildren<QObject*>(); 

QList<Object*> lst2 = QMenuBar::findChildren<QAction*>(); 

Ben QMenuBar::findChildren<QAction*>() yoksa menubar menülerinin listesi, yani, benim QMenuBar gelen "File, Edit, Help" var var MenuBar::actions(), bu durumda QList büyüklüğü 3.

olduğunu kullandığınızda ben QMenuBar::findChildren<QObject*>()'u kullan 6'nın QObject bir listesini aldım, menü çubuğunda doğru sayıda öğe var. Ancak, ben a BOŞ değil tüm bu durumlarda QAction *

QAction *a = (QAction *)lst1.at(0); 
QAction *a = qobject_cast<QAction*>(lst1.at(0)); 
QAction *a = dynamic_cast<QAction*>(lst1.at(0)); 

için dökme tryied, ama ben işlemi adı QAction::title() almaya çalıştığınızda hep ben arızayı segmentasyon neden olur.

menü çubuğu eylemleri listesini aldıktan sonra, bir evet öğe bir QMenu ise eğer, bilmek (öğe bir menü ise geçerli bir QMenu işaretçi döndürür) QAction::menu() sormak ki ben arama edilmiştir ve ben here bulundu biri, o menüdeki işlem listesini tekrarlayabilir ve yinelemeye devam edebilir. Ama bu benim için çalışmıyor, ben her menünün eylemlerin listesini almak, ama olabilir

QList<Object*> lst2 = QMenuBar::findChildren<QAction*>(); 

her öğe geçerli bir menü gösterici döndürür QAction::menu() "Dosya, Düzen Yardım", yani için bunu yapar beklenmektedir Benim için hiç işe yaramıyor.

Vaktinizi ve yardımlarınızı gerçekten takdir ediyorum, umarım bu soru daha fazla insana yardım eder. Bununla gerçekten zor zamanlar geçiriyorum.

Şimdiden teşekkürler.

+0

Ben sorunuzun biten bölümü hakkında emin değilim. 'QList list = menuBar() -> findChildren ();', yinelemeli bir işlev kullanarak yineleyebileceğiniz ve '-> actions()') öğelerini alabileceğiniz geçerli bir QMenü * listesi döndürür. Ne işe yaramaz? – Hossein

cevap

0

qobject_cast'in başarısız olmasının nedeni, ebeveyn olarak QMenuBar ile yalnızca üç QAction olmasıdır. Diğer üç farklı QObjects (benim tahminim üç QMenus), bu yüzden cast başarısız olur. Bu menülerle ilişkili QActions, daha sonra QMenuBar kökünü değil. QMenus'u yinelemeli olarak yineleyerek neden QActions ana listesi oluşturamadığınızı göremiyorum.

Size , ana menüleri tetiklemeyebilecek bir menüden geçiyorsanız, QIction işaretçinizi UI tanımınızdan kullanabileceksiniz. Testi otomatik hale getirmeye çalışıyorsanız, istediğiniz QAction cihazında tetikleyici() muhtemelen ihtiyaç duyduğunuz şekilde detaylandırılmıştır. Kullanıcı eylemlerine yanıt olarak bir şeyler yapmaya çalışıyorsanız, araç çubuklarını değiştirmek, odağı bozmadığı için, muhtemelen daha iyi bir bağlamsal geri bildirim aracıdır. Gerçekte neyi başarmaya çalıştığınıza dair daha fazla ayrıntı yardımcı olacaktır.

6

Menü çubuğundaki her menü öğesinde nasıl yineleme yapılacağı aşağıda açıklanmıştır;

// assuming you have a private QActionGroup* actions; defined in the header.. 
// ...and a slot named 'onAction(QAction*)' as well... this should work: 
QList<QMenu*> lst; 
lst = ui->menuBar->findChildren<QMenu*>(); 
actions = new QActionGroup(this); 
foreach (QMenu* m, lst) 
{ 
    foreach (QAction* a, m->actions()) 
    { 
     actions->addAction(a); 
    } 
} 
connect(actions,SIGNAL(triggered(QAction*)),this,SLOT(onAction(QAction*))); 

Gördüğünüz gibi, daha sonra bir eylem getirmek olabilir çeşitli etkinlikler (ben sadece burada tetiklenen gösterdi ama fikir olsun) işlemek için bir ana yuvası bağlanabilir. Umarım bu yardımcı olur .. Birisi ..

Notlar QActionGroup'ı örnek olarak kullanabileceğin listeyi kullanmak için kullandım, ama radyo gruplarıyla uğraşmadıkça bunu gerçekten kullanmamalısın. İkinci olarak, eğer tüm öğeleri işlemek için onları tek bir yönteme bağlamayı planladığınız için eylemleri istiyorsanız, QMenu'nun tetiklenen/gezinen sinyallerini kullanmanızı veya bir menünün ne zaman açılacağını bilmeniz gerekiyorsa, ihtiyacınız olacak QMenuBar aboutToShow() sinyali. QAction * 'ı yuvadan geçtiğinizden bu sinyallerde ihtiyacınız olanı yapamayacağınız için bir sebep düşünemiyorum (her neyse). Ama eğer bunu diğer yoldan yapmanız gerekiyorsa, bunu yukarıda gösterdiğim şekilde yapabilirsiniz, sadece QActionGroup'u radyo gruplaması için tasarlandığından dolayı kullanmak istemeyebilirsiniz. . (Eğer bir QMenuactions() işlevlerini kullanmayı birer saymak gruba 'sınanabilir' olan öğeleri ekleyerek vermeyerek o etrafında

8

doğru yolu çalışabilir, ancak bir sorun var - bazı eylemlerinin alt menüler bulunur, QMenu::menuAction() ve QAction::menu() bkz

her QMenu de ilişkili olduğunu anlamak için çok önemlidir -. ve onlar Aslında, her QMenu bir QAction ile ilişkilidir yinelemeli iterated gerekiyor ve her ikisi de birbirlerine işaretçileri tutun. QAction Yani, bilmeden, doğru uygulama aşağıdaki gibidir:

void enumerateMenu(QMenu *menu) 
{ 
    foreach (QAction *action, menu->actions()) { 
     if (action->isSeparator()) { 
      qDebug("this action is a separator"); 
     } else if (action->menu()) { 
      qDebug("action: %s", qUtf8Printable(action->text())); 
      qDebug(">>> this action is associated with a submenu, iterating it recursively..."); 
      enumerateMenu(action->menu()); 
      qDebug("<<< finished iterating the submenu"); 
     } else { 
      qDebug("action: %s", qUtf8Printable(action->text())); 
     } 
    } 
} 
+1

Cevabınız için teşekkür ederiz. yararlı oldu. – PeerPandit

0

bu bir araya getiren:

template <class Function> 
class QMenuBarIterator { 
    QMenuBar *i_barP; 

    void iterate_sub(Function f, size_t tabsL, QMenu* m) { 
     foreach (QAction *action, m->actions()) { 
      f(tabsL, action); 

      if (action->menu()) { 
       iterate_sub(f, tabsL + 1, action->menu()); 
      } 
     } 
    } 

    public: 
    QMenuBarIterator(QMenuBar *barP) : i_barP(barP) {} 

    virtual void operator()(size_t levelL, QAction *actionP) { 
    } 

    void iterate(Function f) { 
     QList<QMenu *> menuBar = i_barP->findChildren<QMenu *>(); 

     foreach (QMenu* m, menuBar) { 
      f(0, m->menuAction()); 
      iterate_sub(f, 1, m); 
     } 
    } 
}; 

/***************************************************************************/ 
class CMenuLogger { 
    public: 

    void operator()(size_t tabsL, QAction *action) { 
     SuperString  tabStr(GetIndentString(tabsL)); // returns a string with tabsL tab characters in it 

     if (action->isSeparator()) { 
      qDebug("%s-------------------", tabStr.utf8Z()); 

     } else { 
      qDebug("%s%s (%s)", 
       tabStr.utf8Z(), 
       qUtf8Printable(action->text()), 
       qUtf8Printable(action->objectName())); 
     } 
    } 
}; 

ardından ana in:

{ 
    QMenuBarIterator<CMenuLogger>   bar(ui->menuBar); 

    bar.iterate(CMenuLogger()); 
} 
İlgili konular