2010-09-08 13 views
16

Qt एक अच्छा ढांचा और महान यूआई टूलकिट है और इसमें many useful features and concepts है। हम में से अधिकांश शायद सहमत हैं कि Trolltech, हाल ही में Nokia, ने इसे विकसित करने में बहुत अच्छी नौकरी की है। क्यूटी में नवीनतम प्रगति में से एक QML है, जिसे मुझे आकर्षक प्रगति मिलती है।क्यूटी में आपको कौन सी विशेषताएं या अवधारणाएं परेशान करती हैं?

हालांकि, मुझे Model/View (अवधारणा ठीक है, लेकिन कार्यान्वयन नहीं है) जैसी कुछ अवधारणाओं को बुरी तरह से डिजाइन या बुरी तरह कार्यान्वित किया गया है और यह Phonon मीडिया ढांचे के लिए भी जाता है। कुछ लोग कहते हैं कि यह meta-object अवधारणा है जो उन्हें पागल बनाता है।

यह सब स्पष्ट रूप से कम या ज्यादा व्यक्तिपरक हैं, लेकिन Qt में उपयोग करने के लिए आपको कौन सी विशेषताओं या अवधारणाओं का उपयोग करना पड़ता है और आप उनके आसपास कैसे घूमते हैं?

+5

यह लगभग क्यूटी जैसे लोगों की आलोचना करने के लिए बहुत अधिक दिखता है :-) – Tuminoid

+0

मैं और अधिक शानदार उत्तर पाने के लिए एक और +50 बक्षीस डालूंगा! रखो और आओ। – Tuminoid

+0

दूसरे बक्षीस पर 2 दिन शेष, क्यूटी के साथ अपने मुद्दों को लाएं और आप उन्हें कैसे बाधित करते हैं, या आप उन्हें कैसे ठीक करना चाहते हैं! – Tuminoid

उत्तर

27

क्यूटी के साथ मेरी अधिकांश पकड़ें आती हैं इस तथ्य से कि एपीआई QObject द्वारा प्रदान की गई गतिशीलता को पूरी तरह से गले लगाता नहीं है। यदि आप सी ++ में गतिशील व्यवहार जोड़ने के लिए मेटा-ऑब्जेक्ट कंपाइलर बनाने की हिम्मत करते हैं, तो इसके बारे में शर्मिंदा क्यों हो?

नीचे दी गई सभी चीजें हैं जो मेरी टीम को किसी बिंदु पर चाहिए और हमें इसे स्वयं कोड करना था। यह बहुत मजेदार था और हमने क्यूटी आंतरिक के बारे में बहुत कुछ सीखा, लेकिन अगर यह पहले से ही किया गया था और उपयोग करने के लिए तैयार था तो मुझे कोई फर्क नहीं पड़ता।

नहीं QObject

आप कोको में की तरह पता है, वितरित। वे QtDBus के साथ आधा रास्ता चला गया - नेटवर्किंग करने के लिए छोड़ दिया केवल एक चीज है। हमें इसके लिए अपना स्वयं का समाधान लागू करना पड़ा, और चूंकि हम क्यूटी कोड के बाहर रहते हैं, इसलिए हम सभी अच्छी सुविधाओं को लागू करने के लिए आंतरिक नहीं बदल सकते हैं।

डेटा भंडारण

के लिए और निश्चित रूप से हर किसी को कोई API अपने स्वयं अधूरा QObject करने वाली SQLite पुस्तकालय लिखता है। QDataStream हालांकि, एक बहुत अच्छी शुरुआत है।

कोई डेटा बाइंडिंग

ठीक है, क्यूटी त्वरित डेटा बाइंडिंग, लेकिन डेटा बाइंडिंग QtCore में रहते हैं चाहिए। सभ्य डेटा बाध्यकारी के साथ, QAbstractItemModels लिखना जो QObjects के संग्रह का प्रतिनिधित्व करते हैं, अतीत की बात होनी चाहिए: QObjectListModel आपको बस चाहिए।

कोई स्वत: पूर्ववत प्रबंधन QObjects के लिए (हाँ, QDataWidgetMapper एक मजाक है।)

हमारे मॉडल वर्गों आमतौर पर QObjects और Q_PROPERTY एक वैकल्पिक सूचित संकेत है कि वास्तव में क्या लागू करने की जरूरत उपलब्ध है या नहीं स्वचालित पूर्ववत करें। ऐसा करना इतना आसान है कि यह पहले से ही क्यूटी का हिस्सा होना चाहिए। (यह कुछ ही kludges तथापि की आवश्यकता है,।)

कोई संग्रह गुण

नहीं सभी गुण बराबर पैदा होते हैं। उनमें से कुछ संग्रह हैं। एक अमूर्त तरीके से उनसे निपटने में सक्षम होना निश्चित रूप से एक अच्छी बात होगी।

आधा बेक्ड QMetaStuff एपीआई

और मैं केवल इस एपीआई नफरत है क्योंकि मैं इसे प्यार करता हूँ। उदाहरण के लिए, कोई नहीं कर सकता:

  1. गतिशील रूप से QMetaObjects का निर्माण और उन्हें प्रतिस्थापित करें;
  2. तर्क के रूप में एक QVariants का उपयोग कर मेटा-विधि को कॉल करें;
  3. वापसी प्रकार, नाम या तर्क प्रकार के द्वारा क्वेरी विधियां;
  4. संबंधित QMetaMethods (at least not until 4.8) का उपयोग करके सिग्नल और स्लॉट कनेक्ट करें;
  5. अवरोध संपत्ति सेट/उसी तरह से प्राप्त करें जैसे आप घटनाओं को रोक सकते हैं, उदाहरण के लिए।

लगभग सभी को आसानी से काम किया जा सकता है। # 2 के लिए एक समाधान:

QVariant call(QObject* object, QMetaMethod metaMethod, QVariantList args) 
{ 
    QList<QGenericArgument> arguments; 

    for (int i = 0; i < args.size(); i++) { 

     // Notice that we have to take a reference to the argument. A 
     // const_cast is needed because calling data() would detach 
     // the QVariant. 

     QVariant& argument = args[i]; 

     QGenericArgument genericArgument(
      QMetaType::typeName(argument.userType()), 
      const_cast<void*>(argument.constData()) 
     ); 

     arguments << genericArgument; 
    } 

    QVariant returnValue(QMetaType::type(metaMethod.typeName()), 
     static_cast<void*>(NULL)); 

    QGenericReturnArgument returnArgument(
     metaMethod.typeName(), 
     const_cast<void*>(returnValue.constData()) 
    ); 

    // Perform the call 

    bool ok = metaMethod.invoke(
     object, 
     Qt::AutoConnection, // In case the object is in another thread. 
     returnArgument, 
     arguments.value(0), 
     arguments.value(1), 
     arguments.value(2), 
     arguments.value(3), 
     arguments.value(4), 
     arguments.value(5), 
     arguments.value(6), 
     arguments.value(7), 
     arguments.value(8), 
     arguments.value(9) 
    ); 

    if (!ok) { 
     // Handle the error... 
    } else { 
     return returnValue; 
    } 
} 

उपयोगी सुविधाओं शायद

क्यूटी-हित में बात करते हैं कि DOM, style sheets, और custom file engines क्यूटी के भविष्य के संस्करण में हटा दिया जाएगा नहीं है हटा दिया जाएगा।

फ़ोनॉन कोई पार मंच बैक-एंड है

वास्तव में हर समय काम नहीं कर इसके अलावा, फ़ोनॉन कोई स्थिर बैक-एंड कि तीन सबसे आम प्लेटफार्मों पर काम करता है: विंडोज, लिनक्स और मैक ओएस एक्स एक वीएलसी बैक-एंड है, लेकिन यह निश्चित रूप से स्थिर नहीं है, इसकी लाइसेंसिंग अस्पष्ट है और इसके अलावा, मैक के लिए वीएलसी समर्थन "resting on shaky ground" है। निश्चित रूप से दोष पूरी तरह से लिनक्स पर है। मल्टीमीडिया समर्थन में never beenone of its strengths है। इसमें क्विकटाइम या डायरेक्टस्टफ जैसी कुछ कमी नहीं है।

नहीं क्रिप्टो वर्ग

वहाँ QCryptographicHash और QSSLSocket (और इसके funny error modes) है, और बस इतना ही। सौभाग्य से, इस अंतर को भरने के लिए दो अच्छी पुस्तकालय हैं: Botan और QCA। क्यूसीए क्यूटी पर आधारित है, लेकिन जावा एपीपीओ कक्षाओं से इसकी एपीआई कॉपी करता है, इसलिए बहुत अच्छा नहीं है। बॉटन में निफ्टी इंटरफेस है और (लेकिन?) "शुद्ध" सी ++ है। एक क्यूटी शैली क्रिप्टो पुस्तकालय अभी भी कमी है।

+1

+1: यह वही है जो मैं ढूंढ रहा हूं, महान उत्तर। – Tuminoid

+1

+1: संपूर्ण उत्तर जो क्यूटी के आपके गहरे ज्ञान को प्रकट करता है। QMetaMethod के लिए – WolfgangA

+0

+1 QVariants का उपयोग करके आमंत्रित किया गया। क्या गलत तरीके से टाइप किए गए पैरामीटर प्रदान करना संभव है जिसे सही प्रकार से सही तरीके से डाला जा सकता है? मान लें कि मैं 'foo (long)' को कॉल करना चाहता हूं, क्या आपके समाधान को 'QVariant :: Int' के साथ कॉल करना संभव है? मुझे अपने ऐप में इसकी ज़रूरत है और वर्तमान में मैं वास्तव में एक गंदे हैक किए गए वैकल्पिक समाधान का उपयोग कर रहा हूं जिसे मैं छुटकारा दिलाना चाहता हूं। – leemes

11

यह इतना मंजूरी के लिए के लिए एक अजीब सवाल है, लेकिन यहाँ जाता है:

qmake दांत में लंबा है (और मैं not the only one to say so हूँ)। मैं अपनी खुद की अजीबता के बावजूद cmake का उपयोग करता हूं।

मेटा-ऑब्जेक्ट प्रीप्रोसेसिंग सिग्नल/स्लॉट/आदि के लिए चरण बनाएं। एक बड़ी खरीद है। और जो लोग अमूर्तता के अतिरिक्त स्तर को स्वीकार करने के इच्छुक होंगे वे ऐसे लोगों के प्रकार हैं जो अन्य वातावरण (जावा, सी #, जो कुछ भी है) के लिए आकर्षित होंगे। बाड़ के दूसरी तरफ कट्टर सी ++ प्रोग्रामर हैं जो QThread के बजाय std::thread के साथ काम करेंगे।

(एक सी ++ प्रोग्राम है, तो अधिक सर्वर उन्मुख और कोई जीयूआई है, लोगों को क्यूटी से बचने के लिए लगता है, और मैं उनके नज़रिए से देखते हैं।)

मॉडल/दृश्य न यहाँ और न ही वहाँ है, लेकिन यह है तुच्छ का प्रकार मैं धागा आत्मीयता के मुद्दों की आलोचना की है:

http://blog.hostilefork.com/qt-model-view-different-threads/

इसके अलावा, मैंने पार संकलित मैक और विंडोज और लिनक्स, के लिए एप्लिकेशन और पाया क्यूटी के रूप में ज्यादा मंच मुद्दों से मुझे की रक्षा नहीं करता मैं हो सकता है ' कामना की यदि आप इंटर्नल्स को देखते हैं और ड्रैग और ड्रॉप को बेहद विविध कोड (उदा। qnd_x11.cpp, qdnd_win.cpp, और qdnd_mac.mm) द्वारा लागू किया गया है तो आप देखते हैं कि "Leaky Abstraction" सिद्धांत खेल में आता है। क्यूटी मजबूत औपचारिकता लागू नहीं करता है; आपको अलग-अलग क्रम में या डुप्लिकेट में प्राप्त होने वाले संदेश मिलते हैं - या कुछ प्लेटफ़ॉर्म पर नहीं।

लेकिन सभी आलोचनाएं अलग-अलग हैं, मुझे क्यूटी के डिजाइन, दस्तावेज़ीकरण, सामुदायिक समर्थन और सामान्य सौंदर्यशास्त्र पसंद है। आप बहुत खराब कर सकते हैं!

 
void MainDialog::OnCppException() 
{ 
    throw std::runtime_error("test unhandled exception"); 
} 

इस तरह के बिना क्रिया C++ अपवाद पकड़ा है: (। मैं तुम्हें, wxWidgets और जीटीके पर देख रहा हूँ)

+1

होना चाहिए, आपको कभी-कभी मूल्यवान जानकारी मिलती है: लोग किसी चीज़ से नफरत करते हैं/नाराज होते हैं और वे एक ही चीज को संभवतः बेहतर तरीके से बेहतर तरीके से कर सकते हैं। मुझे क्यूटी भी पसंद है, इसलिए यह बेवकूफ सवाल नहीं है :) – Tuminoid

5
समस्या मैं हल करने की कोशिश की

क्यूटी, wxWidgets और संभवतः अन्य यूआई चौखटे के लिए सामान्य है क्यूटी फ्रेमवर्क द्वारा, तत्काल अपवाद डीबगिंग को रोकने या सूचनात्मक क्रैश डंप उत्पन्न करना। उस स्थान पर जहां क्यूटी इस स्थिति को संभालने की अनुमति देता है, मूल अपवाद जानकारी और ढेर का निशान खो जाता है। मैंने दोनों ढांचे में इस समस्या से लड़ने की कोशिश की, और स्वीकार्य समाधान नहीं मिला। क्यूटी पेशेवरों की सलाह "बस यह मत करो" मेरे पास सब कुछ है, इसका वास्तव में मतलब है: बग मत बनाओ, और सब ठीक हो जाएगा। यह क्यूटी और WxWidjets से मेरी सबसे बड़ी निराशा थी।

1

मैं ज्यादातर एस 60 पर्यावरण के लिए क्यूटी पर काम कर रहा हूं, इसलिए कुछ मुद्दे उस मंच के लिए विशिष्ट हैं।

प्लगइन प्रणाली + QObjects

आप संकेतों के साथ प्लगइन इंटरफ़ेस की घोषणा नहीं कर सकते क्योंकि प्लगइन कार्यान्वयन QObject और कई इंटरफेस से प्राप्त करने की अपेक्षा की जाती है, तो इंटरफ़ेस QObject ही (नहीं होना चाहिए आवश्यक अगर आप चाहते हैं आपके इंटरफेस में कुछ सिग्नल)। क्यूटी-ब्याज मेलिंग सूची पर मिले वर्कअराउंड में आपके प्लगइन इंटरफ़ेस में MyQObject * गेटटर जोड़ना और MyQObject क्लास को कंक्रीट करने के लिए सभी सिग्नल जोड़ना शामिल है। यह काम करता है, लेकिन यह counterintuitive और बदसूरत है।

QSet और अन्य क्यूटी कंटेनरों एसटीएल से कम बहुमुखी हैं या कंटेनर

उदाहरण के लिए यदि आप कम समारोह है कि जब QSet में तत्वों डालने इस्तेमाल किया जाना चाहिए परिभाषित नहीं कर सकते हैं को बढ़ावा देने के। मुझे याद रखने वाली अन्य चीजें remove_if और find_if है। QtMobility पैकेज में

QServiceFramework

हास्यास्पद पुस्तकालय मैं हाल ही में उपयोग करने के लिए मजबूर किया गया। QServiceFramework में स्थापित "सेवा" का उपयोग करने के लिए आपको या तो उस सेवा को शामिल करना होगा जिसमें वह सेवा शामिल है (जो कि काफी व्यर्थ है, क्योंकि QSf लक्ष्यों में से एक निर्भरता को छिपाना है) या QMetaObject :: invokeMethod का उपयोग करें जो संकलन प्रदान नहीं करता है विधियों, तर्क प्रकार, आदि के टाइम जाँच और कोड पठनीयता कम कर देता है:

// using QMetaObject::invokeMethod 
QVariantHash data; 
bool ok = QMetaObject::invokeMethod(myObject, "getStuff", 
    Q_RETURN_ARG(QVariantHash, data) 
    Q_ARG(QString, QString("blah"))); 
Q_ASSERT(ok); 

// using normal syntax 
QVariantHash data(myObject->getStuff("blah")); 

चीजों को बदतर बनाने के लिए, यह फाइल सिस्टम काफी एक बहुत का उपयोग करता है (प्लग इन, SQLite डेटाबेस के साथ संचार के लिए देख dirs पुनरावृत्ति) है, जो S60 पर एक धीमी ऑपरेशन।

QPixmap QApplication ...

की आवश्यकता है ... और केवल QPixmap देशी S60 छवियों (CFbsBitmap वर्ग) और क्यूटी डेटा के बीच रूपांतरण के लिए तरीकों की है। तो आपको या तो अपने ऐप को क्यूप्लिकेशंस बनाना होगा (जो स्टार्टअप टाइम्स और मेमोरी खपत को बढ़ाता है) या आपको मूल एस 60 संरचनाओं में डेटा स्टोर करना होगा (जो पूरे कोड सिम्बियन विशिष्ट बनाता है)

+7

अधिकांश क्यूटी कंटेनर एसटीएल एल्गोरिदम के साथ संगत हैं, ताकि आप हमेशा remove_if और find_if पर कॉल कर सकें। –

+0

दिलचस्प, मुझे इसके बारे में पता नहीं था। धन्यवाद! – chalup

+2

आप प्लगइन इंटरफ़ेस में शुद्ध वर्चुअल सिग्नल घोषित कर सकते हैं। – andref

1

मुझे वही समस्या थी, जो संस्करण तर्कों के साथ एक विधि का आह्वान करने की कोशिश कर रहा था। मैंने यहां इस मुद्दे की सूचना दी: https://bugreports.qt-project.org/browse/QTBUG-28833

उन्होंने वास्तव में समस्या के आसपास काम करने के लिए अनियंत्रित कार्यान्वयन विवरण का उपयोग करने की सिफारिश की। तो मुझे लगता है कि इसे यहां लिंक करने के लायक है।

इस मुद्दे को अंत में स्वीकार किया गया था (प्राथमिकता कम और केवल क्यूटी 5 के लिए)।

संबंधित मुद्दे

 संबंधित मुद्दे