• 0
commando161

Slot(settext()) لا تعمل

سؤال

السلام عليكم و رحمة الله و بركاته

انا حاليا اتعلم مكتبة Qt لعمل برامج GUI و قد اخترت Qt تبعا لنصيحة الكثير اولهم اختى العزيزة رغد .

ندخل فى الموضوع , انا اعمل على برنامج قمة فى البساطة , فكرته فى انى عندما ادوس على زر QPushButton يتم كتابة نص معين فى صندوق نصى QLineEdit

هذا هو الكود :

انسخ الكود
  1.  
  2. #include <QApplication>
  3.  
  4. #include <QWidget>
  5.  
  6. #include <QtGui>
  7.  
  8. class Connection : public QWidget
  9.  
  10. {
  11.  
  12. public:
  13.  
  14. Connection();
  15.  
  16. private:
  17.  
  18. QLineEdit* lineEdit;
  19.  
  20. QPushButton* bt;
  21.  
  22. QWidget* window;
  23.  
  24. QHBoxLayout* layout;
  25.  
  26. };
  27.  
  28. int main(int argc, char* argv[])
  29.  
  30. {
  31.  
  32. QApplication app(argc, argv);
  33.  
  34. Connection *conn = new Connection;
  35.  
  36. return app.exec();
  37.  
  38. }
  39.  
  40. Connection::Connection()
  41.  
  42. {
  43.  
  44. window = new QWidget;
  45.  
  46. lineEdit = new QLineEdit;
  47.  
  48. bt = new QPushButton("Make Connection");
  49.  
  50. layout = new QHBoxLayout;
  51.  
  52. QObject::connect(bt, SIGNAL(clicked()), lineEdit, SLOT(setText("Omar")));
  53.  
  54. layout->addWidget(bt);
  55.  
  56. layout->addWidget(lineEdit);
  57.  
  58. window->setWindowTitle("Connection");
  59.  
  60. window->setLayout(layout);
  61.  
  62. window->show();
  63.  
  64. }
  65.  
  66.  
  67.  
  68.  
  69.  

المشكلة فى سطر جملة connect

انسخ الكود
  1.  
  2. QObject::connect(bt, SIGNAL(clicked()), lineEdit, SLOT(setText("Omar")));
  3.  

انا انشئت connection بين QPushButton اسمه bt و QLineEdit اسمه lineEdit وفعندما يتم الضغط على الزر bt يتم تنفيذ setText

و لكن المشكلة انه لا يتم التنفيذ فالبرنامج يعمل بدون اى مشاكل لكن الكود لا ينفذ .

استعنت بـ Qt Assistant و لكن لا جدوى .

فما هى المشكلة ؟ اتمنى ان نجد الحل سويا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

14 إجابة على هذا السؤال .

  • 0

سارد بعد قليل

تم تعديل بواسطه مصفوفة
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

اهلا اخي Omar Eladel ::

المشكلة في هذا السطر :

QObject::connect(bt, SIGNAL(clicked()), lineEdit, SLOT(setText("Omar")));

والسبب هو ان الـ SIGNAL/SLOT لا تقبل الا انواع الوسائط Parameter Type وليس قيم الوسائط !

يعني يجب ان تكون عبارة الربط بهذا الشكل :

QObject::connect(bt, SIGNAL(clicked()), lineEdit, SLOT(setText(const QString &)));

وايضا توجد مشكلة اخرى وهي ان الاشارة التي تبعث من الزر clicked ، لا ياتي منها string حتى يعرض على lineEdit ، لذا تحتاج الى تعريف slot جديد للفئة Connection .

مثلا شوف عملية الربط بين كائن QSpinBox و QSlider :

connect(spinBox,SIGNAL(valueChanged(int)),slider,SLOT(setValue(int)));

العملية هنا صحيحة ، لان spinBox عندما تغير قيمته فان القيمة الجديدة سترسل الى slider .

والحل في مثالك هو تعريف دالة slot جديدة ، والربط كالاتي :

QObject::connect(bt, SIGNAL(clicked()), this, SLOT(display()));

تعليق على الكود :

1- بما ان الفئة Connection ترث من QWidget فهي بالتالي ترث من QObject اذا لا تحتاج الى كتابة عبارة الـ QObject::connect بهذا الشكل ، وانما يكفي :

connect(bt, SIGNAL(clicked()), this, SLOT(display()));

2- الفئة Connection ترث من QWidget ، اذا لا تحتاج الى انشاء QWidget داخلها ، لان الفئة نفسها هي QWidget "مفهوم الوراثة" .

3- هذا السطر :

window->show();

يعني عند انشاءك للفئة فيجب ان تظهر ، وهو حل ليس خاطئ ولكن لا يحبذ .

ويفضل ان تستبدله بهذا السطر داخل الدالة main

conn->show();

وهذا هو البرنامج بعد التعديل واضافة زر اخر للمسح ، حتى تتضح لك عملية الربط:

+++++++++++++++++++++++

ملف connection.h

#ifndef CONNECTION_H

#define CONNECTION_H



#include <QWidget>

class QLineEdit;



class Connection : public QWidget
{
Q_OBJECT
public:
Connection(QWidget* =0);

public slots:
void display();
void clear();

private:
QLineEdit* lineEdit;
};

#endif

ملف connection.cpp

#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>

#include "connection.h"

Connection::Connection(QWidget* parent):
QWidget(parent)
{
lineEdit = new QLineEdit;
QPushButton* showButton = new QPushButton("Make Connection");
QPushButton* clearButton = new QPushButton("Remove Connection");
QHBoxLayout* layout = new QHBoxLayout;

connect(showButton, SIGNAL(clicked()), this, SLOT(display()));
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));

layout->addWidget(showButton);
layout->addWidget(clearButton);
layout->addWidget(lineEdit);
setWindowTitle("Connection");
setLayout(layout);

}


void Connection::display()
{
lineEdit->setText("Omar");
}

void Connection::clear()
{
lineEdit->clear();
}

ملف main.cpp :

#include <QApplication>
#include "connection.h"

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
Connection *conn = new Connection;
conn->show();

return app.exec();

}

ملاحظة اخيرة ، لكي تمسك الاخطاء الناتجة من SIGNAL/SLOT -اخطاء لا يمسكها المترجم- ، يجب ان تضيف السطر الاتي الى ملف المشروع .pro :

CONFIG+=console

وهذا اذا كنت تعمل في ويندوز ، اما في لينوكس فشغل البرنامج من سطر الاوامر فقط .

وشكرا ،

اي سؤال ..

تم تعديل بواسطه SudaNix
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

مايحتاج تم الرد

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

اشكرك شكرا جزيـــلا اخى SudaNix

طب لو افترضنا ان انا عايز ادخل String معينة و اطبعها , ما الحل ؟

هل الحل يكون :

void Connection::display(QString str)
{
lineEdit->setText(str);
}

و استخدمها بالشكل التالى :

connect(showButton, SIGNAL(clicked()), this, SLOT(display(str)));

سؤال اخر :

المؤشر this , يؤشر لماذا ؟؟

شكرا جزيــلا

وفقكم الله

تعديل : سؤال اخر :

لماذا لم تعرف الـ QPushButtons مثلما عرفنا QLineEdit فى متغيرات private فى تعريف الـ Class ؟

تم تعديل بواسطه Omar Eladel
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

اهلا اخي عمر ..

connect(showButton, SIGNAL(clicked()), this, SLOT(display(str)));

كما ذكرت لك ، لا تستطيع تمرير متغيرات او قيم ، فقط انواع بيانات ، وكيوتي تتكفل بنقل القيمة .

المشكلة الاخرى هي عدم توافق الاشارة مع ال SLOT ، يجب ان يكونوا متطابقين في النوع ، يعني في مثالنا الاشارة يجب ان تكون بهذا الشكل

clicked(const QString&)

وهو خطأ !

لذلك فالحل الوحيد هنا هو تعريف slot جديد للفئة Connection

اما المؤشر this يعني ان ال slot موجودة في الفئة Connection .

لماذا لم تعرف الـ QPushButtons مثلما عرفنا QLineEdit فى متغيرات private فى تعريف الـ Class ؟

سؤال جيد ، لاننا لا نحتاج اليهم كمتغيرات private .

المتغير private وظفيته انه يكون متاح فقط لكل الدوال داخل الفئة .

وفي مثالنا لا يوجد لدينا دوال سوى دالة البناء ودالتين slot .

الدالتين slot وهما clear و display ، يحتاجان الوصول فقط الى lineEdit

ولا يحتاجان الى layout و button ، لذلك انشاناهم داخل دالة البناء .

ولا تخاف انه يحصل Memory Leak بسبب فقدان قيم المؤشرات ، وذلك لان Qt تستخدم علاقة Parent-Child لكل الفئات المشتقة من QObject ، والدالة setLayout ستقوم بوضع ال layout على كائن Connection وبالتالي تفرض علاقة Parent-Child تلقائيا .

ولكي تفهم الفكرة افضل ، جرب اولا هذا المثال ، حيث لا يحتاج الى تعريف slot جديد :

#include <QApplication>
#include <QSpinBox>
#include <QSlider>
#include <QHBoxLayout>

int main(int argc,char* argv[])
{
QApplication app(argc,argv);

QWidget widget;
QSpinBox* spinbox=new QSpinBox;
QSlider* slider=new QSlider(Qt::Horizontal);

QObject::connect(spinbox,SIGNAL(valueChanged(int)),slider,SLOT(setValue(int)));
QObject::connect(slider,SIGNAL(valueChanged(int)),spinbox,SLOT(setValue(int)));

QHBoxLayout* layout=new QHBoxLayout;
layout->addWidget(spinbox);
layout->addWidget(slider);

widget.setLayout(layout);
widget.show();

return app.exec();
}

هنا تم الربط ببساطة ! لماذا ؟

لان الاشارة مطابقة "في النوع" مع الslot لذلك تم تنفيذها .

حيث في المرة الاولى تم ربط التغيير في قيمة ال spinBox مع slider

والمرة الثانية تم العكس .

لاحظ انه لا يجب ان ترسل القيمة فقط النوع !

شكرا لك .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
3- هذا السطر

window->show();

يعني عند انشاءك للفئة فيجب ان تظهر ، وهو حل ليس خاطئ ولكن لا يحبذ .

ويفضل ان تستبدله بهذا السطر داخل الدالة main

conn->show();

اخى العزيز , انا لم افهم هذا الجزء جيدا .

هل معناه ان عند اظهار الـكائن conn يظهر معه كل اولاده ؟ (الابن هنا هو الكائن parent )

و هل parent هو والد كل الـ Widgets فى البرنامج (lineEdit , showButton , clearButton , layout ) ؟

ما هو احسن كتاب لتعليم Qt ؟

بارك الله فيك و اكرمك

وفقكم الله

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

نعم عند اضهار الوالد يضهر جميع الأبناء

والأبناء هنا يكونون ملتصقين به اما ب layout او setParent او عن طريق دالة البناء

في جميع هذه الأحوال الأب يتلقى جميع الأحداث بداخلهم بدون اي استثناء

الا اذا وكلت احداث الأب الى عناصر أخرى .

وبالنسبة للكتب

http://qt-ar.org/books/indexcat-1.html

شوف الكتاب الأول والثالث والرابع جدا مفيدين الأول يعتبر مرجع كامل

والله الموفق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم و رحمة الله و بركاته

انا جربت هذا الكود

void Connection::display()
{
QString str;
str = "AAAAAA";
lineEdit->setText(str);
}

و الكود يعمل 100% الان

-----

الان لى سؤال اخر , لو افترضنا انى سأكتب برنامج له نفس الوظيفة مثل البرنامج الذى كنا نناقشه لكن لا اريد عمله بطريقة OOP ؟

- كيف سأعرف SLOT جديد ؟

- ما هو البديل للمؤشر this ؟

connect(showButton, SIGNAL(clicked()), this , SLOT(display(str)));

بارك الله فيكم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ليس من الضروري استخدام المؤشر this لكي يتصل هي في النهاية مرسل ومستقبل

وبالنسبة ل slot خارج اطار كائن فهنا أنتفت الحكمة فلم يحدث ربط بين الكائنات لأن slot ليس لديها كائن بكل بساطة وطبعا عند انشاء كائن جديد فإنك تضع بعد التصريح عن الصف Q_OBJECT وهو الذي يعرف الاشارات والمستقبلات آمل انه قد وصلك المفهوم .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

للاسف مش فاهم اى حاجة :blink: :wacko:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

اجل نشرحها

انت عندك signal و slot (مرسل ومستقبل)

من تعريفهم هي عملية الربط بين الكائنات

وفيما بعد سوف تتعرف ايضا انها تربط بين المسالك (مستوى متقدم)

من تعريفها انها تربط بين الكائنا اي ان كل منهما لهما كائن يحتويه class

فمثلا

QObject::connect(bt, SIGNAL(clicked()), lineEdit, SLOT(setText(const QString &)));

ربط بين الكائنين bt و lineEdit فال signal مأخوذ من bt ويستقبله ال slot في lineEdit

طيب لو أفترضنا انك صرحت عن slot او signal خارج اطار صف class

فإنه بالتأكيد الحكمة من ربط الكائنات عن طريقهم انتفت والسبب وبكل بساطة ان ليس لديهم كائنات .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

انا فهمت كده انهم لن يعملوا , لأن ببساطة لا يوجد اصناف تحتوى هذه الكائنات

هل ما فهمته صحيح ؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

مرحبا اخي عمر ،،

الان لى سؤال اخر , لو افترضنا انى سأكتب برنامج له نفس الوظيفة مثل البرنامج الذى كنا نناقشه لكن لا اريد عمله بطريقة OOP ؟

- كيف سأعرف SLOT جديد ؟

- ما هو البديل للمؤشر this ؟

connect(showButton, SIGNAL(clicked()), this , SLOT(display(str)));

بارك الله فيكم

قبل ان ارد على السؤال ، ساضع معلومة بسيطة قد تساعد كثيرا في فهم الاجابة ..

كل الـ classes التي ترث من QObject لديها اشارات signals ترسلها ، ولديها دوال slots لتنفيذ شيء معين .

مثلا الكلاس QPushButton ، عندما تقوم بضغط الزر فان الاشارة clicked تبعث تلقائيا .

وكل ما على المبرمج حاليا هو ربط الاشارة باستخدام الدالة connect .

الدالة connect شكلها العام :

connect(sender,signal,receiver,slot)

حيث يتم ربط اشارة معينة signal من الكلاس sender مع دالة معينة من الكلاس receiver.

الشرط الاساسي بين الـ signal و الـ slot هو ان تتطابق في نوع البيانات Data type.

يعني اذا كانت الـ signal هي clicked() فكما نلاحظ هي لا تحوي ولا اي نوع بيانات ، اذا بالتالي يجب ربطها مع دالة slot لا تاخذ اي نوع بيانات .

هذه الفكرة بشكل عام ، لكن حتى لا نقع في مشاكل نقص ال signal و slot في كلاس ما ،، فان Qt اعطتك الحرية في انشاء signal و slot لاي كلاس تنشئه .

طيب نرجع الى مثالك ، انت تريد ان يظهر اسمك على lineEdit في حالة تم الضغط على button .

الاشارة التي يجب ربطها من الكلاس QPushButton هي clicked()

والشيء الذي تريد تنفيذه وهو كتابة نص على QLineEdit يتم بالدالة setText(const QString&)

وكما تلاحظ لن تستطيع الربط هنا ، لوجود اختلاف في نوع البيانات !

اذا ما هو الحل ؟

الحل الصحيح هنا هو انشاء فئة جديدة مثلا Connection لكي نستطيع تعريف slot خاص بها .

الـ slot الجديد يجب ان لا يحوي وسائط ، لكي يطابق الاشارة clicked ويتم الربط بشكل صحيح.

اذا الاجابة على تساؤلاتك :

1- يجب ان تنشئ كلاس جديد لكي تعرف slot جديد.

2- عملية الربط ستكون بين الاشارة clicked والـ slot الجديد والذي هو موجود داخل الفئة Connection لذلك استخدمنا المؤشر this دلالة على ان ال slot الجديد موجود فيها .

اي سؤال ؟

وتقبل تحياتي .

سلام.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بارك الله فيك اخى SudaNix

انا كده فهمت انى حتى انشئ slot او signal جديدة يجب ان انشئ كلاس حتى اعرفهم داخله لاستخدم المؤشر this

فبدون هذه الكلاس , لا ينفع تعريف slots جديدة

شكرا جزيلا

وفقكم الله

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .