Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 74 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
74
Dung lượng
312,35 KB
Nội dung
203 Chapter 9 ✦ Graphics File Formats This example creates a small pixmap from the XPM data included in the source on line 6. The actual size of the pixmap is ignored, and it is set as the background pixmap on line 13; the size of the widget is set on line 14. The result is the window shown in Figure 9-2. Figure 9-2: Displaying compiled XPM data as a tiled background Loading a Pixmap from a File You can load a graphic from a file, instead of compiling it as part of the program, by making a slight change to the previous example. All that is needed is a different method to create the pixmap. The following program loads and displays the logo pixmap previously shown in Figure 9-1: 1 /* showfilexpm.cpp */ 2 #include <kapp.h> 3 #include <qwidget.h> 4 #include <qpixmap.h> 5 6 int main(int argc,char **argv) 7 { 8 KApplication app(argc,argv,”showfilexpm”); 9 QPixmap pixmap(“logo.xpm”); 10 QWidget *widget = new QWidget(); 11 widget->setFixedSize(pixmap.width(),pixmap.height()); 12 widget->setBackgroundPixmap(pixmap); 13 widget->show(); 14 app.setMainWidget(widget); 15 return(app.exec()); 16 } The QPixmap constructor on line 9 uses a file to locate the graphic data. You can use file types other than XPM. For example, to load a different type of file, change the filename on line 9 as follows: QPixmap pixmap(“logo.gif”); The software does not look at the suffix of the filename to determine the file type. Instead, it loads a block of data from the beginning of the file and inspects it to deter- mine the file type. This is why the commented string containing the characters XPM must remain at the top of an XPM file. 4682-1 ch09.f.qc 11/13/00 14:11 Page 203 204 Part II ✦ Step by Step If the software complains about an invalid XPM file, it may be in an older format. The file must be in version 3 in order for you to use it. Make the conversion with a command like the following: sxpm -nod oldform.xpm -o newform.xpm In order to load from a graphic file, the software must understand the file format. The Qt software supports the file types PNG, BMP, GIF, JPEG, XBM, XPM, and PNM. The Qt software was designed in such a way that it may be extended later to include other formats. Also, because of patent issues, it is probably not a good idea to count on the GIF format being available in all countries. Nothing special is required to read from the various file formats. The following example program loads and displays a JPEG version of the graphic shown previously in Figure 9-1: /* showfilejpeg.cpp */ #include <kapp.h> #include <qwidget.h> #include <qpixmap.h> int main(int argc,char **argv) { KApplication app(argc,argv,”showfilejpeg”); QPixmap pixmap(“logo.jpeg”); QWidget *widget = new QWidget(); widget->setFixedSize(pixmap.width(),pixmap.height()); widget->setBackgroundPixmap(pixmap); widget->show(); app.setMainWidget(widget); return(app.exec()); } Using a Pixmap to Decorate a Button A button contains a window just like any other widget, so it can display a picture as well as text. In fact, the QPushButton class has some special enhancements that cause the pixmap to represent the current state of the button. The following program uses a PNG file to paint the face of the button shown in Figure 9-3: 1 /* decobutton.cpp */ 2 #include <kapp.h> 3 #include <kpixmap.h> 4 #include “decobutton.h” 5 6 int main(int argc,char **argv) 7 { 8 KApplication app(argc,argv,”decobutton”); 4682-1 ch09.f.qc 11/13/00 14:11 Page 204 205 Chapter 9 ✦ Graphics File Formats 9 DecoButton decobutton; 10 decobutton.show(); 11 app.setMainWidget(&decobutton); 12 return(app.exec()); 13 } 14 15 DecoButton::DecoButton(QWidget *parent,const char *name) 16 : QWidget(parent,name) 17 { 18 setFixedSize(200,150); 19 20 QPixmap pixmap(“hil-app-go.png”); 21 button = new QPushButton(this); 22 button->setPixmap(pixmap); 23 button->setGeometry(50,50,100,50); 24 } Figure 9-3: A button with a graphic instead of text The widget used for the top-level window is DecoButton. Its constructor begins on line 15. Line 18 sets the widget to a fixed size of 200 pixels wide and 150 high. The pixmap is created from a file named hil-app-go.png on line 20. A button is created and the pixmap is inserted into it with the call to setPixmap() on line 22. On line 23, the button is sized to fit properly with this pixmap. The QPushButton class does something special when the button is pressed. To make the button appear depressed, the background is changed to a darker color and the graphic itself is shifted one pixel down and one to the right. The result is shown in Figure 9-4. Figure 9-4: An activated button with a graphic instead of text 4682-1 ch09.f.qc 11/13/00 14:11 Page 205 206 Part II ✦ Step by Step When the button is activated, the area not covered by the graphic icon is darkened. The icon is actually square, so to darken some of the pixels within the graphic itself it is necessary for them to be transparent. The transparent pixels changing color gives the user the expected feedback from selecting a button. But the graphic of the icon itself is also modified, as you can see by comparing Figures 9-3 and 9-4. This modification is made with the QIconSet class described later in this chapter. The XBM Format If there are only two colors (usually black and white), it is more efficient to store a picture with a single bit for each pixel, as is done in XBM (XBitMap) format. The XBM format is most often used to define mouse and keyboard cursors, but it also has other purposes. Like the XPM format, an XBM file is an ASCII file that can be compiled directly into a C program. The following is an example of an XBM file: #define arrow_width 16 #define arrow_height 16 #define arrow_x_hot 15 #define arrow_y_hot 7 static unsigned char arrow_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x80, 0x0f, 0x80, 0x1f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfc, 0xff, 0xfc, 0x7f, 0xfc, 0x3f, 0x80, 0x1f, 0x80, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; The first two lines determine the width and height in pixels. The next two lines specify the coordinates of the hot spot. The hot spot is the exact x and y pixel loca- tion inside the bitmap that is considered to be the mouse location whenever the bitmap is used as a mouse cursor. The specification of the hot spot is optional, so the two lines can be omitted. Figure 9-5 shows the appearance of this bitmap. The hot spot is at the tip of the arrow point on the right. Figure 9-5: A bitmap defines graphics in black and white. In the file, the bit settings are written as byte values, and each number specifies the on or off status of eight pixels. The pixels are first mapped from left to right, and then from top to bottom. They are all held in a single array, so the software that uses it must have the height and width information to know where the lines break. The Bitmap Utility There is a utility that you can use to create bitmap files and to modify them once they are created. To create a new bitmap with the default size of 16 × 16, just enter 4682-1 ch09.f.qc 11/13/00 14:11 Page 206 207 Chapter 9 ✦ Graphics File Formats the command name with no arguments. If you want to create a new bitmap that is 24 pixels wide and 32 pixels high, enter the command as follows: bitmap -size 24x32 Once a bitmap is created and written to disk, it can be loaded again for editing by being named on the command line as follows: bitmap arrow.xbm The window used to edit the arrow is shown in Figure 9-6. As you can see from the array of controlling buttons, you can edit the figure in a number of ways. The figure layout is displayed in the grid on the right, enabling you to use the left mouse button to set pixel values to 0, and the right mouse button to set them to 1. The diamond- shaped pixel on the right indicates the hot spot — and there can be only one hot spot. To set the hot spot, select the Set Hot Spot button and then select a pixel. Figure 9-6: The bitmap editor with arrow.xbm loaded The bitmap utility can be used to create cursors. A cursor requires two bitmaps—one for the cursor and one for the mask. The process of creating a cursor is described in Chapter 8. 4682-1 ch09.f.qc 11/13/00 14:11 Page 207 208 Part II ✦ Step by Step This program is part of the standard X11 distribution. Its buttons and menu labels look very different from the ones in KDE because this program was developed using a completely different set of widgets and utilities. Fortunately, the underlying X11 standards and protocols allow programs based on completely different soft- ware to all execute simultaneously on the same display. Customizing Graphics for Menus and Toolbars The graphic icon indicator on a toolbar button can be modified to indicate that the selection is either not available or that the toolbar button widget is currently being selected by the user with the mouse button. To indicate the conditions, it is necessary to make modifications to the appearance of the pixmap. To do this, the QIconSet class accepts a single QPixmap as input and generates three pixmaps in two different sizes. These six different versions of the pixmap can be used in toolbars and menus, as described in Chapter 6. The following example program allows you to browse through a selection of graph- ics files and display the six different forms of the one you select, as shown in Figure 9-7. A QFileDialog, described in Chapter 5, is used to select and load a QPixmap from a graphic file. A QIconSet object is then used to create the six versions of the pixmap displayed in the figure. Figure 9-7: An icon shown in six different forms SetIcon Header 1 /* seticon.h */ 2 #ifndef SETICON_H 3 #define SETICON_H 4 5 #include <qwidget.h> 6 #include <qlayout.h> 7 #include <qlabel.h> 8 #include <qpixmap.h> 9 #include <qpushbutton.h> 10 11 class SetIcon: public QWidget 12 { 13 Q_OBJECT 14 public: Note 4682-1 ch09.f.qc 11/13/00 14:12 Page 208 209 Chapter 9 ✦ Graphics File Formats 15 SetIcon(QWidget *parent=0,const char *name=0); 16 private: 17 QVBoxLayout *makeVerticalBox(); 18 QGridLayout *makeGrid(); 19 void insertNewPixmap(); 20 private: 21 QPixmap pixmap; 22 QString pixmapName; 23 QPushButton *button; 24 QLabel *picLabel; 25 QLabel *nameLabel; 26 QLabel *normal; 27 QLabel *disabled; 28 QLabel *active; 29 QLabel *small; 30 QLabel *large; 31 QLabel *normalSmall; 32 QLabel *normalLarge; 33 QLabel *disabledSmall; 34 QLabel *disabledLarge; 35 QLabel *activeSmall; 36 QLabel *activeLarge; 37 public slots: 38 void newPixmap(); 39 }; 40 41 #endif Three internal methods are defined on lines 17 through 19. The methods make VerticalBox() and makeGrid() are used by the constructor to help in the layout of the top-level window. The method insertNewPixmap() is called whenever a new QPixmap has been created and needs to be displayed. The QPixmap and QString on lines 21 and 22 hold the current pixmap and its name. The pushbutton and the labels declared on lines 23 through 36 are the ones that appear on the display. The labels named picLabel and nameLabel display the unmodified pixmap and the name of the file from which it was loaded. The labels on lines 26 through 30 are used to annotate the table shown in Figure 9-7, and the labels on lines 31 through 36 are used to display each of the six versions of the pixmap. SetIcon 1 /* seticon.cpp */ 2 #include <kapp.h> 3 #include <qfiledialog.h> 4 #include “seticon.h” 5 6 int main(int argc,char **argv) 7 { 8 KApplication app(argc,argv,”seticon”); 4682-1 ch09.f.qc 11/13/00 14:12 Page 209 210 Part II ✦ Step by Step 9 SetIcon seticon; 10 seticon.show(); 11 app.setMainWidget(&seticon); 12 return(app.exec()); 13 } 14 15 SetIcon::SetIcon(QWidget *parent,const char *name) 16 : QWidget(parent,name) 17 { 18 pixmapName = “hil-app-go.png”; 19 pixmap = QPixmap(pixmapName); 20 21 QHBoxLayout *hbox = new QHBoxLayout(this,5); 22 QVBoxLayout *vbox = makeVerticalBox(); 23 hbox->addLayout(vbox); 24 hbox->addSpacing(50); 25 QGridLayout *grid = makeGrid(); 26 hbox->addLayout(grid); 27 hbox->activate(); 28 29 insertNewPixmap(); 30 31 connect(button,SIGNAL(clicked()), 32 this,SLOT(newPixmap())); 33 } 34 35 QVBoxLayout *SetIcon::makeVerticalBox() 36 { 37 QVBoxLayout *vbox = new QVBoxLayout(5); 38 39 vbox->addStretch(1); 40 41 button = new QPushButton(“Select”,this); 42 button->setFixedSize(button->sizeHint()); 43 vbox->addWidget(button); 44 45 vbox->addStretch(1); 46 47 picLabel = new QLabel(“”,this); 48 picLabel->setAutoResize(TRUE); 49 picLabel->setAlignment(AlignHCenter | AlignVCenter); 50 vbox->addWidget(picLabel); 51 52 nameLabel = new QLabel(“”,this); 53 nameLabel->setAutoResize(TRUE); 54 nameLabel->setAlignment(AlignHCenter | AlignVCenter); 55 vbox->addWidget(nameLabel); 56 57 vbox->addStretch(1); 58 59 return(vbox); 60 } 61 QGridLayout *SetIcon::makeGrid() 62 { 4682-1 ch09.f.qc 11/13/00 14:12 Page 210 211 Chapter 9 ✦ Graphics File Formats 63 QGridLayout *grid = new QGridLayout(4,3); 64 65 normal = new QLabel(“Normal”,this); 66 grid->addWidget(normal,1,0); 67 disabled = new QLabel(“Disabled”,this); 68 grid->addWidget(disabled,2,0); 69 active = new QLabel(“Active”,this); 70 grid->addWidget(active,3,0); 71 small = new QLabel(“Small”,this); 72 grid->addWidget(small,0,1); 73 large = new QLabel(“Large”,this); 74 grid->addWidget(large,0,2); 75 76 normalSmall = new QLabel(“”,this); 77 grid->addWidget(normalSmall,1,1); 78 normalLarge = new QLabel(“”,this); 79 grid->addWidget(normalLarge,1,2); 80 disabledSmall = new QLabel(“”,this); 81 grid->addWidget(disabledSmall,2,1); 82 disabledLarge = new QLabel(“”,this); 83 grid->addWidget(disabledLarge,2,2); 84 activeSmall = new QLabel(“”,this); 85 grid->addWidget(activeSmall,3,1); 86 activeLarge = new QLabel(“”,this); 87 grid->addWidget(activeLarge,3,2); 88 89 return(grid); 90 } 91 void SetIcon::insertNewPixmap() 92 { 93 picLabel->setPixmap(pixmap); 94 nameLabel->setText(pixmapName); 95 96 QIconSet iconset(pixmap); 97 98 QPixmap p; 99 p = iconset.pixmap(QIconSet::Small,QIconSet::Normal); 100 normalSmall->setPixmap(p); 101 p = iconset.pixmap(QIconSet::Large,QIconSet::Normal); 102 normalLarge->setPixmap(p); 103 104 p = iconset.pixmap(QIconSet::Small,QIconSet::Disabled); 105 disabledSmall->setPixmap(p); 106 p = iconset.pixmap(QIconSet::Large,QIconSet::Disabled); 107 disabledLarge->setPixmap(p); 108 109 p = iconset.pixmap(QIconSet::Small,QIconSet::Active); 110 activeSmall->setPixmap(p); 111 p = iconset.pixmap(QIconSet::Large,QIconSet::Active); 112 activeLarge->setPixmap(p); 113 } 114 void SetIcon::newPixmap() 115 { 116 QString filter = “Icon (*.png *.xpm *.xbm)”; 4682-1 ch09.f.qc 11/13/00 14:12 Page 211 212 Part II ✦ Step by Step 117 QString name = QFileDialog::getOpenFileName(“”, 118 filter,this); 119 if(!name.isEmpty()) { 120 int length = name.length() - name.findRev(‘/’); 121 pixmapName = name.right(length - 1); 122 pixmap = QPixmap(name); 123 insertNewPixmap(); 124 } 125 } The SetIcon widget, with its constructor beginning on line 15, is used as the top-level window of the application on line 11. Lines 18 and 19 specify the name and value of the initial pixmap. The window is laid out as the horizontal box hbox, which contains a QVBoxLayout named vbox on the left and a QGridLayout named grid on the right. The call to makeVerticalBox() and makeGrid() on lines 22 and 25 create the two sub-layouts included in the horizontal box. The call to insertNewPixmap() on line 29 installs the initial pixmap as the one currently displayed. The call to connect() on line 31 establishes the slot method newPixmap() as the one to be executed whenever the button is clicked. The method makeVerticalBox() on line 35 creates the Select button, the display label to display the unmodified graphic, and the label holding the name of the graphic file. These are all inserted into a vertical box. The button is created and inserted on lines 41 through 43. The two labels are created and added to the vertical box on lines 47 through 55. The labels are left empty for now because the pixmap and its filename will be installed in them later. The method makeGrid() beginning on line 61 uses a QGridLayout to create a table of QLabel objects that are used to display the various incarnations of the current pixmap. The grid is 3 cells wide and 4 cells high. The first row and the first column are used for annotation labels, as you can see on the right side of the win- dow in Figure 9-7. The labels created on lines 65 through 74 are the annotations, so they are all created with the text included. The labels created on lines 76 through 87 are intended to display pixmap graphics, so they are created without text. The method insertNewPixmap() on line 91 uses the current pixmap information to fill out the display. This method is called once when the program first starts running, to install the default pixmap; and once again whenever a new pixmap is selected. The QIconSet object iconset is created on line 96 using the pixmap that was stored in the pixmap field of the object. All that is needed now is for each of the six modified pixmaps to be retrieved and inserted into the label widgets for display. The method pixmap() is used to retrieve each version of the graphic. The arguments passed to the method determine which of the six is returned. The first argument specifies that the returned pixmap be either Small or Large. The second argument requests that it be Normal, Disabled, or Active. The argument values are defined as enums in the QIconSet class. 4682-1 ch09.f.qc 11/13/00 14:12 Page 212 [...]... Vposition = Vmiddle; 37 updateDisplay(); } 38 void setBottom() { Vposition = Vbottom; 39 updateDisplay(); } 40 void setLeft() { Hposition = Hleft; 41 updateDisplay(); } 42 void setCenter() { Hposition = Hcenter; 43 updateDisplay(); } 44 void setRight() { Hposition = Hright; 45 updateDisplay(); } 46 }; 47 48 #endif The FontPaint class is the widget used as the top-level window The enumerated types on lines... connect(bottomButton,SIGNAL(clicked()), 34 this,SLOT(setBottom())); 35 vbox->addLayout(hbox); 36 37 frame = new QWidget(this); 38 frame->setMinimumSize(150,150); 39 vbox->addWidget(frame); 40 41 hbox = new QHBoxLayout(5); 42 leftButton = new QPushButton(“Left”,this); 43 hbox->addWidget(leftButton); 44 connect(leftButton,SIGNAL(clicked()), 45 this,SLOT(setLeft())); 46 centerButton = new QPushButton(“Center”,this); 47 hbox->addWidget(centerButton);... frame->font(); 64 updateDisplay(); 65 } 66 void FontPaint::popupDialog() 67 { 68 bool okay; 69 70 QFont newFont = QFontDialog::getFont(&okay,font,this); 71 if(okay) { 72 font = newFont; 46 82-1 ch10.f.qc 11/13/00 14: 12 Page 229 Chapter 10 ✦ Fonts 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 1 04 105 106 107 108 109 110 111 112 113 1 14 115 116 117 118... The next chapter explores the various fonts and font-rendering techniques that are available to your application ✦ ✦ ✦ 213 46 82-1 ch09.f.qc 11/13/00 14: 12 Page 2 14 4682-1 ch10.f.qc 11/13/00 14: 12 Page 215 10 C H A P T E R Fonts T he way that fonts are used by X11 (and thus by Qt and KDE) may confuse you at first But once you see what is going on, it becomes quite simple A method was devised that keeps... class is quite simple It only contains the button to be clicked and the slot to be executed to pop up the dialog 221 46 82-1 ch10.f.qc 222 11/13/00 14: 12 Page 222 Part II ✦ Step by Step FontPrompt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 /* fontprompt.cpp */ #include #include #include “fontprompt.h” int main(int... previous one, except that it uses a KFontDialog to do the selection The pop-up dialog is shown in Figure 10-7 223 46 82-1 ch10.f.qc 2 24 11/13/00 14: 12 Page 2 24 Part II ✦ Step by Step Figure 10-7: A font selection dialog showing a large font FontPrompt2 Header 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /* fontprompt2.h */ #ifndef FONTPROMPT2_H #define FONTPROMPT2_H #include #include ... in exactly the same display: 76 void FontPaint2::updateDisplay() 77 { 78 int align; 79 QString text; 231 46 82-1 ch10.f.qc 232 11/13/00 14: 12 Page 232 Part II ✦ Step by Step 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 1 04 105 106 107 108 109 110 111 112 113 1 14 115 116 117 118 } QPainter painter(frame); painter.setFont(font); painter.setBackgroundColor(QColor(“black”));... QWidget(parent,name) { QVBoxLayout *vbox = new QVBoxLayout(this,10); QLabel *label1 = new QLabel( “Bold 14- point Courier”,this); QFont font1(“Courier”, 14, QFont::Bold,FALSE); label1->setFont(font1); vbox->addWidget(label1); 219 46 82-1 ch10.f.qc 220 11/13/00 14: 12 Page 220 Part II ✦ Step by Step 27 28 29 30 31 32 33 34 35 36 37 38 } QLabel *label2 = new QLabel( “20-point Fixed”,this); QFont font2(“Fixed”,20,QFont::Normal,FALSE);... FontPrompt2 1 2 3 4 5 6 7 8 9 10 11 12 /* fontprompt2.cpp */ #include #include #include “fontprompt2.h” int main(int argc,char **argv) { KApplication app(argc,argv,”fontprompt2”); FontPrompt2 fontprompt2; fontprompt2.show(); app.setMainWidget(&fontprompt2); return(app.exec()); 46 82-1 ch10.f.qc 11/13/00 14: 12 Page 225 Chapter 10 ✦ Fonts 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27... 23 through 28 are each used to store values in Vposition and Hposition Each of the slot methods on lines 34 through 45 is connected to a button; and when the method is called, it updates the position of the text and calls updateDisplay() to paint the window FontPaint 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /* fontpaint.cpp */ #include #include #include #include . button->setFixedSize(button->sizeHint()); 43 vbox->addWidget(button); 44 45 vbox->addStretch(1); 46 47 picLabel = new QLabel(“”,this); 48 picLabel->setAutoResize(TRUE); 49 picLabel->setAlignment(AlignHCenter. to your application. ✦✦✦ 46 82-1 ch09.f.qc 11/13/00 14: 12 Page 213 46 82-1 ch09.f.qc 11/13/00 14: 12 Page 2 14 Fonts T he way that fonts are used by X11 (and thus by Qt and KDE) may confuse you at. QLabel( 22 “Bold 14- point Courier”,this); 23 QFont font1(“Courier”, 14, QFont::Bold,FALSE); 24 label1->setFont(font1); 25 vbox->addWidget(label1); 26 46 82-1 ch10.f.qc 11/13/00 14: 12 Page 219 220 Part