📄 designer-manual-6.html
字号:
Q_PROPERTY( Mode mode READ mode WRITE setMode ) Q_PROPERTY( QString fileName READ fileName WRITE setFileName ) public: FileChooser( <a href="qwidget.html">QWidget</a> *parent = 0, const char *name = 0); enum Mode { File, Directory }; <a href="qstring.html">QString</a> fileName() const; Mode mode() const;</pre> <p>The constructor is declared in the standard way for widgets. We declare two public functions, <tt>fileName()</tt> to return the filename, and <tt>mode()</tt> to return the mode.</p><pre> public slots: void setFileName( const <a href="qstring.html">QString</a> &fn ); void setMode( Mode m ); signals: void fileNameChanged( const <a href="qstring.html">QString</a> & ); private slots: void chooseFile();</pre> <p>The two 'set' functions are declared as public slots. <tt>setFileName()</tt> and <tt>setMode()</tt> set the filename and mode respectively. We declare a single signal, <tt>fileNameChanged()</tt>. The private slot, <tt>chooseFile()</tt> is called by the widget itself when its button is clicked.</p><pre> private: <a href="qlineedit.html">QLineEdit</a> *lineEdit; <a href="qpushbutton.html">QPushButton</a> *button; Mode md; };</pre> <p>A pointer to <b>QLineEdit</b> and <b>QPushButton</b>, as well as a Mode variable are held as private data.</p><h5><a name="2-1-2"></a>Coding the Implementation</h5><p>We will work step-by-step through the implementation which is in <tt>qt/tools/designer/examples/filechooser/widget/filechooser.cpp</tt>.</p><pre> FileChooser::FileChooser( <a href="qwidget.html">QWidget</a> *parent, const char *name ) : <a href="qwidget.html">QWidget</a>( parent, name ), md( File ) {</pre> <p>The constructor passes the parent and name to its superclass, <b>QWidget</b>, and also initializes the private mode data, md, to File mode.</p><pre> <a href="qhboxlayout.html">QHBoxLayout</a> *layout = new <a href="qhboxlayout.html">QHBoxLayout</a>( this ); layout-><a href="qlayout.html#setMargin">setMargin</a>( 0 ); lineEdit = new <a href="qlineedit.html">QLineEdit</a>( this, "filechooser_lineedit" ); layout-><a href="qboxlayout.html#addWidget">addWidget</a>( lineEdit );</pre> <p>We begin by creating a horizontal box layout (<b>QHBoxLayout</b>) and add a <b>QLineEdit</b> and a <b>QPushButton</b> to it.</p><pre> <a href="qobject.html#connect">connect</a>( lineEdit, SIGNAL( <a href="qlineedit.html#textChanged">textChanged</a>( const <a href="qstring.html">QString</a> & ) ), this, SIGNAL( fileNameChanged( const <a href="qstring.html">QString</a> & ) ) ); button = new <a href="qpushbutton.html">QPushButton</a>( "...", this, "filechooser_button" ); button-><a href="qwidget.html#setFixedWidth">setFixedWidth</a>( button-><a href="qwidget.html#fontMetrics">fontMetrics</a>().width( " ... " ) ); layout-><a href="qboxlayout.html#addWidget">addWidget</a>( button ); <a href="qobject.html#connect">connect</a>( button, SIGNAL( <a href="qbutton.html#clicked">clicked</a>() ), this, SLOT( chooseFile() ) );</pre> <p>We connect the lineEdit's<!-- index textChanged() --> <tt>textChanged()</tt> signal to the custom widget's <tt>fileNameChanged()</tt> signal. This ensures that if the user changes the text in the <b>QLineEdit</b> this fact will be propagated via the custom widget's own signal. The button's<!-- index clicked() --> <tt>clicked()</tt> signal is connected to the custom widget's <tt>chooseFile()</tt> slot which invokes the appropriate dialog for the user to choose their file or directory.</p><pre> <a href="qwidget.html#setFocusProxy">setFocusProxy</a>( lineEdit ); }</pre> <p>We set the lineEdit as the focus proxy for our custom widget. This means that when the widget is given focus the focus actually goes to the lineEdit.</p><pre> void FileChooser::setFileName( const <a href="qstring.html">QString</a> &fn ) { lineEdit-><a href="qlineedit.html#setText">setText</a>( fn ); } QString FileChooser::fileName() const { return lineEdit-><a href="qlineedit.html#text">text</a>(); }</pre> <p>The <tt>setFileName()</tt> function sets the filename in the <b>QLineEdit</b>, and the <tt>fileName()</tt> function returns the filename from the <b>QLineEdit</b>. The <tt>setMode()</tt> and <tt>mode()</tt> functions (not shown) are similarly set and return the given mode.</p><pre> void FileChooser::chooseFile() { <a href="qstring.html">QString</a> fn; if ( mode() == File ) fn = QFileDialog::<a href="qfiledialog.html#getOpenFileName">getOpenFileName</a>( lineEdit-><a href="qlineedit.html#text">text</a>(), QString::null, this ); else fn = QFileDialog::<a href="qfiledialog.html#getExistingDirectory">getExistingDirectory</a>( lineEdit-><a href="qlineedit.html#text">text</a>(),this ); if ( !fn.<a href="qstring.html#isEmpty">isEmpty</a>() ) { lineEdit-><a href="qlineedit.html#setText">setText</a>( fn ); emit fileNameChanged( fn ); } }</pre> <p>When <tt>chooseFile()</tt> is called it presents the user with a file or directory dialog depending on the mode. If the user chooses a file or directory the <b>QLineEdit</b> is updated with the chosen file or directory and the <tt>fileNameChanged()</tt> signal is emitted.</p><p>Although these two files complete the implementation of the FileChooser widget it is good practice to write a test harness to check that the widget behaves as expected before attempting to put it into a plugin.</p><h5><a name="2-1-3"></a>Testing the Implementation</h5><!-- index main.cpp --><!-- index Forms!Creating Test Harnesses --><p>We present a rudimentary test harness which will allow us to run our custom widget. The test harness requires two files, a <tt>main.cpp</tt> to contain the FileChooser, and a <tt>.pro</tt> file to create the Makefile from. Here is <tt>qt/tools/designer/examples/filechooser/widget/main.cpp</tt>:</p><pre> #include <<a href="qapplication-h.html">qapplication.h</a>> #include "filechooser.h" int main( int argc, char ** argv ) { <a href="qapplication.html">QApplication</a> a( argc, argv ); FileChooser *fc = new FileChooser; fc-><a href="qwidget.html#show">show</a>(); return a.<a href="qapplication.html#exec">exec</a>(); }</pre> <p>And here is <tt>qt/tools/designer/examples/filechooser/widget/filechooser.pro</tt></p><pre>SOURCES += filechooser.cpp main.cppHEADERS += filechooser.hTARGET = filechooserTEMPLATE =appCONFIG += qt warn_on releaseDBFILE = filechooser.dbLANGUAGE = C++</pre><p>We can create the makefile using <tt>qmake</tt>: <tt>qmake -o Makefile filechooser.pro</tt>, then we can make and run the harness to test our new widget. Once we're satisfied that the custom widget is robust and has the behaviour we require we can embed it into a plugin.</p><h4><a name="2-2"></a>Creating a Plugin</h4><!-- index Creating Plugins --><!-- index Plugins!Creating a Plugin --><!-- index Component!Plugins --><p>Qt Plugins can be used to provide self-contained software components for Qt applications. Qt currently supports the creation of five kinds of plugins: codecs, image formats, database drivers, styles and custom widgets. In this section we will explain how to convert our filechooser custom widget into a <em>Qt Designer</em> custom widget plugin.</p><p>A <em>Qt Designer</em> custom widget plugin is always derived from <b>QWidgetPlugin</b>. The amout of code that needs to be written is minimal.</p><p>To make your own plugin it is probably easiest to start by copying our example<!-- index plugin.h --> <tt>plugin.h</tt> and<!-- index plugin.cpp --> <tt>plugin.cpp</tt> files and changing 'CustomWidgetPlugin' to the name you wish to use for your widget plugin implementation class. Below we provide an introduction to the header file although it needs no changes beyond class renaming. The implementation file requires simple changes, mostly more class renaming; we will review each function in turn and explain what you need to do.</p><h5><a name="2-2-1"></a>The <b>CustomWidgetPlugin</b> Implementation</h5><p>We have called our header file<!-- index plugin.h --> <tt>plugin.h</tt> and we've called our plugin class <b>CustomWidgetPlugin</b> since we will be using our plugin class to wrap our custom widgets. We present the entire header file to give you an impression of the scope of the implementation required. Most of the functions require just a few lines of code.</p><pre> #include <<a href="qwidgetplugin-h.html">qwidgetplugin.h</a>> class QT_WIDGET_PLUGIN_EXPORT CustomWidgetPlugin : public <a href="qwidgetplugin.html">QWidgetPlugin</a> { public: CustomWidgetPlugin(); <a href="qstringlist.html">QStringList</a> keys() const; <a href="qwidget.html">QWidget</a>* create( const <a href="qstring.html">QString</a> &classname, QWidget* parent = 0, const char* name = 0 ); <a href="qstring.html">QString</a> group( const <a href="qstring.html">QString</a>& ) const; <a href="qiconset.html">QIconSet</a> iconSet( const <a href="qstring.html">QString</a>& ) const; <a href="qstring.html">QString</a> includeFile( const <a href="qstring.html">QString</a>& ) const; <a href="qstring.html">QString</a> toolTip( const <a href="qstring.html">QString</a>& ) const; <a href="qstring.html">QString</a> whatsThis( const <a href="qstring.html">QString</a>& ) const; bool isContainer( const <a href="qstring.html">QString</a>& ) const; };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -