Qt'de normal bir işlevmiş gibi bir sinyali çağırmakla emit kullanmak


97

Diyelim ki şu sinyale sahibim:

signals:
    void progressNotification(int progress);

Kısa bir süre önce Qt'deki emit anahtar kelimesini öğrendim. Şimdiye kadar, sinyalleri sadece normal bir işlev gibi çağırarak yürütürdüm. Yani bunun yerine:

emit progressNotification(1000 * seconds);

Yazardım:

progressNotification(1000 * seconds);

Onları bu şekilde çağırmak işe yarıyor gibi görünüyordu ve tüm bağlı slotlar çalışacaktı, bu yüzden emit anahtar sözcüğünü kullanmak farklı bir davranışa neden olur mu, yoksa sadece sözdizimsel şeker mi?


17
+1 Asla bilmeye emitgerek yoktur. emitSinyal slot sistemi Qt hakkında öğrenilmesi gereken ilk şeylerden biri olduğu için, sinyalleri doğrudan çağırdıktan sonra uzun süre öğrenmiş olmanız gariptir .
Christian Rau

Yanıtlar:


89

emitsadece sözdizimsel şekerdir. Bir sinyal yayan işlevin önceden işlenmiş çıkışına bakarsanız emit, hemen gittiğini görürsünüz .

"Sihir", moc tarafından üretilen C ++ kodunu inceleyerek bakabileceğiniz sinyal yayma işlevi için üretilen kodda gerçekleşir.

Örneğin foo, parametresiz bir sinyal bu üye işlevi üretir:

void W::foo()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

Ve kod emit foo();, basitçefoo();

emittanımlanır Qt/qobjectdefs.h, bu gibi (kaynak olsa bu açık kaynak lezzet):

#ifndef QT_NO_EMIT
# define emit
#endif

( no_keywordsTanımlama koruması , Qt'yi QMake yapılandırma seçeneği aracılığıyla çakışan adlara sahip diğer çerçevelerle kullanmanızı sağlamaktır .)


14
emitHiçbir şeyden fazlasını yapmayan bir uygulamanın bir uygulaması (veya planlanmış bir uygulama) olup olmadığını biliyor musunuz? Bu durumda 'sözdizimsel şekere' sahip olmanın acemiyi (veya en azından acemi bir Qt kullanıcısıyken en azından benim) kafasını karıştırdığını görüyorum - emitsözde anahtar kelimeyle hiçbir şey yapmadığında büyülü veya önemli bir şey oluyor gibi görünüyor . hepsi - tüm sihir, mocyaratan normal bir eski işlevde gerçekleşir ( mocQt sinyalleri ve yuvaları için sihirdir). emithiçbir şey yapmayan ancak önemli görünen gereksiz bir dekorasyondur.
Michael Burr

12
Emit olduğunu değil "sadece dekorasyon". emitÇağrıyı okuyan kişiye sihrin gerçekleşmek üzere olduğunu söyler (yani bu, bu sınıfın potansiyel olarak hiç duymadığı nesnelerde kodu tetikleyecektir ve bu çağrılar eşzamanlı veya eşzamansız olabilir), anahtar kelimeyi atlarsanız esasen tamamen kaybolur. Kullan onu. Otomatik olarak belgeleniyor. "Acemiler" dokümanları ve öğreticileri okumalı ve emither zaman oradadır (yine de resmi belgelerde). Sadece "ışığı gördükten" sonra işlevin gerçekleşmesi gerektiğini keşfederek - o noktada artık acemi değilsiniz.
Mat

19
Hmm, emit'anahtar kelimenin' ne kadar değerli olduğu konusunda seninle aynı fikirde olduğumdan emin değilim . Sanırım, bir işlev çağrısının bir sinyal olduğunu netleştirmeye ihtiyaç varsa bir adlandırma kuralının kullanılmasını tercih ederdim.
Michael Burr

2
Pekala, buna radikal bir şekilde katılmıyorum :) Bir adlandırma kuralını zorlamak, projelerinizde / iş yerinizde kendiniz yapabileceğiniz bir şeydir, Qt bunu engellemez. Qt sizi "anahtar kelimeyi" kullanmaya zorlamaz ve hatta kodunuzun diğer bölümleriyle çakışması durumunda onu kapatmanıza izin verir. Kanımca, anahtar kelime yaklaşımı daha iyidir - derleyici, adlandırma ilkelerini uygulamanıza yardımcı olamaz, ancak yanlış yazılanları yakalayacaktır emit.
Mat

15
Açık olmak gerekirse - bir adlandırma kuralının kullanılmasını savunmuyordum - sadece bir emitpsuedo-anahtar kelime-yorumunun nedeni bir sinyalin çağrıldığını netleştirmekse, o zaman bir adlandırma kuralı aynı şeyi yapabilirdi, gizem ve benzer faydalarla. Adlandırma kuralı Qt tarafından uygulanamaz (aslında mocbunu uygulayabilir - ama bunu da savunmuyorum), ancak Qt emitikisinin de kullanımını zorlayamaz . Ve emitbir isim çatışması varsa 'kapatabilseniz de, onu kullanan bir grup kaynak dosyanız varsa (gereksiz yere, önyüklemek için) bu pek yardımcı olmaz.
Michael Burr

