Using Trolltech's Qt you can build industrial-strength C++ applications that run natively on Windows, Linux/Unix, Mac OS X, and embedded Linux–without making source code changes. With this book Trolltech insiders have written a start-to-finish guide to getting great results with the most powerful version of Qt ever created: Qt 4.1.
Using C++ GUI Programming with Qt 4 you'll discover the most effective Qt 4 programming patterns and techniques as you master key technologies ranging from Qt's model/view architecture to Qt's powerful new 2D paint engine. The authors provide readers with unparalleled insight into Qt's event model and layout system. Then, using realistic examples, they introduce superior techniques for everything from basic GUI development to advanced database and XML integration.
Includes new chapters on Qt 4's model/view architecture and Qt's new plugin support, along with a brief introduction to Qtopia embedded programming
Covers all Qt fundamentals, from dialogs and windows to implementing application functionality
Introduces best practices for layout management and event processing
Shows how to make the most of Qt 4's new APIs, including the powerful new 2D paint engine and the new easy-to-use container classes
Contains completely updated material in every chapter
Presents advanced Qt 4 techniques covered in no other book, from creating both Qt and application plugins to interfacing with native APIs
Contains an in-depth appendix on C++/Qt programming for experienced Java developers
Qt (که کیوت تلفظ می شه) یک چارچوب توسعهی کاربردی هست. خلاصش یعنی همون framework خودمون. کیوت اغلب برای ساخت برنامههای GUI استفاده میشه که تو اینجور مواقع بهش Widget toolkit میگن، البته این به این معنی نیست که در ساخت برنامههای غیر GUI مانند برنامههای کنسول و سرورها استفاده نداره، بلکه داره!
از کیوت اکثرا به خاطر ساخت KDE (بزرگترین پروژه بازمتن)، اپرا، گوگل ارث، اسکایپ، Qtopia و Mathematica یاد میشه.
کیوت از ++C به همراه اکستنشنهای غیراستاندارد که با پیشپردازندهها پیادهسازی شده استفاده میکنه که به این طریق قبل از کامپایل، کد استاندارد تولید میشه. از کیوت میتونید در زبانهای برنامهنویسی دیگر که بایندینگش برای آنها موجود است مانند آدا، سیشارپ، جاوا، پاسکال، پرل، پیاچپی، روبی و پایتون استفاده کنید. و در نهایت مهمترین نکته اینکه، کیوت بر روی همه پلتفرمها اجرا میشه.
نصب بر روی لینوکس
پاشین برین تو اینجا و از یکی از آینهها دانلودش کنید. یادتون باشه که ما داریم از نسخه Qt/X11 استفاده میکنیم. حالا اون فایل رو که ممکنه اسمش با فایل ما فرق کنه با دستور ذیل (هه! یه دفعه با ادب شدم!) از حالت فشرده خارج کنید:
tar -zxf qt-x11-opensource-src-4.3.3.tar.gz
اصولا پروسهی نصب یه برنامه تو لینوکس به سه بخش زیر تقسیم میشه:
اول از همه با اجرای اسکریپت configure شروع میکنیم. این اسکریپت کتابخانه را برای نوع کامپیوتر ما پیکربندی میکند. به صورت پیشفرض کیوت در شاخهی /usr/local/Trolltech/Qt-4.3.3 نصب میشه که با پارامتر prefix- میشه اون رو تغییر بدیم (ولی ما که آزار نداریم این کار رو نمیکنیم). حواستون باشه که منظور از واژهی نصب در اینجا دو معنی داره. یکی به معنی کل پروسه (شامل سه مرحله) و دیگری به معنای «انتقال فایلها به شاخهی مورد نظر» که در واقع مرحله سوم هست. حالا برای انجام مرحله اول دستور زیر را وارد کنید:
./configure
حالا بهتون پیغامی نشون میده مبنی بر اینکه مجوز رو قبول میکنی یا نه. که اصولا بدون خوندن قبول میکنیم. ولی بی شوخی بعدا در مقالهای جداگانه ماجرای کیوت و دو مجوز GPL و QPL رو بررسی میکنیم.
انجام شدن کارهای این اسکریپت به چند دقیقه زمان نیاز داره. توصیه من بهتون صرف یک لیوان چای سبز و کمی مدیتیشن هست (برید حال کنید با ایده).
حالا نوبت مرحله ساخت هست. پس دستور زیر را وارد کنید:
make
مرحله ساخت چند ساعت طول میکشه پس می تونید یک پیتزا سفارش بدید و با طمانینه میل کنید یا اینقدر چایی بخورید که از 6-7 سوراختون چایی بزنه بیرون. پس بخورید و بیاشامید ولی اصراف نکنید.
در حین نصب حرارت پردازنده خیلی بالا میره. واسه اینکه حوصلتون سر نره میتونید دستور زیر رو توی یک ترمینال دیگه وارد کنید:
cat /proc/acpi/thermal_zone/THRM/temperature
خوب حالا نوبت میرسه به مرحله نصب. برای اینکار از دستور زیر استفاده کنید:
sudo make install
اگر sudo بر روی سیستمتون کار نمیکنه دستور زیر رو با اختیارات مدیر سیستم اجرا کنید:
make install
اگه فکر میکنید این دستور آنقدر طول خواهد کشید که باید سیرابی بار بگذارید، سخت در اشتباهید؛ برید دوباره چایی بخورید.
خوب حالا به عنوان آخرین کار باید متغیر سیستمی PATH رو تغییر بدید. برای اینکار دو دستور زیر را وارد کنید:
PATH=/usr/local/qt4/bin:$PATH
export PATH
اگه میخواید هر بار که وارد سیستم میشید این دستورات خود به خود اجرا شوند، دو دستور بالا رو به فایل profile. در شاخهی خانگی کاربر اضافه کنید.
نصب بر روی ویندوز
ویندوزیهایی که میخوان Qt نصب کنند و فکرمیکنند که نصب برنامه یعنی 4 تا next، خوب توجه کنند که میخوایم از روزمرگی و پوچی درشون بیاریم.
حواستون رو جمع کنید. یه بار تند و سریع میگم اگه نصب شد که شد اگه نشد خوب باید بشینیم و بررسی کنیم که مشکلش چیه! در کل جالبه که از نرمافزار آزاد میخواین رو windozd استفاده کنید ولی اینو یادتون باشه که اسم این نسخه Qt/Windows هست(نگی نگفتی!). حالا برید اینجا و فایل exe رو دانلود کنید. فایل اینستالر هنگام نصب به اینترنت وصل میشه و برنامه MinGW را که مجموعهای از کتابخانهها و برنامه gccی پورت شده به ویندوز است رو دریافت میکنه. حالا توسط خط فرمان به پوشهای که کیوت رو نصب کرده رفته و دستور زیر را برای پیکربندی اجرا کنید.
configure -platform win32-g++
شما مجبورید که برای نصب از پارامتر بالا استفاده کنید چون win32-msvc (ویژوال استادیو) در نسخهی متن باز پشتیبانی نمیشه (برای رفع ابهام اینجا رو نگاه کنید). مطمئن بشید که آدرس پوشهی bin در محل نصب MinGW رو به متغیر PATH از طریق System Properties > Advanced > Environment Variables اضافه کردهاید. حالا در داخل خط فرمان دستور زیر رو وارد کنید:
mingw32-make
این مرحله خیلی طول میکشه اما چون شما ویندوزی هستید بهتون نمیگم که چه کارایی میتونید حین نصب انجام بدید.
خوب حالا مرحله نصب تموم شده. در آخرین مرحله باید پوشه نصب (به طور مثال c:\qt\4.3.3\bin) را به روش گفته شده در بالا به متغیر محیطی PATH اضافه کنید.
برای انکه شما بتوانید با استفاده از GTK+ به توسعه نرم افزار در محیط گنوم بپردازید لازم است که پیش تر بتوانید به راحتی با زبان C کار کنید . Andrew Krause در شماره 21 مجله free software یک مقاله بسیار جامع برای اموزش مفاهیم زبان برنامه نویسی C نوشته است که مطالعه ان برای مبتدیان به عنوان یک مرجع کوتاه و بسیار مفید توصیه می شود . در این مقاله هر انچه که شما باید از زبان C بدانید تا بتوانید با کتابخانه GTK+ کار کنید ذکر شده است .
If you want to develop applications with GTK+, a graphical toolkit used by the GNOME desktop environment, it is essential that you are comfortable with the C programming language. This article is meant to give you a short refresher on the basics of C that you will need to know when developing GTK+ applications.
Basic C program structure
Every C program is composed of one or more functions in the following format. The function receives a number of variable parameters, runs the commands in the function, and then returns a variable of the given type. Note that you can omit the return value by using void as your function type.
type function (parameters)
{
local variables
commands
}
Here is a practical example (don’t worry if you don’t understand it yet):
int my_function(int a)
{
char b;
b='r';
printf("%d %c",a,c);
}
Another example function is shown below. The main() function is the only one that is required by every C program. It receives two parameters (argc and argv), which contain the command line parameters entered when the program begins and the number of parameters. The function should return an integer to exit. The following code will print out “x = 0 and y = 1”. (The printf() function will be covered later in this section!)
#include <stdio.h>
int main (int argc, char *argv[])
{
int x, y;
x = 0;
printf ("x = %d ", x);
y = 1;
printf ("and y = %d", y);
return 0;
}
Compiling your programs
If you are reading this article, you will probably need to compile your programs. Assuming that you call your file result.c, you can compile your programs by typing:
gcc -o result result.c
You will now be able to run the program by typing ./result in the directory where the program was compiled. It’s handy to have a console open with the program, and a second console with the command line above, ready to compile the code.
Variable types
C provides a number of variable types. You may notice that these are very basic types, all holding numbers, but they can be used to represent any piece of data. The following table gives an overview of the types that are available to you.
|
Data Type |
Bytes |
Lower Bound |
Upper Bound |
|
char |
1 |
-128 |
127 |
|
unsigned char |
1 |
0 |
255 |
|
short (int) |
2 |
-32768 |
32767 |
|
unsigned short (int) |
2 |
0 |
65536 |
|
int |
4 |
-2^31 |
2^31 - 1 |
|
unsigned int |
4 |
0 |
2^32 - 1 |
|
long (int) |
4 |
-2^31 |
2^31 - 1 |
|
unsigned long (int) |
4 |
0 |
2^32 - 1 |
|
float |
4 |
-3.2e38 |
3.2e38 |
|
double |
8 |
-1.7e308 |
1.7e308 |
C Data Types
It’s important to think about where you place the declaration when creating variables. The scope of a variable refers to which parts of the application can access the variable. In general, variables use the following scope rules in C:
You can declare variables outside any function, such as above the main() function. This is called a global variable. Also, a variable declared within a function is local to that function.
Arrays
The variable types previously mentioned are useful, but what if you want a thousand integers? It would take quite some time to create a variable for each of these integers. To solve this problem, you could create an array of integers. The following program creates an array, and then fills it up with the numbers 1 to 1000. Notice that arrays are indexed beginning from zero.
int arrayOfInt[1000], i;
for (i = 0; i < 1000; i++)
arrayOfInt[i] = i + 1;
It is also possible to create arrays with multiple dimensions. The following applications creates an array that has 1000 columns and 1000 rows, and fills it up with the sum of the indexes.
int multiArray[1000][1000], i, j;
for (i = 0; i < 1000; i++)
for (j = 0; j < 1000; j++)
arrayOfInt[i][j] = i + j;
The maximum number of dimensions is defined by the compiler, but most applications do not use more than three at the most. If you reach the maximum (GCC’s maximum is 29), you should consider rethinking your approach to the problem at hand!
Outputting (printing) data
Although GTK+ is a graphical toolkit, it is still useful to be able to output debugging information to the terminal. To do this in C, you would use printf(), which you already saw in a previous example. You can use additional parameters in this function to embed numbers and strings into the output text. In order for this function to work, you must include the header file stdio.h
The following example would print out “x = 5 and y = 10.7”. The %d is replaced by the first variable, which is an integer. Then, %4.1f is replaced by the second floating point variable with a maximum length of 4 characters and one character following the decimal point.
int x = 5;
double y = 10.74;
printf ("x = %d and y = %4.1f", x, y);
There are a large number of options available of printf(). It would be pointless to enumerate them here since the reference is available on thousands of sites around the Internet. To read more on this function, take a look at this page.
Conditionals and loops
C provides a number of methods for controlling the flow of your program. In order to understand these, you need to understand a few logical operators that are available. They are introduced in the following table.
|
Operator |
Description |
|
== |
Comparison operator that returns true if the value on the left is equal to the value on the right. |
|
!= |
Comparison operator that returns true if the value on the left is not equal to the value on the right. |
|
< (>) |
Comparison operator that return true if the value on the left is less than (greater than) the value on the right. |
|
<= (>=) |
Comparison operator that return true if the value on the left is less than (greater than) or equal to the value on the right. |
|
&& |
Used to concatenate multiple comparisons that will only return true if both evaluate to true. For example, ((2 > 1) && (0 > 1)) would return false. |
|
|
| | Used to concatenate multiple comparisons that will return true if at least one evaluates to true. For example, ((2 > 1) || (0 > 1)) would return true. |
|
! |
Returns the opposite value of the following expression. For example, !(1 > 0) would return false. |
Logical Operators in C
If/else comparisons
The if statement is a comparison command that can be used to run code only if a condition is met. In addition, you can include optional else if statements, that will only be evaluated if the previous statements were found to be false. Lastly, an else statement can be used at the end to catch all other cases.
The following example shows you how to use an if. Note, the curly brackets can be omitted if only one command is run after a conditional statement.
int x;
if (x > 0) {
printf ("x is positive");
}
else if (x == 0) {
printf ("x is equal to zero");
}
else {
printf ("x is negative");
}
In this example, what would be printed if x was equal to -5, 0, or 5? The application would print “x is negative”, “x is equal to zero”, and “x is positive” respectively.
The switch statement
The switch can be used as a cleaner style in place of some if statements. It compares the variable or expression in the switch to each case value. If the correct value is found, all of the commands will be run until a break or the end of the statement is reached.
In the following example, white space will be printed if ch is a space, tab, or new line character. If the letter is an uppercase vowel, vowel will be printed. Otherwise, the output will show other character.
char ch;
switch (ch) {
case ' ':
case '\t':
case '\n':
printf ("white space");
break;
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
printf ("vowel");
break;
default:
printf ("other character");
}
The default case is not required, but it can be used to catch all other cases not previously specified. Note that each case value must be constant, meaning that they cannot be variables.
While loops
The while loop will continue to run its contained commands over and over until its condition is evaluated as false.
while (condition) {
commands
}
In the following example, the while will continue running until x is greater than or equal to ten. The break statement can be used to exit the loop before it is completed. What will this code print out?
int x = 0;
while (x < 10) {
printf ("%d ", x);
x += 2;
if ((x % 3) == 0)
break;
}
The code above will print 0 2 4 . The x variable is incremented by 2 every time, but when it reaches 6, the if statement evaluates to true and exits the loop. Note: The percent sign (%) represents the modulus operator, which returns the remainder of the division.
For loops
The for loop allows you to perform initialization, comparison, and incrementing all at once. You can omit one or all of these steps by leaving it blank, although leaving out the comparison will make an infinite loop. In this case, you could use the break command to exit the loop when necessary.
for (initialize; comparison; increment) {
commands
}
In the following example, the integer i is initialized to zero at the beginning of the loop. It will continue running until i is greater than or equal to ten, incrementing by one every time the loop is run. What will this code output?
int i;
for (i = 0; i < 10; i++) {
if ((x % 3) == 0)
continue;
printf ("%d ", i);
}
The above code will output 1 2 4 5 7 8 . If x is divisible by three, continue will skip the rest of the loop’s iteration, so the values 0, 3, 6, and 9 will not be printed. You can also use the break command with for loops.
Pointers
One of the most important parts the C programming language is the pointer. A pointer is basically a variable that store the memory address of a variable, array, function, etc. There are two operators that are used with pointers:
To help you understand this concept, look at the following example. The second line creates a pointer that stores the memory location of x. The next line dereferences ptr, printing out the integer at that memory location (1). Then, the memory location ptr is set to the value 7. Since ptr points to x, the last statement prints out “7”.
If you find this confusing, slowly re-read the sentence above (yes, it does make sense!) and experiment with the code.
int x = 1;
int *ptr = &x;
printf ("%d", *ptr);
*ptr = 7;
printf ("%d", x);
Pointers are very powerful, because they can be used with arrays. The following example creates an array of one hundred characters, and then uses a pointer to traverse the array, setting each to the value of its index.
char chArray[100];
char *ptr;
int i;
for (i = 0, ptr = &chArray[0]; i < 100; i++, ++ptr)
*ptr = i;
This example shows a few important concepts. First, you should notice that you can provide multiple commands in the first and third parts of the for statement by separating them will commas. This allows you to initialize multiple variables, or provide more than one increment.
In terms of pointers, you can increment or decrement a pointer by using standard integer operations. It is legal to move a pointer with any of the following: ++ptr, --ptr, ptr += 10, ptr -= intVariable, etc.
Strings
Strings are very important to any programming language, because human interaction would be very difficult otherwise. A string is defined in C as an array of char variables. Each string in C must end with the null character (‘\0’ or 0) so that the end can be found. This is because most strings are stored as pointers.
The following example shows one way to create a string. A pointer called text is created that points to nothing at first. It is then initialized to “Hello world!” and printed to the screen.
char *text;
text = "Hello world!";
printf (text);
This string was initialized by setting the text directly, but this is generally not a good idea. Instead, you should use a function defined in string.h called strdup() to dynamically allocate a copy of the string like the following example. Once the application is done with the string, free() should be called so that the memory taken up by that string can be used by other parts of the program.
char *text;
text = strdup ("Hello world!");
printf (text);
free (text);
There are a number of other functions available in string.h for manipulating strings. The following application shows a few of them, but you should reference the header file for a full list of functions.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
char *text1, *text2;
text1 = strdup ("+");
text2 = (char*) malloc (10 * sizeof (char));
strcpy (text2, text1);
while (strlen (text2) < 10)
{
if (strcmp (text2, "+++++") == 0)
printf ("Pluses: ");
strcat (text2, text1);
}
printf (text2);
free (text1);
free (text2);
return 0;
}
The example above is a bit frivolous, but it shows some of the most common functions used for string manipulation. First, the malloc() function was used to allocate a piece of memory with a size of 10 bytes. This function requires you to include stdlib.h and will be covered in more detail in the next section.
Then, the contents of text1 are copied into text2 with strcpy(). The loop continues until the length of text2 is nine characters. During each iteration of the loop, a single plus is concatenated to the variable with strcat().
The conditional statement uses strcmp() to compare two strings. It will return a negative number if the first string should be sorted before the second, zero if the two strings are equal, or a positive number otherwise. You should note that you cannot use ==, !=, or any other operator to compare strings, since using those operators would just comparing the pointer location!
Dynamic memory allocation
One of the main reasons for pointers is to enable dynamic memory allocation, or the ability to allocate memory while the application is running. Memory is allocated in C with malloc(), which uses the following syntax. It accepts the number of bytes to allocate, returning a pointer to the newly allocated memory location. When you are done with the memory, you must call free(), or that space will be leaked by your application!
int *data;
data = (int*) malloc (100 * sizeof (int));
In addition to this function, you can use calloc(), which allocates an array of data with the given size. In the following example, an array of 100 elements with a size of 4 bytes is allocated. This code does the same essentially the same thing as the previous example.
int *data;
data = (int*) calloc (100, sizeof (int));
As with malloc(), everything allocated with calloc() should be freed when you are done using it. Also, one of the most common problems encountered with pointers is not allocating memory before using it, so make sure to avoid using uninitialized pointers! Basically, if you get a Segmentation Fault, you are misusing pointers.
Structures
The struct type allows you to create your own data types in C. For example, let us assume you want to store information about an animal. You could use the following structure to do this:
typedef struct
{
char *name;
char *sound;
int legs;
} animal;
The structure definition above creates a new data type called animal. This data type holds two strings and one integer. This is useful because you can create as many instances of animal as you want. The following code shows two ways you can use the new structure, one without and one with pointers.
animal cow;
animal *chicken;
cow.name = strdup ("Cow");
cow.sound = strdup ("Moo");
cow.legs = 4;
chicken = (animal*) malloc (sizeof (animal));
chicken->name = strdup ("Chicken");
chicken->sound = strdup ("Cluck");
chicken->legs = 2;
free (chicken);
In this example, and instance of animal is created called cow. Since this is not a pointer, you can use the period character to reference the members of the structure. In the second part of this code, the memory is allocated for another animal instance. Notice that, with a pointer, you must use -> to access the members of the structure!
It may not be immediately apparent from this example why you would want to use a pointer. However, if you wanted to pass the structure to a function, it would be much more convenient. Passing chicken would just create a copy of the pointer. This is why pointers are preferred in C.
Conclusion
By now, you should be familiar with the basics of the C programming language. While there are other aspects of the language that you may need to learn when programming with GTK+, these basics will allow you to use all but the most advanced portions of the libraries.
If you are interested in learning GTK+, I would encourage you to check out my book on the subject: Foundations of GTK+ Development. This book covers everything from the basics of the libraries to creating your own widgets, and much more in between.