1. Ruby/Qt tutorial
كدا انهينا RubyGnomeو wxRubyنستكمل رحلتنا مع Ruby/Qt
Qtهى اداة تطوير تطبيقات toolkitكانت مملوكة لشركة trolltechحتى استحوذت عليها Nokia
من مميزاتها انها عابرة للنظم CrossPlatform
تنقسم Qtللعديد من الوحدات
--اعجوبة 4pyqt
الوحدة QtCoreتحتوي الوظائف المركزية غير الرسومية. تستخدم هذه الوحدة في التعامل مع الوقت
والملفات والدلة )المجلدات( وأنواع البيانات المختلفة والسيالت streamsوروابط URLوأنواع الملفات
MIMEوالعمليات .processes and threads
الوحدة QtGuiفتحتوي على المكونات الرسومية وما يتعلق يها من صنوف. وتشتمل على سبيل المثال
على الزرار والنوافذ وأشرطة الدوات والحالة والزلقات والصور النقصية واللوان والخطوط …إلخ.
الوحدة QtSVGبها الصنوف اللزمة لعرض محتويات ملفات .SVGوهي لغة وصفية للرسومات المتجهية
ثنائية البعاد والتطبيقات الرسومية ب XML
الوحدة QtOpenGLتستخدم لتوليد رسومات ثلثة البعاد أو ثنائية باستخدام مكتبة .OpenGLمما يمكننا
من دمج Qtمع OpenGLدون عناء.
الوحدة QtNetworkتحتوي على الصنوف اللزمة لبرمجة الشبكات. هذه الصنوف تسمح بكتابة برامج
خوادم seversأو مخدومات clientsلبروتوكولت TCP/IPو .UDPمما يجعل برمجية الشبكات أسهل
وقابل للنقل لمنصات أخرى.
الصنوف في الوحدة QtXmlللعمل على ملفات .xmlهذه الوحدة تقدم تطبيق ل SAXو .DOM
الوحدة QtSqlتقدم صنوف التعامل مع قواعد البيانات.
--اخر القتباس
2. البرنامج الول
عرضلنا ويدجت عليها titleمكتوب عليه !Hello, QtRubyوبمساحة 003 عرض و 002 ارتفاع
1- ضيف ال 4 Qtلساحة العمل
"4require "Qt
2- انشئ application objectليعبر عن التطبيق )لحظ هو applicationواحد فقط الذى يتم انشائه(عن
طريق
Qt::Application.new
كالتالى
)app=Qt::Application.new(ARGV
بيتم تجهيزه بال ARGVاللى هتتباصى للبرنامج
3- انشئ الويدجت بإستخدام ال Widget class
w=Qt::Widget.new
4- حدد ال titleبإستخدام الميثود setWindowTitleالموجودة بال w object
"!w.setWindowTitle "Hello, QtRuby
5- اعمل اعادة تحديد للمساحة بإستخدام الميثود resizeالموجودة بال w object
w.resize(300, 200) #width, height
6- اظهر ال widget
w.show
7- نفذ ال applicationبإستخدام ال exec methodالموجود بال app object
app.exec
رائع جدا بس مش هو دا اللى عايزينه احنا عايزين نكتب ب إسلوب *افضل*
انشئ classبإسم MyWidgetفى my_widget.rbعلى فرض ان ال entry pointللبرنامج هتكون دائما
main.rb
class MyWidget < Qt::Widget
def initialize
)( super
init_comp
end
3.
end
.. على الويدجت او الفورم الخcomponents دى هتكون الميثود المسئولة عن تجهيز الinit_comp ال
وفى المثال هنا معرفة كالتالى
def init_comp
setWindowTitle('Hello, World!')
#resize(200, 300) #w, h
setGeometry(300, 300, 250, 150) #x, y, w, h
setToolTip("Simple Widget")
setWindowIcon(Qt::Icon.new('icons/apps/preferencesdesktopremotedesktop')) #Set Icon..
end
setToolTip وsetWindowIcon وsetGeometry فى حاجات جديدة وهما
.setGeometry(x, y, w, h)
.setToolTip
tooltip لعرض
ايضاmarkup تقدر تحط فيها
.setWindowIcon
لتحديد ايكون على الويدجتIcon object وبتاخد
سهل مش كدا؟؟
4. عايزين ننشئ حاجة مشابهه لكدا
تمام ويدجت وعليه buttonمكتوب عليه !Click Me
اوكى تمام هنحتاج نتكلم الول عن الستراتيجى بتاعتنا
اول الويدجت بأبسط صورة عبارة عن مستطيل كدا
محتاجين نضيف ليه حاجة اسمها Layoutلنقدر نضيف اى ويدجتس اخرى جواه )اسلوب مشهور جدا(
ال Layoutدا عبارة عن صندوق داخلى جوا الويدجت الصلى
5. ممكن يشمل Layoutsاخرى وممكن يشمل فى نفس الوقت كنترولز )راجع جزئية ال RubyGnome
بخصوص ال (Hbox, Vbox
المهم فى عندنا اكتر من نوع لل Layoutفى افقى وفى رأسى.. الفقى بيتم فيه اضافة الويدجتس/اللي
اوتس بصورة افقيه والرأسى بيتم إضافتهم بصورة رأسية..
مثل اللى داخل الويدجت دا الفقى
وعند إضافة كنترولز بيتم التحجيم وتجهيز مكان جديد للضافة مثل
اما الرأسى فبيتم الضافة رأسيا كما فى الصورة التالية مثل
6. Vbox بيكونMain داخلية بس الLayouts الرئيسى هو رأسى وبعمل جواهLayout انا ديما بعتبر ان ال
تعالى نجرب مثال على الضافة الرأسية
def init_comp
setWindowTitle('Hello, World!')
#resize(200, 300) #w, h
setGeometry(300, 300, 250, 150) #x, y, w, h
setToolTip("Simple Widget")
setWindowIcon(Qt::Icon.new('icons/apps/preferencesdesktopremotedesktop')) #Set Icon..
vlay=Qt::VBoxLayout.new
#add 5 buttons vertically!
(1..5).each { |i|
vlay.addWidget(Qt::PushButton.new(i.to_s))
}
setLayout(vlay)
end
VboxLayout class رأسى إستخدامLayout لنشاء
text وباصى للمشيد الPushButton class استخدمpush button لنشاء
addWidget استخدمlayout لضافة ويدجت معين ل
7. setLayout الساسى استخدمLayout لتحديد ال
طب لو افقى ؟ تقدر تطبق نفس السابق كالتالى
vlay=Qt::VBoxLayout.new
hlay=Qt::HBoxLayout.new {|lay|
(6..10).each{|i|
lay.addWidget(Qt::PushButton.new(i.to_s))
}
vlay.addLayout(lay)
addLayout معين استخدم الميثودlayout لLayout لضافة
طب لو عايزين نضيف التنين بنفس الوقت ال 5 الرأسى وال 5 الفقى ؟
التصميم
9. هى إشارة بتتبعت من وإلىsignal ال
هى ال هاندلر زى مابنقول او الميثود اللى هيتم تنفيذها حين وصول الشارة من اوبجكت معينslot ال
ليه كذا سيجنال ممكن يرسلها )بناء على التفاعل مع المستخدم او تغير فى الحالة( زىbutton مثال ال
صح؟هيتم ارسالها إلى مين؟clicked
يتم تنفيذها حين الضغط فالمستخدم لوslot تمام لو مش اتحددتbutton الى ال ويدجت اللى فيه ال
يعنىhandler اوmethod ضغط من هنا لمليون سنة قدام مش هيحصل تغيير فكل اللى عليك تنشئ
.. دىSIGNAL دى فيتم تنفيذها كل مرة تتبعت الSIGNAL وتربطها بالSLOT وتعرفها على انها
هنشوف حال فى المثال دا
class MyWidget < Qt::Widget
slots 'onBtnClickMeClicked()'
def initialize
super()
@times=0
init_comp
end
def init_comp
setWindowTitle('Hello, World!')
#resize(200, 300) #w, h
setGeometry(300, 300, 250, 150) #x, y, w, h
setToolTip("Simple Widget")
vlay=Qt::VBoxLayout.new
#Add a button..
@btnclickme=Qt::PushButton.new("Hi")
connect(@btnclickme, SIGNAL('clicked()'), SLOT('onBtnClickMeClicked()'))
vlay.addWidget(@btnclickme)
setLayout(vlay)
end
def onBtnClickMeClicked
Qt::MessageBox::information(self, "Hello!", "Welcome to Qt!")
10. end
لحظ السطر
slots 'onBtnClickMeClicked()'
SLOTs هنا بنعرف مصفوفة من الميثودز اللى عايزينها يتم اعتبارهم
دا بإنه الساسى للويدجتlayout وحددنا الlayout وضفناه للbutton رأسى وضفنا ليهlayout انشأنا
كالتالىslot onBtnClickMeClicked تحديدا بالbtnclickme@ المرسل من الclicked ربطنا الحدث
connect(@btnclickme, SIGNAL('clicked()'), SLOT('onBtnClickMeClicked()'))
معرفة كالتالىonBtnClickMeClicked ال
def onBtnClickMeClicked
Qt::MessageBox::information(self, "Hello!", "Welcome to Qt!")
end
هى بوينترself وWelcome to Qt ! وفى المحتوى مكتوبHello مكتوبtitle بتعرض لينا رسالة فى ال
للب
Click Me المثال الشهير
بعد الضغط 6 مرات
الفكرة العامة ان يبقة عندنا متغير نحسب فيه عدد الضغطات ودى نقدر نحسبها بإننا نتتبع كل ضغطة
معينlabel وبعد كدا نعدل التكست علىbutton تتم على ال
class MyWidget < Qt::Widget
slots 'onBtnClickMeClicked()'
def initialize
super()
@times=0
12. setLayout(vlay)
بقةslot تمام تعريف ال
def onBtnClickMeClicked
@times += 1 #Inc times.
updateCounterLabel
end
بإستدعاءlabel بمقدار 1 عند كل استدعاء وعمل تحديث للtimes@ هتقوم بزيادة المتغير
المعرفة كالتالىupdateCounterLabel
private
def updateCounterLabel
@lblcounter.setText("Clicked: #{@times}")
end
تم انشائهم كالتالىspinner وعندناslider هنا عندنا
slider=Qt::Slider.new(Qt::Horizontal)
slider.setRange(0, 100)
spinner=Qt::SpinBox.new
spinner.setRange(0, 100)
وبتاخد معاملين قيمة صغرى وقيمة كبرىsetRange تم تحديد مداهم بإستخدام ال
ممكن يكون افقى او رأسى ودى بتحددها من خلل المشيد بتحديد التجاه من خللslider لحظ ال
Qt::Vertical اوQt::Horizontal
بإستخدام الspinner بإنها تحدث القيمة دى على الslider نربط حدوث اى تغيير فى القيمة الخاصة بال
valueChanged, setValue
connect(slider, SIGNAL('valueChanged(int)'), spinner, SLOT('setValue(int)'))
كالتالىslider بتحديث القيمة على الspinner ونفس الشئ نربط اى تغيير فى القيمة الخاصة بال
connect(spinner, SIGNAL('valueChanged(int)'), slider, SLOT('setValue(int)'))
layout نضيفهم لل
vlay.addWidget(slider)
vlay.addWidget(spinner)
الساسىlayout نحدد ال
setLayout(vlay)
13. Menus/ToolBars
تمام برامج كتير بتعرض وظايفها على صورة منيو واهم الوظايف فيها على صورة toolbarمثل اى
تكست اديتور
تمام Qtبتنتهج اسلوب للتعامل اسمه ال actionsال actionبيعبر عن اى itemظاهر فى منيو او فى
تولبار بيسمى actionال actionدا ليه عدة وظايف مثل صورة عليه.. اختصار.. نص مساعدة!
فى المثال القادم هننشئ حاجة مشابهه لكدا
15. connect(newaction, SIGNAL("triggered()"), SLOT("onNew()"))
المشيد الخاص بيه بياخد 3 معاملت الول عبارة عن اليكونAction class استخدمAction لنشاء ال
والتانى التسكت والتالت هو النافذة اللى بينتمى ليها
action object الموجود بالsetShortcut استخدمShortcut لتحديد ال
action object الموجودة بالsetStatusTip استخدمstatus tip لتحديد ال
connections ودى هى اللى بنربطها فى حال انشاء الtriggered المسماه بSGINAL ليه الaction وال
exitaction=Qt::Action.new("Exit", self)
exitaction.setStatusTip("Exit..")
connect(exitaction, SIGNAL('triggered()'), $qApp, SLOT('closeAllWindows()'))
بالتكست فقط والنافذة البAction نفس السابقة انشأنا
status tip حددنا ال
qApp$ الخاصة بالSLOT closeAllWindows بالaction الصادرة من الtriggered signal اخيرا ربطنا ال
...application object ؟ متغير عام بيشير للqApp$ ماهو ال
معرفة مسبقا لغلق كل النوافذ ومن ثم غلق البلكيشنSLOT هىcloseAllWindows ال
فى الويدجتstatusbar عند اول استدعاء ليها هتقوم بإظهار الstatusBar
إضافة منيو
mbar=menuBar #fetch it.
filemenu=mbar.addMenu("&File")
filemenu.addAction(newaction)
filemenu.addAction(openaction)
filemenu.addSeparator
filemenu.addAction(exitaction)
editmenu=mbar.addMenu("&Edit")
editmenu.addAction(copyaction)
editmenu.addAction(cutaction)
.. ميثود او تقدر تستخدمها مباشرة فى كل مرة حسب راحتكmenuBar اول خد رفرنس من ال
menuBar object الموجودة بالaddMenu. لنشاء منيو استخدم
اللى جهزته مسبقاaction وباصي ليها الaddAction لمنيو معينة استخدمaction لضافة
addSeparator. استخدمseparator لضافة
menu object من الaddMenu. لضافة منيو داخلية استخدم
التعامل مع التولبار
معaddToolBar او كدا استخدمfile menu لضافة جزء جديد بالتولبار بيعبر عن منطقة معينة مثل ال
( بين عناصر المناطقseparator اسم المنطقة )لحظ بين كل استدعاء ليها هيتم انشاء
toolbar object الموجودة بالaddAction ليها استخدمactions لضافة
fbar=addToolBar('file') #Toolbar for file menu items..
fbar.addAction(newaction)
fbar.addAction(openaction)
16. ebar=addToolBar("edit") #Toolbar for edit menu items..
ebar.addAction(copyaction)
ebar.addAction(cutaction)
كود المثال
class MyWindow < Qt::MainWindow
slots 'onNew()', 'onOpen()', 'onCopy()', 'onCut()'
def initialize
super()
init_comp
end
def init_comp
setWindowTitle('Hello, World!')
#resize(200, 300) #w, h
setGeometry(300, 300, 250, 150) #x, y, w, h
setToolTip("Simple Widget")
newaction=Qt::Action.new(Qt::Icon.new('actions/documentnew.png'),"New",self)
#set shortcut
newaction.setShortcut("Ctrl+N")
newaction.setStatusTip("Create a new file.")
connect(newaction, SIGNAL("triggered()"), SLOT("onNew()"))
openaction=Qt::Action.new(Qt::Icon.new('actions/documentopen.png'),"Open",self)
#set shortcut
openaction.setShortcut("Ctrl+O")
openaction.setStatusTip("Open a file")
connect(openaction, SIGNAL("triggered()"), SLOT("onOpen()"))
copyaction=Qt::Action.new(Qt::Icon.new('actions/editcopy.png'),"Copy",self)
#set shortcut
copyaction.setShortcut("Ctrl+C")
copyaction.setStatusTip("Copy")
connect(copyaction, SIGNAL("triggered()"), SLOT("onCopy()"))
cutaction=Qt::Action.new(Qt::Icon.new('actions/editcut.png'),"Cut",self)
#set shortcut
cutaction.setShortcut("Ctrl+X")
cutaction.setStatusTip("Cut")
connect(cutaction, SIGNAL("triggered()"), SLOT("onCut()"))
exitaction=Qt::Action.new("Exit", self)
18. end
ال Dialogs
التعامل مع ال Dialogsكتير سهل مع ال Qtفهنشرح المثال الموجود بال standard dialogs
QinputDialog
هو كلس بيسهل التعامل مع المستخدم واخذ قيمة معينة منه سواء Integer, Double, Text, Item
getInteger
التعريف العام ليها
int getInteger ( QWidget * parent, const QString & title, const QString & label, int value = 0, int
= minValue = 2147483647, int maxValue = 2147483647, int step = 1, bool * ok = 0, Qt::WindowFlags f
) 0
اول معامل مع النافذة الب
الثانى هو عنوان الديالوج
الثالث هو الرسالة
الرابع هو القيمة المختارة
الخامس اقل قيمة
19. السادس اكبر قيمة
السابع مقدار الزيادة
الثامن هو مؤشر للمتغير اللى هيتم تخزين فيه ناتج تعامل المستخدم مع الديالوج
التاسع هو ال ) WindowFlagsيستحسن مراجعة ال enumمن ال (Qt Assistant
التعامل من خلل روبى
)( def setInteger
ok = Qt::Boolean.new
,)")( i = Qt::InputDialog.getInteger(self, tr("Qt::InputDialog.getInteger
) tr("Percentage:"), 25, 0, 100, 1, ok
if ok
) @integerLabel.text = tr("%d%" % i
end
end
لحظ انشأنا okمن النوع Qt::Booleanليتم مباصاته لل getIntegerلحساب قيمة التفاعل مع المستخدم
استدعينا الديالوج من خلل ال static getIntegerواخدت معاملت زى ماذكرنا الب والعنوان والرسالة
والقيمة المختارة والقيمة الصغرى والقيمة الكبرى ومقدار الزيادة ومتغير okليتم وضع ناتج التفاعل فيه
فى حال ان ال okدا قيمته اعيدت ب trueهيتم وضع تكست على labelمسمى @integerLabel
getDouble
نفس تعريف سابقتها ولكن بتعمل ريترن ب double
,0 = double getDouble ( QWidget * parent, const QString & title, const QString & label, double value
,0 = double minValue = 2147483647, double maxValue = 2147483647, int decimals = 1, bool * ok
0 = ( Qt::WindowFlags f
اول معامل مع النافذة الب
الثانى هو عنوان الديالوج
الثالث هو الرسالة
الرابع هو القيمة المختارة
الخامس اقل قيمة
20. السادس اكبر قيمة
السابع مقدار الزيادة
الثامن هو مؤشر للمتغير اللى هيتم تخزين فيه ناتج تعامل المستخدم مع الديالوج
التاسع هو ال ) WindowFlagsيستحسن مراجعة ال enumمن ال (Qt Assistant
التعامل من خلل روبى
)( def setDouble
ok = Qt::Boolean.new
,)")( d = Qt::InputDialog.getDouble(self, tr("Qt::InputDialog.getDouble
) tr("Amount:"), 37.56, 10000, 10000, 2, ok
if ok
@doubleLabel.text = "$%f" % d
end
end
استدعينا الديالوج من خلل ال static getDoubleواخدت معاملت زى ماذكرنا الب والعنوان والرسالة
والقيمة المختارة والقيمة الصغرى والقيمة الكبرى ومقدار الزيادة ومتغير okليتم وضع ناتج التفاعل فيه
فى حال ان ال okدا قيمته اعيدت ب trueهيتم وضع تكست على labelمسمى @doubleLabel
getItem
& QString getItem ( QWidget * parent, const QString & title, const QString & label, const QStringList
) 0 = list, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags f
:parentهو الب
:titleالعنوان
:labelالرسالة
:listالختيارات المتاحة
:currentرقم الختيار الحالى )اللى هيتم عرضه( index
:editableهل المستخدم يقدر يكتب فى مكان الختيار او ل
:okمؤشر للريترن
يفضل مراجعة ال WindowFlagsمع ال Qt Assistant
21. التعامل من خلل روبى
def setItem()
items = []
items << tr("Spring") << tr("Summer") << tr("Fall") << tr("Winter")
ok = Qt::Boolean.new
item = Qt::InputDialog.getItem(self, tr("Qt::InputDialog.getItem()"),
tr("Season:"), items, 2, false, ok)
if ok && !item.nil?
@itemLabel.text = item
end
end
مثل ونحط فيها القيمitems بإسمlist بننشئ
ونباصى ليها رفرنس للب والعنوان ومحتوى الرسالةstatic getItem ونستدعى الديالوج بإستخدام ال
والختيارات والختيار المنشط و سماحية الكتابة ورفرنس لناتج التفاعل
بحيث انه يظهرitemLabel@ نختبر العائد من التفاعل والقيم اللى اختارها المستخدم وبناء عليها هنعدل
... الختيار
getText
معرفة كالتالى
QString getText ( QWidget * parent, const QString & title, const QString & label,
QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0,
Qt::WindowFlags f = 0 )
من المستخدمstring ميثود بتحصل على
: البparent
: العنوانtitle
: محتوى الرسالةlabel
المستخدم اهمهمecho mode : بيعبر عن الmode
Normal: عرض الحروف جميعا
NoEcho: عدم العرض
22. Password: إستبدال الحروف بنجوم
LineEdit : هو النص الفتراضى الموجود بالtext
: ناتج التفاعل مع المستخدمok
التعامل من خلل روبى
def setText()
ok = Qt::Boolean.new
text = Qt::InputDialog.getText(self, tr("Qt::InputDialog.getText()"),
tr("User name:"), Qt::LineEdit::Normal,
Qt::Dir::home().dirName(), ok)
if ok && !text.nil?
@textLabel.text = text
end
end
ColorDialog
static getColor هو كلس بيسهل علينا الحصول على لون معين من اختيار المستخدم ودا من خلل ال
المعرفة كالتالى
QColor getColor ( const QColor & initial = Qt::white, QWidget * parent = 0 )
( )البparent وبينتمى الديالوج لinitial بتعرض ديالوج فيه الختيار الولى
ميثودcolor.isValid فللختبار استخدمinvalid هيتم اعادةcancel لو المستخدم ضغط
الستخدام من خلل روبى
24. فى الواقع الميثود دى معرفة اكثر من مرة overloadedفإحنا هناخد دى
) 0 = QFont getFont ( bool * ok, const QFont & initial, QWidget * parent
هنا okبتعبر عن ناتج التفاعل مع المستخدم
:initialالفونت اللى هيتم وضعه كبداية
:parentالنافذة الب
او تقدر تستدعيه كالتالى
) 0 = QFont getFont ( bool * ok, QWidget * parent
وهيتم وضع ال fontالفتراضى للبلكيشن ك initial
التعامل مع روبى
)( def setFont
ok = Qt::Boolean.new
) font = Qt::FontDialog.getFont(ok, Qt::Font.new(@fontLabel.text), self
if ok
)( @fontLabel.text = font.key
end
end
okمتغير ليعبر عن الحالة
نعمل runللديالوج بإستخدام ال static getFontواللى هتاخد okو Font Objectليعبر عن الفونت الولى
وهنا بدل مانكتب التعريف ناخده مباشرة من fontLabelو selfرفرنس للب
اختبر ال ok
25. او تقدر تستخدمه كما ذكرنا بالعلى
def setFont()
ok = Qt::Boolean.new
font = Qt::FontDialog.getFont(ok, self)
if ok
@fontLabel.text = font.key()
end
end
FileDialog
كلس بيتيح ليك بسهولة امكانية اختيار ملفات او مجلدات
getDir
QString getExistingDirectory ( QWidget * parent = 0, const QString & caption = QString(), const
QString & dir = QString(), Options options = ShowDirsOnly )
للحصول على مجلد موجود من قبل
: النافذة البparent
caption الcaption
: الفولدر اللى هيتم البدأ منهdir
: مجموعة من الوبشنز الفتراضى عرض الفولدرات فقطoptions
اهمهم
ShowDirsOnly, DontResolveSymLinks
... وهى بيتم حلها افتراضياsymlinks لمنع حل ال
التعامل من خلل روبى
33. general, permissions, applications بإسمtabs 3 هنا فى الصورة السابقة عندنا
كل واحد فى ويدجت معين وتقدر تحدد هتعرض مينlayout 3 الفكرة العامة ان يبقة عندك
من السابقينtab هتنشئ 3 كلسات كل واحد فيهم بيعبر عن
class GeneralTab < Qt::Widget
#Code omitted
end
class PermissionsTab < Qt::Widget
#Code omitted..
end
class ApplicationsTab < Qt::Widget
#Code omitted..
end
... هو الديفولتgeneral tab 3 دول وفيه الtabs اوكى نبدأ بالتصميم للديالوج بتاعنا اللى فيه ال
class TabDialog < Qt::Dialog
def initialize(fileName, parent = nil)
super(parent)
fileInfo = Qt::FileInfo.new(fileName)
@tabWidget = Qt::TabWidget.new
@tabWidget.addTab(GeneralTab.new(fileInfo), tr("General"))
@tabWidget.addTab(PermissionsTab.new(fileInfo), tr("Permissions"))
38. Applications Tab تصميم ال
topLabel> Label, text (Open with)
applicationsListBox > ListWidget, 30 Applications
alwaysCheckBox >CheckBox
VBoxLayout ومرصوصين رأسيا بإستخدام
class ApplicationsTab < Qt::Widget
def initialize(fileInfo, parent = nil)
super(parent)
topLabel = Qt::Label.new(tr("Open with:"))
applicationsListBox = Qt::ListWidget.new
applications = []
(1..30).each do |i|
applications.push tr("Application %d" % i)
end
applicationsListBox.insertItems(0, applications)
if fileInfo.suffix.nil?
alwaysCheckBox = Qt::CheckBox.new(tr("Always use this application to " +
"open this type of file"))
else
alwaysCheckBox = Qt::CheckBox.new(tr("Always use this application to " +
"open files with the extension '%s'" % fileInfo.suffix()))
end
self.layout = Qt::VBoxLayout.new do |l|
l.addWidget(topLabel)
l.addWidget(applicationsListBox)
l.addWidget(alwaysCheckBox)
end
39. end
end
لحظ ان كل ال Tabsاخدت fileInfoفى المشيد الخاص بيها )راجع اول فقرة(
ConfigDialog
الخطوة القادمة تصميم ديالوج مشابه لدا
الفكرة كلها اننا عندنا جزئين جزء فيه Listكل عناصرها على صورة Iconsوالجزء التانى فيه
StackedWidgetودا مشابه لل Tabولكن غير ظاهر وبيشمل ويدجتس ايضا الفكرة هنا اننا هنربط التغيير
فى العنصر المختار من ال Listبنفس الترتيب على ال StackedWidgetليتم اظهاره
تمام الول هننشئ الصفحات دى
تصميم ال config page
تصميمها بسيط مجرد groupboxفيها labelو comboboxفيها عدة عناصر وهما مرصوصين افقيا وال
40. مرصوص بصورة رأسيةgroup box
class ConfigurationPage < Qt::Widget
def initialize(parent = nil)
super(parent)
configGroup = Qt::GroupBox.new(tr("Server configuration"))
serverLabel = Qt::Label.new(tr("Server:"))
serverCombo = Qt::ComboBox.new do |c|
c.addItem(tr("Trolltech (Australia)"))
c.addItem(tr("Trolltech (Norway)"))
c.addItem(tr("Trolltech (People's Republic of China)"))
c.addItem(tr("Trolltech (USA)"))
end
serverLayout = Qt::HBoxLayout.new do |s|
s.addWidget(serverLabel)
s.addWidget(serverCombo)
end
configGroup.layout = Qt::VBoxLayout.new do |c|
c.addLayout(serverLayout)
end
self.layout = Qt::VBoxLayout.new do |m|
m.addWidget(configGroup)
m.addStretch(1)
end
end
end
..object الموجودة بالaddItem استخدمcomboBox لضافة عنصر إلى
update page تصميم ال
41. button مرصوصة رأسيا معgroupbox تصميمها مباشر جدا
( فى المثالgridlayout )هنشرح الgrid العناصر مرصوصة فىgroupbox وداخل ال
class UpdatePage < Qt::Widget
def initialize(parent = nil)
super(parent)
packagesGroup = Qt::GroupBox.new(tr("Look for packages"))
nameLabel = Qt::Label.new(tr("Name:"))
nameEdit = Qt::LineEdit.new
dateLabel = Qt::Label.new(tr("Released after:"))
dateEdit = Qt::DateTimeEdit.new(Qt::Date.currentDate())
releasesCheckBox = Qt::CheckBox.new(tr("Releases"))
upgradesCheckBox = Qt::CheckBox.new(tr("Upgrades"))
hitsSpinBox = Qt::SpinBox.new do |h|
h.prefix = tr("Return up to ")
h.suffix = tr(" results")
h.specialValueText = tr("Return only the first result")
h.minimum = 1
h.maximum = 100
h.singleStep = 10
end
startQueryButton = Qt::PushButton.new(tr("Start query"))
packagesGroup.layout = Qt::GridLayout.new do |p|
p.addWidget(nameLabel, 0, 0)
p.addWidget(nameEdit, 0, 1)
42. p.addWidget(dateLabel, 1, 0)
p.addWidget(dateEdit, 1, 1)
p.addWidget(releasesCheckBox, 2, 0)
p.addWidget(upgradesCheckBox, 3, 0)
p.addWidget(hitsSpinBox, 4, 0, 1, 2)
end
self.layout = Qt::VBoxLayout.new do |m|
m.addWidget(packagesGroup)
m.addSpacing(12)
m.addWidget(startQueryButton)
m.addStretch(1)
end
end
end
GroupBox class وحددنا ال تكست الظاهر عليها بإستخدام المشيد للgroupbox 1- انشأنا ال
packagesGroup = Qt::GroupBox.new(tr("Look for packages"))
Name LineEdit والName Label 2- انشأنا ال
nameLabel = Qt::Label.new(tr("Name:"))
nameEdit = Qt::LineEdit.new
DataTime Edit و الDate label 3- انشأنا ال
dateLabel = Qt::Label.new(tr("Released after:"))
dateEdit = Qt::DateTimeEdit.new(Qt::Date.currentDate())
وبتباصى التكست الظاهر جمب الصندوق فىCheckBox class بإستخدام الCheck Boxes 4- انشأنا ال
المشيد ليه
releasesCheckBox = Qt::CheckBox.new(tr("Releases"))
upgradesCheckBox = Qt::CheckBox.new(tr("Upgrades"))
SpinBox 5- انشأنا ال
hitsSpinBox = Qt::SpinBox.new do |h|
h.prefix = tr("Return up to ")
h.suffix = tr(" results")
h.specialValueText = tr("Return only the first result")
h.minimum = 1
h.maximum = 100
h.singleStep = 10
end
هو ماقبل القيمة الظاهرةprefix ال
هو مابعد القيمة الظاهرةsuffix ال
تقدر تظهره عن اصغر قيمة مقبولةstring هوspecialValueText ال
اصغر قيمة مقبولةminimum ال
اكبر قيمة مقبولةmaximum ال
43. مقدار الزيادة عند كل ضغطةsingleStep ال
GridLayout نيجى لجزئية ال
packagesGroup.layout = Qt::GridLayout.new do |p|
p.addWidget(nameLabel, 0, 0)
p.addWidget(nameEdit, 0, 1)
p.addWidget(dateLabel, 1, 0)
p.addWidget(dateEdit, 1, 1)
p.addWidget(releasesCheckBox, 2, 0)
p.addWidget(upgradesCheckBox, 3, 0)
p.addWidget(hitsSpinBox, 4, 0, 1, 2)
end
بيسمحلك تضيف الويدجتسGridLayout والpackagesGroup داخل الGridLayout هنا بنقول ان فى
0 حاجة مشابهه لجدول وكل مافيها خليا بيبدأ من اعلى اليسار ودى بتبقة الخلية فى الصفgrid فى
0 والعمود
مثل هنا دا عبارة عن 3 صفوف و 5 اعمدة
(overloaded )هتلقيهاaddWidget استخدمgrid للضافة داخل
addWidget(widget, row, col)
addWidget(row, col, rospan, col, colspan)
حيث
: رقم الصفrow
: رقم العمودcol
row span : الrowspan
colspan : الcolspan