2012-03-26 16 views
8

का स्क्रीन स्थिति खोजें केस का उपयोग करें: यह एक सामान्य समस्या होनी चाहिए। QMdiArea के साथ एक सामान्य QMainWindow में एक QGraphicsView के साथ एक mdiChild रहता है। यह दृश्य अंदर QGraphicsItems के साथ एक QGraphicsScene प्रदर्शित करता है। इन वस्तुओं में से किसी एक पर राइट-क्लिक आइटम (फोकस) का चयन करता है और एक संदर्भ मेनू खोलता है, जिसे आसानी से स्क्रीन पर निर्देशित किया जाता है QGraphicsSceneMouseEvent::screenPos()। यह उम्मीद के रूप में काम कर रहा है।एक QGraphicsItem

अब जब मैं एक कुंजी दबाता हूं (उदा। Qt :: Key_Menu) मैं वही संदर्भ मेनू दिखाना चाहता हूं। मुझे चयनित (केंद्रित) आइटम पता है, मुझे दृश्य पता है जो दृश्य प्रदर्शित करता है।

तो मेरे सवाल है:
स्थान प्राप्त करने के लिए सही तरीका क्या है एक दृश्य के भीतर एक QGraphicsItem के दृश्य प्रतिनिधित्व की (वैश्विक में, स्क्रीन निर्देशांक)?

यहाँ क्या काम नहीं कर रहा है:

QGraphicsItem *item = ...; // is the currently selected item next to which the context menu shall be opened 
QGraphicsScene *scene = ...; // is the scene that hosts the item 
QGraphicsView *graphicsView = ...; // is the view displaying the scene, this inherits from QWidget 

// get the position relative to the scene 
QPointF sp = item->scenePos(); 
// or use 
QPointF sp = item->mapToScene(item->pos()); 

// find the global (screen) position of the item 
QPoint global = graphicsView->mapToGlobal(graphicsView->mapFromScene(sp)); 

// now 
myContextMenu.exec(global); 
// should open the context menu at the top left corner of the QGraphicsItem item, but it goes anywhere 

The doc says: आप को पता है जहां व्यूपोर्ट में एक आइटम स्थित है चाहते हैं, आप QGraphicsItem :: mapToScene() मद पर, तो QGraphicsView कॉल कर सकते हैं: : mapFromScene() दृश्य पर।
जो मैं कर रहा हूं, ठीक है?


बस a thread in a german forum कि करने के लिए संकेत पर ठोकर खाई:

QGraphicsView *view = item->scene()->views().last(); 

या यहां तक ​​कि अच्छे:

QGraphicsView *view; 
foreach (view, this->scene()->views()) 
{ 
    if (view->underMouse() || view->hasFocus()) break; 
} 
// (use case in the forum thread:) // QMenu *menu = new QMenu(view); 

का उपयोग करना है कि मेरे सवाल का एक और अधिक सामान्यीकृत जवाब दे सकती है ...

+0

मैं एक प्रतिक्रिया पोस्ट करने वाला था, लेकिन दस्तावेज़ों को दोबारा पढ़ने से मुझे लगता है कि मैं आपके विश्लेषण से सहमत हूं: QGraphicsView :: mapFromScene को व्यूपोर्ट निर्देशांक (लायक जांच) देना चाहिए। एमडीआई बच्चों के अंदर विजेट्स पर MapToGlobal में एक गुप्त बग है तो केवल सवाल ही होगा। –

+0

@ जेम्ससर्नर तो आपका पहला अनुमान क्या होगा (जिसे आपने प्रतिक्रिया में लिखा होगा)? –

उत्तर

6

मुझे एक कामकाजी समाधान मिला।
QGraphicsItem स्क्रीन पर दिखाई देना चाहिए। (शायद अगर यह दिखाई दे रहा है क्योंकि दृश्य दृश्य के कुछ अन्य बिंदु से पता चलता नहीं है, एक दृश्य के व्यूपोर्ट के रेक्ट इंगित को नियंत्रित कर सकते हैं।)

// get the screen position of a QGraphicsItem 
// assumption: the scene is displayed in only one view or the first view is the one to determine the screen position for 
QPoint sendMenuEventPos; // in this case: find the screen position to display a context menu at 
QGraphicsItem *pFocusItem = scene()->focusItem(); 