2

18 ay sonra ... @ Mat'ın cevabının altındaki yorumlarla başladım ve hızla odam tükeniyordu. Böylece cevap.

IMO emitne sözdizimsel şeker ne de basit bir anahtar kelimedir.

  1. Kod üretir (yukarıda @Mat tarafından açıklandığı gibi),
  2. connectMekanizmanın aslında bunun bir a olduğunu anlamasına yardımcı olur signalve
  3. Sinyalin nerede ve nasıl yayıldığına bağlı olarak sinyallerin ve yanıtların (yuvaların) senkronize veya asenkron olarak yürütülebildiği veya sıraya konulabildiği "daha büyük" bir sistemin parçası olmasını sağlar. Bu, sinyal / slot sisteminin son derece kullanışlı bir özelliğidir.

Tüm sinyal / slot sistemi, basit bir fonksiyon çağrısından farklı bir deyimdir. Gözlemci modelinden kaynaklandığına inanıyorum. Ayrıca a signalve a arasında büyük bir fark vardır slot: bir sinyalin uygulanması gerekmez , oysa bir yuvanın uygulanması gerekir !

Caddede yürüyorsunuz ve yanmakta olan bir ev görüyorsunuz (bir sinyal). 911'i arayın ( yangın sinyalini 911 yanıt yuvasına bağlayın ). Sinyal sadece yayıldı , oysa yuva itfaiye tarafından uygulandı . Kesin olmayabilir, ama fikri anladınız. OP örneğine bakalım.

Bazı arka uç nesneleri, ne kadar ilerleme kaydedildiğini bilir. Yani basitçe emit progressNotification(...)sinyal verebilir . Bu sinyali alıp üzerinde yürütmek, gerçek ilerleme çubuğunu görüntüleyen sınıfa bağlıdır. Ancak görüş bu sinyale nasıl bağlanır? Qt'nin sinyal / slot sistemine hoş geldiniz. Artık, bir görünüm nesnesi ve bir veri hesaplama nesnesinden (her ikisi de mevcut olan QObjects) oluşan bir yönetici sınıfı (tipik olarak bir tür widget) tasarlanabilir connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress).

Yönetici sınıfının tasarım yönlerine girmeyelim, ancak sinyal / slot sisteminin parladığı yerin burası olduğunu söylemek yeterli. Uygulamam için çok temiz bir mimari tasarlamaya odaklanabiliyorum. Her zaman değil, çoğu zaman, yalnızca sinyal yaydığımı, yuvaları uyguladığımı görüyorum .

Bir sinyal yöntemini , onu hiç yaymadan kullanmak / çağırmak mümkünse , o zaman bu , ilk başta bir sinyal olarak bu işleve asla ihtiyaç duymadığınız anlamına gelir .


6
Hayır, emitaslında yalnızca boş bir makrodur ve tamamen isteğe bağlıdır. Anahtar kelimeler signalve slotmoc tarafından işlenenler öyle değildir. signalişlevin uygulanmasını sağlamak için slotkullanılır, meta nesne girişini oluşturmak için kullanılır, böylece SLOT(MySlot())makro veya QML'de bulunur. emitsözdizimsel şekerli. Yazarsanız emit i++;(ama belki iş arkadaşlarınız olabilir) ve yine de bağlantı kuramazsanız hiçbir şey şikayet etmez i++.
derM

-4

İkinci seçenek, işlev adının ve işlev parametrelerinin ne olduğunu her zaman bildiğinizi ve onu gönderdiğiniz nesnenin o belirli işlev tarafından bilindiğini ima eder. Bu iki durum her zaman doğru değildir, bu nedenle yuvaların ve sinyallerin neden yapıldığı iki ana şeydir. "kaputun altında" sinyal ve yuva mekanizması, bağlı olan her işlev için işaretçiler içeren bir tablodur.

Ayrıca, sinyallerin ve yuva mekanizmasının doğasını çok net bir şekilde açıklayan bu pdf'ye bakın: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf


Her iki yol da sinyal adını ve parametrelerini bilmeyi gerektirir - onu yayıyorsunuz, bilmediğiniz bir şeyi nasıl yayabilirsiniz? Her ikisi de aynı anlamlara sahiptir, aynıdırlar.
Mat

1
Belki de doğrudan bir slot çağrısıyla bir sinyal çağrısını bozuyorsunuz? Ama ilk başta soru başlığını da merak ettiğimi itiraf etmeliyim, çünkü emitoperasyonsuz olduğunu hiç bilmiyordum . Ama bu durumda bile, soru gövdesini okumak işleri açıklığa kavuşturmalıydı, yani -1.
Christian Rau
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.