if(scene() != NULL // the focus item belongs to a scene 
    && !scene()->views().isEmpty() // that scene is displayed in a view... 
    && scene()->views().first() != NULL // ... which is not null... 
    && scene()->views().first()->viewport() != NULL // ... and has a viewport 
    ) 
{ 
    QGraphicsView *v = scene()->views().first(); 
    QPointF sceneP = pFocusItem->mapToScene(pFocusItem->boundingRect().bottomRight()); 
    QPoint viewP = v->mapFromScene(sceneP); 
    sendMenuEventPos = v->viewport()->mapToGlobal(viewP); 
} 

if(sendMenuEventPos != QPoint()) 
{ 
    // display the menu: 
    QMenu m; 
    m.exec(sendMenuEventPos); 
} 

यह दृश्य coords मानचित्रण के लिए दृश्य की व्यूपोर्ट उपयोग करने के लिए महत्वपूर्ण है वैश्विक तारों के लिए।

संदर्भ मेनू कुंजी (Qt :: Key_Menu) का पता लगाने "मुख्य" QGraphicsItem (मेरे प्रोग्राम की संरचना के कारण) के keyPressEvent() में होता है।

+1

किसी ईवेंट के दौरान, दृश्य का व्यूपोर्ट 'QGraphicsSceneEvent :: विजेट() 'के साथ दृश्य के संपर्क में आता है। आप केवल पहले को लेने के बजाय "सही" दृश्य खोजने के लिए 'QWidget :: isAncestorOf (event-> विजेट()) 'का उपयोग कर सकते हैं। – hmn

+0

जब तक कि एप्लिकेशन हमेशा पूर्ण स्क्रीन में नहीं चलता है, तब तक 'qMainWindow'' को 'sendMenuEventPos = v-> व्यूपोर्ट() -> mapTo (mainWindow, viewP) के साथ मैप करना बेहतर होगा; 'mapToGlobal' का उपयोग करने के बजाय – vsz

1

कोड सही लगता है। लेकिन संदर्भ मेनू के निर्माण के साथ कुछ समस्या हो सकती है।

क्या आपने QContextMenu के माता-पिता को मेनविंडो (या आपके आवेदन में उस तरह का कुछ) सेट किया है ??

मुझे लगता है कि आपके मामले में समस्या हो सकती है।

शुभकामनाएं !!

1

अंधेरे में बस एक स्टैब लेकिन इस http://www.qtcentre.org/threads/36992-Keyboard-shortcut-event-not-received पर एक नज़र डालें।

क्यूटी दस्तावेज़ीकरण को देखते हुए, ऐसा लगता है कि QGraphicsView का उपयोग शॉर्टकट के संबंध में कुछ असाधारण व्यवहार का कारण बन सकता है।

ऐसा लगता है कि आपके इच्छित परिणाम को प्राप्त करने का एक मानक तरीका हो सकता है।

निर्भर करता है कि आप अपने संदर्भ मेनू, शॉर्टकट्स और क्यूग्राफिक्स व्यू को कैसे कार्यान्वित कर रहे हैं, आपको QGraphicsView के लिए Qt :: ContextMenuPolicy को उचित रूप से सेट करने और मेनू को अलग-अलग बनाने और कॉल करने की आवश्यकता हो सकती है।

मुझे इस प्रश्न में काफी रूचि है क्योंकि मुझे जल्द ही कुछ ऐसा करने की आवश्यकता होगी!

+0

'क्यूटी :: क्रियाएंटेन्स्टमेनमेनू * चमकदार * दिखता है। मैं इसमें एक नजर रखूंगा, लेकिन मुझे पूरा भरोसा नहीं है कि इससे मदद मिलेगी। मेरी सामान्य समस्या कीबोर्ड इनपुट के मुकाबले पोजिशनिंग के बारे में अधिक है (मैं उस समारोह को कहीं से भी कॉल कर सकता हूं)। –

+0

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आपने यह कैसे लागू किया है कि यह प्रासंगिक है या नहीं। मुझे ब्याज के लिए प्रलेखन में निम्न अधिभारित 'exec' फ़ंक्शन परिभाषा भी मिली: http://doc.qt.nokia.com/4.7-snapshot/qmenu.html#exec-3। यह एक अजीब स्थैतिक विधि की तरह लगता है लेकिन संभावना है कि एक QPoint पर्याप्त नहीं है जब "... माता-पिता QGraphicsView में एम्बेड किया गया है"। यह थोड़ा रहस्यमय है। –