Move opengl/wid/net example docs to proper folders.
Change-Id: I846439a9cf7ad965ed27a00f98dbc4ff97abe73b Reviewed-by: Jerome Pasion <jerome.pasion@digia.com> Reviewed-by: Martin Smith <martin.smith@digia.com>
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/bearermonitor
|
||||
\example bearermonitor
|
||||
\title Bearer Monitor Example
|
||||
|
||||
The Bearer Monitor example shows how to use the Bearer Management API.
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/books
|
||||
\example books
|
||||
\title Books
|
||||
|
||||
The Books example shows how Qt's SQL classes can be used with the model/view
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example tools/codecs
|
||||
\example codecs
|
||||
\title Codecs Example
|
||||
|
||||
The Codecs example demonstrates the principles behind importing and exporting text
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example tools/completer
|
||||
\example completer
|
||||
\title Completer Example
|
||||
|
||||
The Completer example shows how to provide string-completion facilities
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example dbus/complexpingpong
|
||||
\example complexpingpong
|
||||
\title Complex Ping Pong Example
|
||||
|
||||
The Complex Ping Pong example improves on the \l{D-Bus Ping Pong Example} by providing
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example tools/contiguouscache
|
||||
\example contiguouscache
|
||||
\title Contiguous Cache Example
|
||||
|
||||
The Contiguous Cache example shows how to use QContiguousCache to manage memory usage for
|
||||
|
@ -1,178 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/cube
|
||||
\group all-examples
|
||||
\title Cube OpenGL ES 2.0 example
|
||||
|
||||
The Cube OpenGL ES 2.0 example shows how to write mouse rotateable
|
||||
textured 3D cube using OpenGL ES 2.0 with Qt. It shows how to handle
|
||||
polygon geometries efficiently and how to write simple vertex and
|
||||
fragment shader for programmable graphics pipeline. In addition it
|
||||
shows how to use quaternions for representing 3D object orientation.
|
||||
|
||||
This example has been written for OpenGL ES 2.0 but it works also on
|
||||
desktop OpenGL because this example is simple enough and for the
|
||||
most parts desktop OpenGL API is same. It compiles also without OpenGL
|
||||
support but then it just shows a label stating that OpenGL support is
|
||||
required.
|
||||
|
||||
\image cube.png Screenshot of the Cube example running on N900
|
||||
|
||||
The example consist of two classes:
|
||||
|
||||
\list
|
||||
\li \c MainWidget extends QGLWidget and contains OpenGL ES 2.0
|
||||
initialization and drawing and mouse and timer event handling
|
||||
\li \c GeometryEngine handles polygon geometries. Transfers polygon geometry
|
||||
to vertex buffer objects and draws geometries from vertex buffer objects.
|
||||
\endlist
|
||||
|
||||
We'll start by initializing OpenGL ES 2.0 in \c MainWidget.
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\section1 Initializing OpenGL ES 2.0
|
||||
|
||||
Since OpenGL ES 2.0 doesn't support fixed graphics pipeline anymore it has to
|
||||
be implemented by ourselves. This makes graphics pipeline very flexible but
|
||||
in the same time it becomes more difficult because user has to implement graphics
|
||||
pipeline to get even the simplest example running. It also makes graphics pipeline
|
||||
more efficient because user can decide what kind of pipeline is needed for the
|
||||
application.
|
||||
|
||||
First we have to implement vertex shader. It gets vertex data and
|
||||
model-view-projection matrix (MVP) as parameters. It transforms vertex position
|
||||
using MVP matrix to screen space and passes texture coordinate to
|
||||
fragment shader. Texture coordinate will be automatically interpolated on polygon
|
||||
faces.
|
||||
|
||||
\snippet examples/opengl/cube/vshader.glsl 0
|
||||
|
||||
After that we need to implement second part of the graphics pipeline - fragment
|
||||
shader. For this exercise we need to implement fragment shader that handles
|
||||
texturing. It gets interpolated texture coordinate as a parameter and looks up
|
||||
fragment color from the given texture.
|
||||
|
||||
\snippet examples/opengl/cube/fshader.glsl 0
|
||||
|
||||
Using \c QGLShaderProgram we can compile, link and bind shader code to
|
||||
graphics pipeline. This code uses Qt Resource files to access shader source code.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 3
|
||||
|
||||
The following code enables depth buffering and back face culling.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 2
|
||||
|
||||
\section1 Loading textures from Qt Resource files
|
||||
|
||||
\c QGLWidget interface implements methods for loading textures from QImage to GL
|
||||
texture memory. We still need to use OpenGL provided functions for specifying
|
||||
the GL texture unit and configuring texture filtering options.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 4
|
||||
|
||||
\section1 Cube Geometry
|
||||
|
||||
There are many ways to render polygons in OpenGL but the most efficient way is
|
||||
to use only triangle strip primitives and render vertices from graphics hardware
|
||||
memory. OpenGL has a mechanism to create buffer objects to this memory area and
|
||||
transfer vertex data to these buffers. In OpenGL terminology these are referred
|
||||
as Vertex Buffer Objects (VBO).
|
||||
|
||||
\image cube_faces.png Cube faces and vertices
|
||||
|
||||
This is how cube faces break down to triangles. Vertices are ordered this way
|
||||
to get vertex ordering correct using triangle strips. OpenGL determines triangle
|
||||
front and back face based on vertex ordering. By default OpenGL uses
|
||||
counter-clockwise order for front faces. This information is used by back face
|
||||
culling which improves rendering performance by not rendering back faces of the
|
||||
triangles. This way graphics pipeline can omit rendering sides of the triangle that
|
||||
aren't facing towards screen.
|
||||
|
||||
Creating vertex buffer objects and transferring data to them is quite simple using
|
||||
OpenGL provided functions.
|
||||
|
||||
\snippet examples/opengl/cube/geometryengine.cpp 0
|
||||
|
||||
\snippet examples/opengl/cube/geometryengine.cpp 1
|
||||
|
||||
Drawing primitives from VBOs and telling programmable graphics pipeline how to
|
||||
locate vertex data requires few steps. First we need to bind VBOs to be used.
|
||||
After that we bind shader program attribute names and configure what
|
||||
kind of data it has in the bound VBO. Finally we'll draw triangle
|
||||
strip primitives using indices from the other VBO.
|
||||
|
||||
\snippet examples/opengl/cube/geometryengine.cpp 2
|
||||
|
||||
\section1 Perspective projection
|
||||
|
||||
Using \c QMatrix4x4 helper methods it's really easy to calculate perpective
|
||||
projection matrix. This matrix is used to project vertices to screen space.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 5
|
||||
|
||||
\section1 Orientation of the 3D object
|
||||
|
||||
Quaternions are handy way to represent orientation of the 3D object. Quaternions
|
||||
involve quite complex mathematics but fortunately all the necessary mathematics
|
||||
behind quaternions is implemented in \c QQuaternion. That allows us to store
|
||||
cube orientation in quaternion and rotating cube around given axis is quite
|
||||
simple.
|
||||
|
||||
The following code calculates rotation axis and angular speed based on mouse events.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 0
|
||||
|
||||
\c QBasicTimer is used to animate scene and update cube orientation. Rotations
|
||||
can be concatenated simply by multiplying quaternions.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 1
|
||||
|
||||
Model-view matrix is calculated using the quaternion and by moving world by Z axis.
|
||||
This matrix is multiplied with the projection matrix to get MVP matrix for shader
|
||||
program.
|
||||
|
||||
\snippet examples/opengl/cube/mainwidget.cpp 6
|
||||
|
||||
*/
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/blockingfortuneclient
|
||||
\example blockingfortuneclient
|
||||
\title Blocking Fortune Client Example
|
||||
|
||||
The Blocking Fortune Client example shows how to create a client for a
|
||||
@ -53,7 +53,7 @@
|
||||
\endlist
|
||||
|
||||
The implementation is very similar to the
|
||||
\l{network/fortuneclient}{Fortune Client} example, but instead of having
|
||||
\l{fortuneclient}{Fortune Client} example, but instead of having
|
||||
QTcpSocket as a member of the main class, doing asynchronous networking in
|
||||
the main thread, we will do all network operations in a separate thread
|
||||
and use QTcpSocket's blocking API.
|
||||
@ -69,7 +69,7 @@
|
||||
We will start with the FortuneThread class, which handles the network
|
||||
code.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.h 0
|
||||
\snippet blockingfortuneclient/fortunethread.h 0
|
||||
|
||||
FortuneThread is a QThread subclass that provides an API for scheduling
|
||||
requests for fortunes, and it has signals for delivering fortunes and
|
||||
@ -83,15 +83,15 @@
|
||||
FortuneThread's data members from different threads concurrently, we use
|
||||
QMutex to synchronize access.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 2
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 2
|
||||
|
||||
The requestNewFortune() function stores the host name and port of the
|
||||
fortune server as member data, and we lock the mutex with QMutexLocker to
|
||||
protect this data. We then start the thread, unless it is already
|
||||
running. We will come back to the QWaitCondition::wakeOne() call later.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 4
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 5
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 4
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 5
|
||||
|
||||
In the run() function, we start by acquiring the mutex lock, fetching the
|
||||
host name and port from the member data, and then releasing the lock
|
||||
@ -104,7 +104,7 @@
|
||||
|
||||
The run() function now enters a loop:
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 6
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 6
|
||||
|
||||
The loop will continue requesting fortunes for as long as \e quit is
|
||||
false. We start our first request by creating a QTcpSocket on the stack,
|
||||
@ -114,7 +114,7 @@
|
||||
\l{QTcpSocket::connected()}{connected()} or
|
||||
\l{QTcpSocket::error()}{error()}.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 8
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 8
|
||||
|
||||
But since we are running in a non-GUI thread, we do not have to worry
|
||||
about blocking the user interface. So instead of entering an event loop,
|
||||
@ -129,8 +129,8 @@
|
||||
After this statement, we have a connected socket to work with. Now it's
|
||||
time to see what the fortune server has sent us.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 9
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 10
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 9
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 10
|
||||
|
||||
This step is to read the size of the packet. Although we are only reading
|
||||
two bytes here, and the \c while loop may seem to overdo it, we present this
|
||||
@ -140,43 +140,43 @@
|
||||
we abort the operation. After this statement, we know that we have received
|
||||
enough data.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 11
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 11
|
||||
|
||||
Now we can create a QDataStream object, passing the socket to
|
||||
QDataStream's constructor, and as in the other client examples we set
|
||||
the stream protocol version to QDataStream::Qt_4_0, and read the size
|
||||
of the packet.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 12
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 13
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 12
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 13
|
||||
|
||||
Again, we'll use a loop that waits for more data by calling
|
||||
QTcpSocket::waitForReadyRead(). In this loop, we're waiting until
|
||||
QTcpSocket::bytesAvailable() returns the full packet size.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 14
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 14
|
||||
|
||||
Now that we have all the data that we need, we can use QDataStream to
|
||||
read the fortune string from the packet. The resulting fortune is
|
||||
delivered by emitting newFortune().
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 15
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 15
|
||||
|
||||
The final part of our loop is that we acquire the mutex so that we can
|
||||
safely read from our member data. We then let the thread go to sleep by
|
||||
calling QWaitCondition::wait(). At this point, we can go back to
|
||||
requestNewFortune() and look closed at the call to wakeOne():
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 1
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 1
|
||||
\dots
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 3
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 3
|
||||
|
||||
What happened here was that because the thread falls asleep waiting for a
|
||||
new request, we needed to wake it up again when a new request
|
||||
arrives. QWaitCondition is often used in threads to signal a wakeup call
|
||||
like this.
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/fortunethread.cpp 0
|
||||
\snippet blockingfortuneclient/fortunethread.cpp 0
|
||||
|
||||
Finishing off the FortuneThread walkthrough, this is the destructor that
|
||||
sets \e quit to true, wakes up the thread and waits for the thread to exit
|
||||
@ -185,30 +185,30 @@
|
||||
|
||||
Now for the BlockingClient class:
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.h 0
|
||||
\snippet blockingfortuneclient/blockingclient.h 0
|
||||
|
||||
BlockingClient is very similar to the Client class in the
|
||||
\l{network/fortuneclient}{Fortune Client} example, but in this class
|
||||
\l{fortuneclient}{Fortune Client} example, but in this class
|
||||
we store a FortuneThread member instead of a pointer to a QTcpSocket.
|
||||
When the user clicks the "Get Fortune" button, the same slot is called,
|
||||
but its implementation is slightly different:
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.cpp 0
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.cpp 1
|
||||
\snippet blockingfortuneclient/blockingclient.cpp 0
|
||||
\snippet blockingfortuneclient/blockingclient.cpp 1
|
||||
|
||||
We connect our FortuneThread's two signals newFortune() and error() (which
|
||||
are somewhat similar to QTcpSocket::readyRead() and QTcpSocket::error() in
|
||||
the previous example) to requestNewFortune() and displayError().
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.cpp 2
|
||||
\snippet blockingfortuneclient/blockingclient.cpp 2
|
||||
|
||||
The requestNewFortune() slot calls FortuneThread::requestNewFortune(),
|
||||
which \e shedules the request. When the thread has received a new fortune
|
||||
and emits newFortune(), our showFortune() slot is called:
|
||||
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.cpp 3
|
||||
\snippet blockingfortuneclient/blockingclient.cpp 3
|
||||
\codeline
|
||||
\snippet examples/network/blockingfortuneclient/blockingclient.cpp 4
|
||||
\snippet blockingfortuneclient/blockingclient.cpp 4
|
||||
|
||||
Here, we simply display the fortune we received as the argument.
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/broadcastreceiver
|
||||
\example broadcastreceiver
|
||||
\title Broadcast Receiver Example
|
||||
|
||||
The Broadcast Receiver example shows how to receive information that is broadcasted
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/broadcastsender
|
||||
\example broadcastsender
|
||||
\title Broadcast Sender Example
|
||||
|
||||
The Broadcast Sender example shows how to broadcast information to multiple clients
|
@ -26,19 +26,19 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/fortuneclient
|
||||
\example fortuneclient
|
||||
\title Fortune Client Example
|
||||
|
||||
The Fortune Client example shows how to create a client for a simple
|
||||
network service using QTcpSocket. It is intended to be run alongside the
|
||||
\l{network/fortuneserver}{Fortune Server} example or
|
||||
the \l{network/threadedfortuneserver}{Threaded Fortune Server} example.
|
||||
\l{fortuneserver}{Fortune Server} example or
|
||||
the \l{threadedfortuneserver}{Threaded Fortune Server} example.
|
||||
|
||||
\image fortuneclient-example.png Screenshot of the Fortune Client example
|
||||
|
||||
This example uses a simple QDataStream-based data transfer protocol to
|
||||
request a line of text from a fortune server (from the
|
||||
\l{network/fortuneserver}{Fortune Server} example). The client requests a
|
||||
\l{fortuneserver}{Fortune Server} example). The client requests a
|
||||
fortune by simply connecting to the server. The server then responds with
|
||||
a 16-bit (quint16) integer containing the length of the fortune text,
|
||||
followed by a QString.
|
||||
@ -62,12 +62,12 @@
|
||||
\endlist
|
||||
|
||||
In this example, we will demonstrate the asynchronous approach. The
|
||||
\l{network/blockingfortuneclient}{Blocking Fortune Client} example
|
||||
\l{blockingfortuneclient}{Blocking Fortune Client} example
|
||||
illustrates the synchronous approach.
|
||||
|
||||
Our class contains some data and a few private slots:
|
||||
|
||||
\snippet examples/network/fortuneclient/client.h 0
|
||||
\snippet fortuneclient/client.h 0
|
||||
|
||||
Other than the widgets that make up the GUI, the data members include a
|
||||
QTcpSocket pointer, a copy of the fortune text currently displayed, and
|
||||
@ -77,23 +77,23 @@
|
||||
widget as parent, so that we won't have to worry about deleting the
|
||||
socket:
|
||||
|
||||
\snippet examples/network/fortuneclient/client.cpp 0
|
||||
\snippet fortuneclient/client.cpp 0
|
||||
\dots
|
||||
\snippet examples/network/fortuneclient/client.cpp 1
|
||||
\snippet fortuneclient/client.cpp 1
|
||||
|
||||
The only QTcpSocket signals we need in this example are
|
||||
QTcpSocket::readyRead(), signifying that data has been received, and
|
||||
QTcpSocket::error(), which we will use to catch any connection errors:
|
||||
|
||||
\dots
|
||||
\snippet examples/network/fortuneclient/client.cpp 3
|
||||
\snippet fortuneclient/client.cpp 3
|
||||
\dots
|
||||
\snippet examples/network/fortuneclient/client.cpp 5
|
||||
\snippet fortuneclient/client.cpp 5
|
||||
|
||||
Clicking the \uicontrol{Get Fortune} button will invoke the \c
|
||||
requestNewFortune() slot:
|
||||
|
||||
\snippet examples/network/fortuneclient/client.cpp 6
|
||||
\snippet fortuneclient/client.cpp 6
|
||||
|
||||
In this slot, we initialize \c blockSize to 0, preparing to read a new block
|
||||
of data. Because we allow the user to click \uicontrol{Get Fortune} before the
|
||||
@ -119,7 +119,7 @@
|
||||
|
||||
Let's go through the \l{QTcpSocket::error()}{error()} case first:
|
||||
|
||||
\snippet examples/network/fortuneclient/client.cpp 13
|
||||
\snippet fortuneclient/client.cpp 13
|
||||
|
||||
We pop up all errors in a dialog using
|
||||
QMessageBox::information(). QTcpSocket::RemoteHostClosedError is silently
|
||||
@ -129,9 +129,9 @@
|
||||
Now for the \l{QTcpSocket::readyRead()}{readyRead()} alternative. This
|
||||
signal is connected to \c Client::readFortune():
|
||||
|
||||
\snippet examples/network/fortuneclient/client.cpp 8
|
||||
\snippet fortuneclient/client.cpp 8
|
||||
\codeline
|
||||
\snippet examples/network/fortuneclient/client.cpp 10
|
||||
\snippet fortuneclient/client.cpp 10
|
||||
|
||||
The protocol is based on QDataStream, so we start by creating a stream
|
||||
object, passing the socket to QDataStream's constructor. We then
|
||||
@ -148,9 +148,9 @@
|
||||
with the size of the packet, so first we need to ensure that we can read
|
||||
the size, then we will wait until QTcpSocket has received the full packet.
|
||||
|
||||
\snippet examples/network/fortuneclient/client.cpp 11
|
||||
\snippet fortuneclient/client.cpp 11
|
||||
\codeline
|
||||
\snippet examples/network/fortuneclient/client.cpp 12
|
||||
\snippet fortuneclient/client.cpp 12
|
||||
|
||||
We proceed by using QDataStream's streaming operator to read the fortune
|
||||
from the socket into a QString. Once read, we can call QLabel::setText()
|
@ -26,45 +26,45 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/fortuneserver
|
||||
\example fortuneserver
|
||||
\title Fortune Server Example
|
||||
|
||||
The Fortune Server example shows how to create a server for a simple
|
||||
network service. It is intended to be run alongside the
|
||||
\l{network/fortuneclient}{Fortune Client} example or the
|
||||
\l{network/blockingfortuneclient}{Blocking Fortune Client} example.
|
||||
\l{fortuneclient}{Fortune Client} example or the
|
||||
\l{blockingfortuneclient}{Blocking Fortune Client} example.
|
||||
|
||||
\image fortuneserver-example.png Screenshot of the Fortune Server example
|
||||
|
||||
This example uses QTcpServer to accept incoming TCP connections, and a
|
||||
simple QDataStream based data transfer protocol to write a fortune to the
|
||||
connecting client (from the \l{network/fortuneclient}{Fortune Client}
|
||||
connecting client (from the \l{fortuneclient}{Fortune Client}
|
||||
example), before closing the connection.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.h 0
|
||||
\snippet fortuneserver/server.h 0
|
||||
|
||||
The server is implemented using a simple class with only one slot, for
|
||||
handling incoming connections.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 1
|
||||
\snippet fortuneserver/server.cpp 1
|
||||
|
||||
In its constructor, our Server object calls QTcpServer::listen() to set up
|
||||
a QTcpServer to listen on all addresses, on an arbitrary port. In then
|
||||
displays the port QTcpServer picked in a label, so that user knows which
|
||||
port the fortune client should connect to.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 2
|
||||
\snippet fortuneserver/server.cpp 2
|
||||
|
||||
Our server generates a list of random fortunes that is can send to
|
||||
connecting clients.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 3
|
||||
\snippet fortuneserver/server.cpp 3
|
||||
|
||||
When a client connects to our server, QTcpServer will emit
|
||||
QTcpServer::newConnection(). In turn, this will invoke our
|
||||
sendFortune() slot:
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 4
|
||||
\snippet fortuneserver/server.cpp 4
|
||||
|
||||
The purpose of this slot is to select a random line from our list of
|
||||
fortunes, encode it into a QByteArray using QDataStream, and then write it
|
||||
@ -75,7 +75,7 @@
|
||||
we can communicate with clients from future versions of Qt. (See
|
||||
QDataStream::setVersion().)
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 6
|
||||
\snippet fortuneserver/server.cpp 6
|
||||
|
||||
At the start of our QByteArray, we reserve space for a 16 bit integer that
|
||||
will contain the total size of the data block we are sending. We continue
|
||||
@ -84,14 +84,14 @@
|
||||
total size of the array. By doing this, we provide a way for clients to
|
||||
verify how much data they can expect before reading the whole packet.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 7
|
||||
\snippet fortuneserver/server.cpp 7
|
||||
|
||||
We then call QTcpServer::newPendingConnection(), which returns the
|
||||
QTcpSocket representing the server side of the connection. By connecting
|
||||
QTcpSocket::disconnected() to QObject::deleteLater(), we ensure that the
|
||||
socket will be deleted after disconnecting.
|
||||
|
||||
\snippet examples/network/fortuneserver/server.cpp 8
|
||||
\snippet fortuneserver/server.cpp 8
|
||||
|
||||
The encoded fortune is written using QTcpSocket::write(), and we finally
|
||||
call QTcpSocket::disconnectFromHost(), which will close the connection
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/googlesuggest
|
||||
\example googlesuggest
|
||||
\title Google Suggest Example
|
||||
|
||||
The Google Suggest example demonstrates how to use the QNetworkAccessManager
|
||||
@ -48,7 +48,7 @@
|
||||
This class implements an event filter and a number of functions to display
|
||||
the search results and to determent when and how to perform the search.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.h 1
|
||||
\snippet googlesuggest/googlesuggest.h 1
|
||||
|
||||
The class connects to a QLineEdit and uses a QTreeWidget to display the
|
||||
results. A QTimer controls the start of the network requests that are
|
||||
@ -60,7 +60,7 @@
|
||||
queries. This is the basis for the query. The letters typed into the search
|
||||
box will be added to the query to perform the search itself.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 1
|
||||
\snippet googlesuggest/googlesuggest.cpp 1
|
||||
|
||||
In the constructor, we set the parent of this GSuggestCompletion instance
|
||||
to be the QLineEdit passed in. For simplicity, the QLineEdit is also stored
|
||||
@ -84,12 +84,12 @@
|
||||
Finally, we connect the networkManagers \c finished() signal with the \c
|
||||
handleNetworkData() slot to handle the incoming data.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 2
|
||||
\snippet googlesuggest/googlesuggest.cpp 2
|
||||
|
||||
Since the QTreeWidget popup has been instantiated as a toplevel widget, the
|
||||
destructor has to delete it explicitly from memory to avoid a memory leak.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 3
|
||||
\snippet googlesuggest/googlesuggest.cpp 3
|
||||
|
||||
The event filter handles mouse press and key press events that are
|
||||
delivered to the popup. For mouse press events we just hide the popup and
|
||||
@ -106,13 +106,13 @@
|
||||
popup is hidden. This way the user's typing will not be interrupted by the
|
||||
popping up of the completion list.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 4
|
||||
\snippet googlesuggest/googlesuggest.cpp 4
|
||||
|
||||
The \c showCompletion() function populates the QTreeWidget with the results
|
||||
returned from the query. It takes two QStringLists, one with the suggested
|
||||
search terms and the other with the corresponding number of hits.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 5
|
||||
\snippet googlesuggest/googlesuggest.cpp 5
|
||||
|
||||
A QTreeWidgetItem is created for each index in the list and inserted into
|
||||
the QTreeWidget. Finally, we adjust position and size of the popup to make
|
||||
@ -124,24 +124,24 @@
|
||||
make the \c editor QLineEdit emit the returnPressed() signal, to which the
|
||||
application can connect to open the respective web page.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 6
|
||||
\snippet googlesuggest/googlesuggest.cpp 6
|
||||
|
||||
The \c autoSuggest() slot is called when the timer times out, and uses the
|
||||
text in the editor to build the complete search query. The query is then
|
||||
passed to the QNetworkAccessManager's \c get() function to start the
|
||||
request.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 7
|
||||
\snippet googlesuggest/googlesuggest.cpp 7
|
||||
|
||||
The function \c preventSuggest() stops the timer to prevent further
|
||||
requests from being started.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 8
|
||||
\snippet googlesuggest/googlesuggest.cpp 8
|
||||
|
||||
When the network request is finished, the QNetworkAccessManager delivers the
|
||||
data received from the server through the networkReply object.
|
||||
|
||||
\snippet examples/network/googlesuggest/googlesuggest.cpp 9
|
||||
\snippet googlesuggest/googlesuggest.cpp 9
|
||||
|
||||
To extract the data from the reply we use the \c readAll() function, which
|
||||
is inherited from QIODevice and returns a QByteArray. Since this data is
|
||||
@ -160,14 +160,14 @@
|
||||
A \c GSuggestCompletion member provides the SearchBox with the request
|
||||
functionality and the suggestions returned from the Google search engine.
|
||||
|
||||
\snippet examples/network/googlesuggest/searchbox.h 1
|
||||
\snippet googlesuggest/searchbox.h 1
|
||||
|
||||
\section1 SearchBox Class Implementation
|
||||
|
||||
The search box constructor instantiates the GSuggestCompletion object and
|
||||
connects the returnPressed() signal to the doSearch() slot.
|
||||
|
||||
\snippet examples/network/googlesuggest/searchbox.cpp 1
|
||||
\snippet googlesuggest/searchbox.cpp 1
|
||||
|
||||
The function \c doSearch() stops the completer from sending any further
|
||||
queries to the search engine.
|
||||
@ -175,6 +175,6 @@
|
||||
Further, the function extracts the selected search phrase and opens it
|
||||
in the default web browser using QDesktopServices.
|
||||
|
||||
\snippet examples/network/googlesuggest/searchbox.cpp 2
|
||||
\snippet googlesuggest/searchbox.cpp 2
|
||||
|
||||
*/
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/http
|
||||
\example http
|
||||
\title HTTP Example
|
||||
|
||||
The HTTP example demonstrates a simple HTTP client that shows how to fetch files
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/loopback
|
||||
\example loopback
|
||||
\title Loopback Example
|
||||
|
||||
The Loopback example shows how to communicate between simple clients and servers on a local
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/multicastreceiver
|
||||
\example multicastreceiver
|
||||
\title Multicast Receiver Example
|
||||
|
||||
The Multicast Receiever example shows how to receive information that is
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/multicastsender
|
||||
\example multicastsender
|
||||
\title Multicast Sender Example
|
||||
|
||||
The Multicast Sender example shows how to send information to multiple
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/network-chat
|
||||
\example network-chat
|
||||
\title Network Chat Example
|
||||
|
||||
The Network Chat example demonstrates a stateful peer-to-peer Chat client
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/securesocketclient
|
||||
\example securesocketclient
|
||||
\title Secure Socket Client Example
|
||||
|
||||
The Secure Socket Client example shows how to use QSslSocket to
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/threadedfortuneserver
|
||||
\example threadedfortuneserver
|
||||
\title Threaded Fortune Server Example
|
||||
|
||||
The Threaded Fortune Server example shows how to create a server for a
|
||||
@ -36,25 +36,25 @@
|
||||
\image threadedfortuneserver-example.png
|
||||
|
||||
The implementation of this example is similar to that of the
|
||||
\l{network/fortuneserver}{Fortune Server} example, but here we will
|
||||
\l{fortuneserver}{Fortune Server} example, but here we will
|
||||
implement a subclass of QTcpServer that starts each connection in a
|
||||
different thread.
|
||||
|
||||
For this we need two classes: FortuneServer, a QTcpServer subclass, and
|
||||
FortuneThread, which inherits QThread.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortuneserver.h 0
|
||||
\snippet threadedfortuneserver/fortuneserver.h 0
|
||||
|
||||
FortuneServer inherits QTcpServer and reimplements
|
||||
QTcpServer::incomingConnection(). We also use it for storing the list of
|
||||
random fortunes.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortuneserver.cpp 0
|
||||
\snippet threadedfortuneserver/fortuneserver.cpp 0
|
||||
|
||||
We use FortuneServer's constructor to simply generate the list of
|
||||
fortunes.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortuneserver.cpp 1
|
||||
\snippet threadedfortuneserver/fortuneserver.cpp 1
|
||||
|
||||
Our implementation of QTcpServer::incomingConnection() creates a
|
||||
FortuneThread object, passing the incoming socket descriptor and a random
|
||||
@ -63,18 +63,18 @@
|
||||
gets deleted once it has finished. We can then call QThread::start(),
|
||||
which starts the thread.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.h 0
|
||||
\snippet threadedfortuneserver/fortunethread.h 0
|
||||
|
||||
Moving on to the FortuneThread class, this is a QThread subclass whose job
|
||||
is to write the fortune to the connected socket. The class reimplements
|
||||
QThread::run(), and it has a signal for reporting errors.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.cpp 0
|
||||
\snippet threadedfortuneserver/fortunethread.cpp 0
|
||||
|
||||
FortuneThread's constructor simply stores the socket descriptor and
|
||||
fortune text, so that they are available for run() later on.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.cpp 1
|
||||
\snippet threadedfortuneserver/fortunethread.cpp 1
|
||||
|
||||
The first thing our run() function does is to create a QTcpSocket object
|
||||
on the stack. What's worth noticing is that we are creating this object
|
||||
@ -83,19 +83,19 @@
|
||||
to our socket from the main thread while we are accessing it from
|
||||
FortuneThread::run().
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.cpp 2
|
||||
\snippet threadedfortuneserver/fortunethread.cpp 2
|
||||
|
||||
The socket is initialized by calling QTcpSocket::setSocketDescriptor(),
|
||||
passing our socket descriptor as an argument. We expect this to succeed,
|
||||
but just to be sure, (although unlikely, the system may run out of
|
||||
resources,) we catch the return value and report any error.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.cpp 3
|
||||
\snippet threadedfortuneserver/fortunethread.cpp 3
|
||||
|
||||
As with the \l{network/fortuneserver}{Fortune Server} example, we encode
|
||||
As with the \l{fortuneserver}{Fortune Server} example, we encode
|
||||
the fortune into a QByteArray using QDataStream.
|
||||
|
||||
\snippet examples/network/threadedfortuneserver/fortunethread.cpp 4
|
||||
\snippet threadedfortuneserver/fortunethread.cpp 4
|
||||
|
||||
But unlike the previous example, we finish off by calling
|
||||
QTcpSocket::waitForDisconnected(), which blocks the calling thread until
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example network/torrent
|
||||
\example torrent
|
||||
\title Torrent Example
|
||||
|
||||
The Torrent example is a functional BitTorrent client that
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/2dpainting
|
||||
\example 2dpainting
|
||||
\title 2D Painting Example
|
||||
|
||||
The 2D Painting example shows how QPainter and QGLWidget can be used
|
||||
@ -66,7 +66,7 @@
|
||||
|
||||
The \c Helper class is minimal:
|
||||
|
||||
\snippet examples/opengl/2dpainting/helper.h 0
|
||||
\snippet 2dpainting/helper.h 0
|
||||
|
||||
Apart from the constructor, it only provides a \c paint() function to paint
|
||||
using a painter supplied by one of our widget subclasses.
|
||||
@ -76,7 +76,7 @@
|
||||
The constructor of the class sets up the resources it needs to paint
|
||||
content onto a widget:
|
||||
|
||||
\snippet examples/opengl/2dpainting/helper.cpp 0
|
||||
\snippet 2dpainting/helper.cpp 0
|
||||
|
||||
The actual painting is performed in the \c paint() function. This takes
|
||||
a QPainter that has already been set up to paint onto a paint device
|
||||
@ -84,7 +84,7 @@
|
||||
about the region to be painted, and a measure of the elapsed time (in
|
||||
milliseconds) since the paint device was last updated.
|
||||
|
||||
\snippet examples/opengl/2dpainting/helper.cpp 1
|
||||
\snippet 2dpainting/helper.cpp 1
|
||||
|
||||
We begin painting by filling in the region contained in the paint event
|
||||
before translating the origin of the coordinate system so that the rest
|
||||
@ -95,13 +95,13 @@
|
||||
animate them so that they appear to move outward and around the coordinate
|
||||
system's origin:
|
||||
|
||||
\snippet examples/opengl/2dpainting/helper.cpp 2
|
||||
\snippet 2dpainting/helper.cpp 2
|
||||
|
||||
Since the coordinate system is rotated many times during
|
||||
this process, we \l{QPainter::save()}{save()} the QPainter's state
|
||||
beforehand and \l{QPainter::restore()}{restore()} it afterwards.
|
||||
|
||||
\snippet examples/opengl/2dpainting/helper.cpp 3
|
||||
\snippet 2dpainting/helper.cpp 3
|
||||
|
||||
We draw some text at the origin to complete the effect.
|
||||
|
||||
@ -110,7 +110,7 @@
|
||||
The \c Widget class provides a basic custom widget that we use to
|
||||
display the simple animation painted by the \c Helper class.
|
||||
|
||||
\snippet examples/opengl/2dpainting/widget.h 0
|
||||
\snippet 2dpainting/widget.h 0
|
||||
|
||||
Apart from the constructor, it only contains a
|
||||
\l{QWidget::paintEvent()}{paintEvent()} function, that lets us draw
|
||||
@ -125,12 +125,12 @@
|
||||
\c Helper object supplied and calling the base class's constructor,
|
||||
and enforces a fixed size for the widget:
|
||||
|
||||
\snippet examples/opengl/2dpainting/widget.cpp 0
|
||||
\snippet 2dpainting/widget.cpp 0
|
||||
|
||||
The \c animate() slot is called whenever a timer, which we define later, times
|
||||
out:
|
||||
|
||||
\snippet examples/opengl/2dpainting/widget.cpp 1
|
||||
\snippet 2dpainting/widget.cpp 1
|
||||
|
||||
Here, we determine the interval that has elapsed since the timer last
|
||||
timed out, and we add it to any existing value before repainting the
|
||||
@ -142,14 +142,14 @@
|
||||
to implement a paint event that sets up a QPainter for the widget and calls
|
||||
the helper's \c paint() function:
|
||||
|
||||
\snippet examples/opengl/2dpainting/widget.cpp 2
|
||||
\snippet 2dpainting/widget.cpp 2
|
||||
|
||||
\section1 GLWidget Class Definition
|
||||
|
||||
The \c GLWidget class definition is basically the same as the \c Widget
|
||||
class except that it is derived from QGLWidget.
|
||||
|
||||
\snippet examples/opengl/2dpainting/glwidget.h 0
|
||||
\snippet 2dpainting/glwidget.h 0
|
||||
|
||||
Again, the member variables record the \c Helper used to paint the
|
||||
widget and the elapsed time since the previous update.
|
||||
@ -158,7 +158,7 @@
|
||||
|
||||
The constructor differs a little from the \c Widget class's constructor:
|
||||
|
||||
\snippet examples/opengl/2dpainting/glwidget.cpp 0
|
||||
\snippet 2dpainting/glwidget.cpp 0
|
||||
|
||||
As well as initializing the \c elapsed member variable and storing the
|
||||
\c Helper object used to paint the widget, the base class's constructor
|
||||
@ -169,11 +169,11 @@
|
||||
The \c animate() slot is exactly the same as that provided by the \c Widget
|
||||
class:
|
||||
|
||||
\snippet examples/opengl/2dpainting/glwidget.cpp 1
|
||||
\snippet 2dpainting/glwidget.cpp 1
|
||||
|
||||
The \c paintEvent() is almost the same as that found in the \c Widget class:
|
||||
|
||||
\snippet examples/opengl/2dpainting/glwidget.cpp 2
|
||||
\snippet 2dpainting/glwidget.cpp 2
|
||||
|
||||
Since anti-aliasing will be enabled if available, we only need to set up
|
||||
a QPainter on the widget and call the helper's \c paint() function to display
|
||||
@ -183,7 +183,7 @@
|
||||
|
||||
The \c Window class has a basic, minimal definition:
|
||||
|
||||
\snippet examples/opengl/2dpainting/window.h 0
|
||||
\snippet 2dpainting/window.h 0
|
||||
|
||||
It contains a single \c Helper object that will be shared between all
|
||||
widgets.
|
||||
@ -193,7 +193,7 @@
|
||||
The constructor does all the work, creating a widget of each type and
|
||||
inserting them with labels into a layout:
|
||||
|
||||
\snippet examples/opengl/2dpainting/window.cpp 0
|
||||
\snippet 2dpainting/window.cpp 0
|
||||
|
||||
A timer with a 50 millisecond time out is constructed for animation purposes,
|
||||
and connected to the \c animate() slots of the \c Widget and \c GLWidget objects.
|
178
examples/opengl/doc/src/cube.qdoc
Normal file
@ -0,0 +1,178 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example cube
|
||||
\group all-examples
|
||||
\title Cube OpenGL ES 2.0 example
|
||||
|
||||
The Cube OpenGL ES 2.0 example shows how to write mouse rotateable
|
||||
textured 3D cube using OpenGL ES 2.0 with Qt. It shows how to handle
|
||||
polygon geometries efficiently and how to write simple vertex and
|
||||
fragment shader for programmable graphics pipeline. In addition it
|
||||
shows how to use quaternions for representing 3D object orientation.
|
||||
|
||||
This example has been written for OpenGL ES 2.0 but it works also on
|
||||
desktop OpenGL because this example is simple enough and for the
|
||||
most parts desktop OpenGL API is same. It compiles also without OpenGL
|
||||
support but then it just shows a label stating that OpenGL support is
|
||||
required.
|
||||
|
||||
\image cube.png Screenshot of the Cube example running on N900
|
||||
|
||||
The example consist of two classes:
|
||||
|
||||
\list
|
||||
\li \c MainWidget extends QGLWidget and contains OpenGL ES 2.0
|
||||
initialization and drawing and mouse and timer event handling
|
||||
\li \c GeometryEngine handles polygon geometries. Transfers polygon geometry
|
||||
to vertex buffer objects and draws geometries from vertex buffer objects.
|
||||
\endlist
|
||||
|
||||
We'll start by initializing OpenGL ES 2.0 in \c MainWidget.
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\section1 Initializing OpenGL ES 2.0
|
||||
|
||||
Since OpenGL ES 2.0 doesn't support fixed graphics pipeline anymore it has to
|
||||
be implemented by ourselves. This makes graphics pipeline very flexible but
|
||||
in the same time it becomes more difficult because user has to implement graphics
|
||||
pipeline to get even the simplest example running. It also makes graphics pipeline
|
||||
more efficient because user can decide what kind of pipeline is needed for the
|
||||
application.
|
||||
|
||||
First we have to implement vertex shader. It gets vertex data and
|
||||
model-view-projection matrix (MVP) as parameters. It transforms vertex position
|
||||
using MVP matrix to screen space and passes texture coordinate to
|
||||
fragment shader. Texture coordinate will be automatically interpolated on polygon
|
||||
faces.
|
||||
|
||||
\snippet cube/vshader.glsl 0
|
||||
|
||||
After that we need to implement second part of the graphics pipeline - fragment
|
||||
shader. For this exercise we need to implement fragment shader that handles
|
||||
texturing. It gets interpolated texture coordinate as a parameter and looks up
|
||||
fragment color from the given texture.
|
||||
|
||||
\snippet cube/fshader.glsl 0
|
||||
|
||||
Using \c QGLShaderProgram we can compile, link and bind shader code to
|
||||
graphics pipeline. This code uses Qt Resource files to access shader source code.
|
||||
|
||||
\snippet cube/mainwidget.cpp 3
|
||||
|
||||
The following code enables depth buffering and back face culling.
|
||||
|
||||
\snippet cube/mainwidget.cpp 2
|
||||
|
||||
\section1 Loading textures from Qt Resource files
|
||||
|
||||
\c QGLWidget interface implements methods for loading textures from QImage to GL
|
||||
texture memory. We still need to use OpenGL provided functions for specifying
|
||||
the GL texture unit and configuring texture filtering options.
|
||||
|
||||
\snippet cube/mainwidget.cpp 4
|
||||
|
||||
\section1 Cube Geometry
|
||||
|
||||
There are many ways to render polygons in OpenGL but the most efficient way is
|
||||
to use only triangle strip primitives and render vertices from graphics hardware
|
||||
memory. OpenGL has a mechanism to create buffer objects to this memory area and
|
||||
transfer vertex data to these buffers. In OpenGL terminology these are referred
|
||||
as Vertex Buffer Objects (VBO).
|
||||
|
||||
\image cube_faces.png Cube faces and vertices
|
||||
|
||||
This is how cube faces break down to triangles. Vertices are ordered this way
|
||||
to get vertex ordering correct using triangle strips. OpenGL determines triangle
|
||||
front and back face based on vertex ordering. By default OpenGL uses
|
||||
counter-clockwise order for front faces. This information is used by back face
|
||||
culling which improves rendering performance by not rendering back faces of the
|
||||
triangles. This way graphics pipeline can omit rendering sides of the triangle that
|
||||
aren't facing towards screen.
|
||||
|
||||
Creating vertex buffer objects and transferring data to them is quite simple using
|
||||
OpenGL provided functions.
|
||||
|
||||
\snippet cube/geometryengine.cpp 0
|
||||
|
||||
\snippet cube/geometryengine.cpp 1
|
||||
|
||||
Drawing primitives from VBOs and telling programmable graphics pipeline how to
|
||||
locate vertex data requires few steps. First we need to bind VBOs to be used.
|
||||
After that we bind shader program attribute names and configure what
|
||||
kind of data it has in the bound VBO. Finally we'll draw triangle
|
||||
strip primitives using indices from the other VBO.
|
||||
|
||||
\snippet cube/geometryengine.cpp 2
|
||||
|
||||
\section1 Perspective projection
|
||||
|
||||
Using \c QMatrix4x4 helper methods it's really easy to calculate perpective
|
||||
projection matrix. This matrix is used to project vertices to screen space.
|
||||
|
||||
\snippet cube/mainwidget.cpp 5
|
||||
|
||||
\section1 Orientation of the 3D object
|
||||
|
||||
Quaternions are handy way to represent orientation of the 3D object. Quaternions
|
||||
involve quite complex mathematics but fortunately all the necessary mathematics
|
||||
behind quaternions is implemented in \c QQuaternion. That allows us to store
|
||||
cube orientation in quaternion and rotating cube around given axis is quite
|
||||
simple.
|
||||
|
||||
The following code calculates rotation axis and angular speed based on mouse events.
|
||||
|
||||
\snippet cube/mainwidget.cpp 0
|
||||
|
||||
\c QBasicTimer is used to animate scene and update cube orientation. Rotations
|
||||
can be concatenated simply by multiplying quaternions.
|
||||
|
||||
\snippet cube/mainwidget.cpp 1
|
||||
|
||||
Model-view matrix is calculated using the quaternion and by moving world by Z axis.
|
||||
This matrix is multiplied with the projection matrix to get MVP matrix for shader
|
||||
program.
|
||||
|
||||
\snippet cube/mainwidget.cpp 6
|
||||
|
||||
*/
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/framebufferobject2
|
||||
\example framebufferobject2
|
||||
\title Framebuffer Object 2 Example
|
||||
|
||||
The Framebuffer Object 2 example demonstrates how to use the
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/grabber
|
||||
\example grabber
|
||||
\title Grabber Example
|
||||
|
||||
The Grabber examples shows how to retrieve the contents of an OpenGL framebuffer.
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/hellogl
|
||||
\example hellogl
|
||||
\title Hello GL Example
|
||||
|
||||
The Hello GL example demonstrates the basic use of the OpenGL-related classes
|
||||
@ -48,18 +48,18 @@
|
||||
constructor, destructor, \l{QWidget::sizeHint()}{sizeHint()}, and
|
||||
\l{QWidget::minimumSizeHint()}{minimumSizeHint()} functions:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.h 0
|
||||
\snippet hellogl/glwidget.h 0
|
||||
|
||||
We use a destructor to ensure that any OpenGL-specific data structures
|
||||
are deleted when the widget is no longer needed (although in this case nothing
|
||||
needs cleaning up).
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.h 1
|
||||
\snippet hellogl/glwidget.h 1
|
||||
|
||||
The signals and slots are used to allow other objects to interact with the
|
||||
3D scene.
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.h 2
|
||||
\snippet hellogl/glwidget.h 2
|
||||
|
||||
OpenGL initialization, viewport resizing, and painting are handled by
|
||||
reimplementing the QGLWidget::initializeGL(), QGLWidget::resizeGL(), and
|
||||
@ -67,7 +67,7 @@
|
||||
directly with the scene using the mouse, we reimplement
|
||||
QWidget::mousePressEvent() and QWidget::mouseMoveEvent().
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.h 3
|
||||
\snippet hellogl/glwidget.h 3
|
||||
|
||||
The rest of the class contains utility functions and variables that are
|
||||
used to construct and hold orientation information for the scene. The
|
||||
@ -86,27 +86,27 @@
|
||||
the pointer to the QtLogo object to null, and sets up some colors for
|
||||
later use.
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 0
|
||||
\snippet hellogl/glwidget.cpp 0
|
||||
|
||||
We also implement a destructor to release OpenGL-related resources when the
|
||||
widget is deleted:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 1
|
||||
\snippet hellogl/glwidget.cpp 1
|
||||
|
||||
In this case nothing requires cleaning up.
|
||||
|
||||
We provide size hint functions to ensure that the widget is shown at a
|
||||
reasonable size:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 2
|
||||
\snippet hellogl/glwidget.cpp 2
|
||||
\codeline
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 3
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 4
|
||||
\snippet hellogl/glwidget.cpp 3
|
||||
\snippet hellogl/glwidget.cpp 4
|
||||
|
||||
The widget provides three slots that enable other components in the
|
||||
example to change the orientation of the scene:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 5
|
||||
\snippet hellogl/glwidget.cpp 5
|
||||
|
||||
In the above slot, the \c xRot variable is updated only if the new angle
|
||||
is different to the old one, the \c xRotationChanged() signal is emitted to
|
||||
@ -124,7 +124,7 @@
|
||||
certain rendering flags, and setting other properties used to customize the
|
||||
rendering process.
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 6
|
||||
\snippet hellogl/glwidget.cpp 6
|
||||
|
||||
In this example, we reimplement the function to set the background color,
|
||||
create a QtLogo object instance which will contain all the geometry to
|
||||
@ -143,7 +143,7 @@
|
||||
based on the length of the smallest side of the widget to ensure that
|
||||
the scene is not distorted if the widget has sides of unequal length:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 8
|
||||
\snippet hellogl/glwidget.cpp 8
|
||||
|
||||
A discussion of the projection transformation used is outside the scope of
|
||||
this example. Please consult the OpenGL reference documentation for an
|
||||
@ -156,7 +156,7 @@
|
||||
decorated with pure OpenGL content, we reimplement QGLWidget::paintGL()
|
||||
\e instead of reimplementing QWidget::paintEvent():
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 7
|
||||
\snippet hellogl/glwidget.cpp 7
|
||||
|
||||
In this example, we clear the widget using the background color that
|
||||
we defined in the \l{QGLWidget::initializeGL()}{initializeGL()} function,
|
||||
@ -172,13 +172,13 @@
|
||||
The \l{QWidget::mousePressEvent()}{mousePressEvent()} function simply
|
||||
records the position of the mouse when a button is initially pressed:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 9
|
||||
\snippet hellogl/glwidget.cpp 9
|
||||
|
||||
The \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} function uses the
|
||||
previous location of the mouse cursor to determine how much the object
|
||||
in the scene should be rotated, and in which direction:
|
||||
|
||||
\snippet examples/opengl/hellogl/glwidget.cpp 10
|
||||
\snippet hellogl/glwidget.cpp 10
|
||||
|
||||
Since the user is expected to hold down the mouse button and drag the
|
||||
cursor to rotate the object, the cursor's position is updated every time
|
||||
@ -189,14 +189,14 @@
|
||||
This class encapsulates the OpenGL geometry data which will be rendered
|
||||
in the basic 3D scene.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.h 0
|
||||
\snippet shared/qtlogo.h 0
|
||||
|
||||
The geometry is divided into a list of parts which may be rendered in
|
||||
different ways. The data itself is contained in a Geometry structure that
|
||||
includes the vertices, their lighting normals and index values which
|
||||
point into the vertices, grouping them into faces.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.cpp 0
|
||||
\snippet shared/qtlogo.cpp 0
|
||||
|
||||
The data in the Geometry class is stored in QVector<QVector3D> members
|
||||
which are convenient for use with OpenGL because they expose raw
|
||||
@ -204,7 +204,7 @@
|
||||
are included for adding new vertex data, either with smooth normals, or
|
||||
facetted normals; and for enabling the geometry ready for rendering.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.cpp 1
|
||||
\snippet shared/qtlogo.cpp 1
|
||||
|
||||
The higher level Patch class has methods for accumulating the geometry
|
||||
one face at a time, and treating collections of faces or "patches" with
|
||||
@ -212,14 +212,14 @@
|
||||
may be added as triangles or quads, at the OpenGL level all data is
|
||||
treated as triangles for compatibility with OpenGL/ES.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.cpp 2
|
||||
\snippet shared/qtlogo.cpp 2
|
||||
|
||||
Drawing a Patch is simply acheived by applying any transformation,
|
||||
and material effect, then drawing the data using the index range for
|
||||
the patch. The model-view matrix is saved and then restored so that
|
||||
any transformation does not affect other parts of the scene.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.cpp 3
|
||||
\snippet shared/qtlogo.cpp 3
|
||||
|
||||
The geometry is built once on construction of the QtLogo, and it is
|
||||
paramaterized on a number of divisions - which controls how "chunky" the
|
||||
@ -231,7 +231,7 @@
|
||||
details) which only exist during the build phase, to assemble the parts
|
||||
of the scene.
|
||||
|
||||
\snippet examples/opengl/shared/qtlogo.cpp 4
|
||||
\snippet shared/qtlogo.cpp 4
|
||||
|
||||
Finally the complete QtLogo scene is simply drawn by enabling the data arrays
|
||||
and then iterating over the parts, calling draw() on each one.
|
||||
@ -241,7 +241,7 @@
|
||||
The \c Window class is used as a container for the \c GLWidget used to
|
||||
display the scene:
|
||||
|
||||
\snippet examples/opengl/hellogl/window.h 0
|
||||
\snippet hellogl/window.h 0
|
||||
|
||||
In addition, it contains sliders that are used to change the orientation
|
||||
of the object in the scene.
|
||||
@ -251,7 +251,7 @@
|
||||
The constructor constructs an instance of the \c GLWidget class and some
|
||||
sliders to manipulate its contents.
|
||||
|
||||
\snippet examples/opengl/hellogl/window.cpp 0
|
||||
\snippet hellogl/window.cpp 0
|
||||
|
||||
We connect the \l{QAbstractSlider::valueChanged()}{valueChanged()} signal
|
||||
from each of the sliders to the appropriate slots in \c{glWidget}.
|
||||
@ -263,7 +263,7 @@
|
||||
\l{QAbstractSlider::setValue()}{setValue()} slots in the
|
||||
corresponding sliders.
|
||||
|
||||
\snippet examples/opengl/hellogl/window.cpp 1
|
||||
\snippet hellogl/window.cpp 1
|
||||
|
||||
The sliders are placed horizontally in a layout alongside the \c GLWidget,
|
||||
and initialized with suitable default values.
|
||||
@ -272,7 +272,7 @@
|
||||
that it is set up with a suitable range, step value, tick interval, and
|
||||
page step value before returning it to the calling function:
|
||||
|
||||
\snippet examples/opengl/hellogl/window.cpp 2
|
||||
\snippet hellogl/window.cpp 2
|
||||
|
||||
\section1 Summary
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/hellogl_es
|
||||
\example hellogl_es
|
||||
\title Hello GL ES Example
|
||||
|
||||
The Hello GL ES example is the \l{Hello GL Example} ported to OpenGL ES.
|
||||
@ -59,18 +59,18 @@
|
||||
sides of the quad and hardcode a distance of 0.05f. We also compute the
|
||||
correct normal for each face and store them in another QList.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 0
|
||||
\snippet hellogl_es/glwidget.cpp 0
|
||||
|
||||
And then we convert the complete list of vertexes and the list of normals
|
||||
into the native OpenGL ES format that we can use with the OpenGL ES API.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 1
|
||||
\snippet hellogl_es/glwidget.cpp 1
|
||||
|
||||
In \c paintQtLogo() we draw the triangle array using OpenGL ES. We use
|
||||
q_vertexTypeEnum to abstract the fact that our vertex and normal arrays
|
||||
are either in float or in fixed point format.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 2
|
||||
\snippet hellogl_es/glwidget.cpp 2
|
||||
|
||||
\section1 Using QGLPainter
|
||||
|
||||
@ -78,42 +78,42 @@
|
||||
the rasterizer and cache them in a QImage. This happends only once during
|
||||
the initialiazation.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/bubble.cpp 0
|
||||
\snippet hellogl_es/bubble.cpp 0
|
||||
|
||||
For each bubble this QImage is then drawn to the QGLWidget by using the
|
||||
according QPainter with transparency enabled.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/bubble.cpp 1
|
||||
\snippet hellogl_es/bubble.cpp 1
|
||||
|
||||
Another difference beetwen OpenGL and OpenGL ES is that OpenGL ES does not
|
||||
support glPushAttrib(GL_ALL_ATTRIB_BITS). So we have to restore all the
|
||||
OpenGL states ourselves, after we created the QPainter in
|
||||
GLWidget::paintGL().
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 3
|
||||
\snippet hellogl_es/glwidget.cpp 3
|
||||
|
||||
Setting up up the model view matrix and setting the right OpenGL states is
|
||||
done in the same way as for standard OpenGL.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 4
|
||||
\snippet hellogl_es/glwidget.cpp 4
|
||||
|
||||
Now we have to restore the OpenGL state for the QPainter. This is not done
|
||||
automatically for OpenGL ES.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 5
|
||||
\snippet hellogl_es/glwidget.cpp 5
|
||||
|
||||
Now we use the QPainter to draw the transparent bubbles.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 6
|
||||
\snippet hellogl_es/glwidget.cpp 6
|
||||
|
||||
In the end, we calculate the framerate and display it using the QPainter
|
||||
again.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 7
|
||||
\snippet hellogl_es/glwidget.cpp 7
|
||||
|
||||
After we finished all the drawing operations we swap the screen buffer.
|
||||
|
||||
\snippet examples/opengl/hellogl_es/glwidget.cpp 8
|
||||
\snippet hellogl_es/glwidget.cpp 8
|
||||
|
||||
\section1 Summary
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/overpainting
|
||||
\example overpainting
|
||||
\title Overpainting Example
|
||||
|
||||
The Overpainting example shows how QPainter can be used
|
||||
@ -62,11 +62,11 @@
|
||||
class as a whole, we show the first few lines of the class and only
|
||||
discuss the changes we have made to the rest of it:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.h 0
|
||||
\snippet overpainting/glwidget.h 0
|
||||
\dots
|
||||
\snippet examples/opengl/overpainting/glwidget.h 1
|
||||
\snippet overpainting/glwidget.h 1
|
||||
\dots
|
||||
\snippet examples/opengl/overpainting/glwidget.h 4
|
||||
\snippet overpainting/glwidget.h 4
|
||||
|
||||
As usual, the widget uses \l{QGLWidget::initializeGL()}{initializeGL()}
|
||||
to set up geometry for our scene and perform OpenGL initialization tasks.
|
||||
@ -94,7 +94,7 @@
|
||||
relevant to this example. In the constructor, we initialize a QTimer to
|
||||
control the animation:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 0
|
||||
\snippet overpainting/glwidget.cpp 0
|
||||
|
||||
We turn off the widget's \l{QWidget::autoFillBackground}{autoFillBackground} property to
|
||||
instruct OpenGL not to paint a background for the widget when
|
||||
@ -103,13 +103,13 @@
|
||||
As in the \l{Hello GL Example}{Hello GL} example, the destructor is responsible
|
||||
for freeing any OpenGL-related resources:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 1
|
||||
\snippet overpainting/glwidget.cpp 1
|
||||
|
||||
The \c initializeGL() function is fairly minimal, only setting up the QtLogo
|
||||
object used in the scene. See the \l{Hello GL Example}{Hello GL} example
|
||||
for details of the QtLogo class.
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 2
|
||||
\snippet overpainting/glwidget.cpp 2
|
||||
|
||||
To cooperate fully with QPainter, we defer matrix stack operations and attribute
|
||||
initialization until the widget needs to be updated.
|
||||
@ -126,12 +126,12 @@
|
||||
and other attributes. We use an OpenGL stack operation to preserve the
|
||||
original matrix state, allowing us to recover it later:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 4
|
||||
\snippet overpainting/glwidget.cpp 4
|
||||
|
||||
We define a color to use for the widget's background, and set up various
|
||||
attributes that define how the scene will be rendered.
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 6
|
||||
\snippet overpainting/glwidget.cpp 6
|
||||
|
||||
We call the \c setupViewport() private function to set up the
|
||||
projection used for the scene. This is unnecessary in OpenGL
|
||||
@ -144,21 +144,21 @@
|
||||
an OpenGL call to paint it before positioning the object defined earlier
|
||||
in the scene:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 7
|
||||
\snippet overpainting/glwidget.cpp 7
|
||||
|
||||
Once the QtLogo object's draw method has been executed, the GL
|
||||
states we changed and the matrix stack needs to be restored to its
|
||||
original state at the start of this function before we can begin
|
||||
overpainting:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 8
|
||||
\snippet overpainting/glwidget.cpp 8
|
||||
|
||||
With the 3D graphics done, we construct a QPainter for use on the widget
|
||||
and simply overpaint the widget with 2D graphics; in this case, using a
|
||||
helper class to draw a number of translucent bubbles onto the widget,
|
||||
and calling \c drawInstructions() to overlay some instructions:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 10
|
||||
\snippet overpainting/glwidget.cpp 10
|
||||
|
||||
When QPainter::end() is called, suitable OpenGL-specific calls are made to
|
||||
write the scene, and its additional contents, onto the widget.
|
||||
@ -173,14 +173,14 @@
|
||||
sets up the dimensions of the viewport and defines a projection
|
||||
transformation:
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 11
|
||||
\snippet overpainting/glwidget.cpp 11
|
||||
|
||||
Ideally, we want to arrange the 2D graphics to suit the widget's dimensions.
|
||||
To achieve this, we implement the \l{QWidget::showEvent()}{showEvent()} handler,
|
||||
creating new graphic elements (bubbles) if necessary at appropriate positions
|
||||
in the widget.
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 12
|
||||
\snippet overpainting/glwidget.cpp 12
|
||||
|
||||
This function only has an effect if less than 20 bubbles have already been
|
||||
created.
|
||||
@ -189,7 +189,7 @@
|
||||
the \l{QTimer::timeout()}{timeout()} signal. This keeps the bubbles moving
|
||||
around.
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 13
|
||||
\snippet overpainting/glwidget.cpp 13
|
||||
|
||||
We simply iterate over the bubbles in the \c bubbles list, updating the
|
||||
widget before and after each of them is moved.
|
||||
@ -197,13 +197,13 @@
|
||||
The \c setupViewport() function is called from \c paintEvent()
|
||||
and \c resizeGL().
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 14
|
||||
\snippet overpainting/glwidget.cpp 14
|
||||
|
||||
The \c drawInstructions() function is used to prepare some basic
|
||||
instructions that will be painted with the other 2D graphics over
|
||||
the 3D scene.
|
||||
|
||||
\snippet examples/opengl/overpainting/glwidget.cpp 15
|
||||
\snippet overpainting/glwidget.cpp 15
|
||||
|
||||
\section1 Summary
|
||||
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/pbuffers
|
||||
\example pbuffers
|
||||
\title Pixel Buffers Example
|
||||
|
||||
The Pixel Buffers example demonstrates how to use the
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/pbuffers2
|
||||
\example pbuffers2
|
||||
\title Pixel Buffers 2 Example
|
||||
|
||||
The Pixel Buffers 2 example demonstrates how to use the
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/samplebuffers
|
||||
\example samplebuffers
|
||||
\title Sample Buffers Example
|
||||
|
||||
The Sample Buffers example demonstrates how to use and enable
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example opengl/textures
|
||||
\example textures
|
||||
\title Textures Example
|
||||
|
||||
The Textures example demonstrates the use of Qt's image classes as textures in
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/cachedtable
|
||||
\example cachedtable
|
||||
\title Cached Table Example
|
||||
|
||||
The Cached Table example shows how a table view can be used to access a database,
|
||||
@ -45,7 +45,7 @@
|
||||
The \c TableEditor class inherits QDialog making the table editor
|
||||
widget a top-level dialog window.
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.h 0
|
||||
\snippet cachedtable/tableeditor.h 0
|
||||
|
||||
The \c TableEditor constructor takes two arguments: The first is a
|
||||
pointer to the parent widget and is passed on to the base class
|
||||
@ -73,14 +73,14 @@
|
||||
Before we can use the \c TableEditor class, we must create a
|
||||
connection to the database containing the table we want to edit:
|
||||
|
||||
\snippet examples/sql/cachedtable/main.cpp 0
|
||||
\snippet cachedtable/main.cpp 0
|
||||
|
||||
The \c createConnection() function is a helper function provided
|
||||
for convenience. It is defined in the \c connection.h file which
|
||||
is located in the \c sql example directory (all the examples in
|
||||
the \c sql directory use this function to connect to a database).
|
||||
|
||||
\snippet examples/sql/connection.h 0
|
||||
\snippet connection.h 0
|
||||
|
||||
The \c createConnection function opens a connection to an
|
||||
in-memory SQLITE database and creates a test table. If you want
|
||||
@ -93,7 +93,7 @@
|
||||
constructor and the \c submit() slot. In the constructor we create
|
||||
and customize the data model and the various window elements:
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 0
|
||||
\snippet cachedtable/tableeditor.cpp 0
|
||||
|
||||
First we create the data model and set the SQL database table we
|
||||
want the model to operate on. Note that the
|
||||
@ -116,7 +116,7 @@
|
||||
the \l {QSqlQueryModel::setHeaderData()}{setHeaderData()} function
|
||||
that the model inherits from the QSqlQueryModel class.
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 1
|
||||
\snippet cachedtable/tableeditor.cpp 1
|
||||
|
||||
Then we create a table view. The QTableView class provides a
|
||||
default model/view implementation of a table view, i.e. it
|
||||
@ -129,7 +129,7 @@
|
||||
To make the view present our data, we pass our model to the view
|
||||
using the \l {QAbstractItemView::setModel()}{setModel()} function.
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 2
|
||||
\snippet cachedtable/tableeditor.cpp 2
|
||||
|
||||
The \c {TableEditor}'s buttons are regular QPushButton objects. We
|
||||
add them to a button box to ensure that the buttons are presented
|
||||
@ -150,7 +150,7 @@
|
||||
use. They exist as flags so you can OR them together in the
|
||||
constructor.
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 3
|
||||
\snippet cachedtable/tableeditor.cpp 3
|
||||
|
||||
We connect the \uicontrol Quit button to the table editor's \l
|
||||
{QWidget::close()}{close()} slot, and the \uicontrol Submit button to
|
||||
@ -159,13 +159,13 @@
|
||||
to our model's \l {QSqlTableModel::revertAll()}{revertAll()} slot,
|
||||
reverting all pending changes (i.e., restoring the original data).
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 4
|
||||
\snippet cachedtable/tableeditor.cpp 4
|
||||
|
||||
In the end we add the button box and the table view to a layout,
|
||||
install the layout on the table editor widget, and set the
|
||||
editor's window title.
|
||||
|
||||
\snippet examples/sql/cachedtable/tableeditor.cpp 5
|
||||
\snippet cachedtable/tableeditor.cpp 5
|
||||
|
||||
The \c submit() slot is called whenever the users hit the \uicontrol
|
||||
Submit button to save their changes.
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/drilldown
|
||||
\example drilldown
|
||||
\title Drill Down Example
|
||||
|
||||
The Drill Down example shows how to read data from a database as
|
||||
@ -66,7 +66,7 @@
|
||||
The \c InformationWindow class is a custom widget inheriting
|
||||
QWidget:
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.h 0
|
||||
\snippet drilldown/informationwindow.h 0
|
||||
|
||||
When we create an information window, we pass the associated
|
||||
location ID, a parent, and a pointer to the database, to the
|
||||
@ -81,14 +81,14 @@
|
||||
we will emit a signal carrying the ID and file name as parameters
|
||||
whenever the users changes the associated image.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.h 1
|
||||
\snippet drilldown/informationwindow.h 1
|
||||
|
||||
Since we allow the users to alter some of the location data, we
|
||||
must provide functionality for reverting and submitting their
|
||||
changes. The \c enableButtons() slot is provided for convenience
|
||||
to enable and disable the various buttons when required.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.h 2
|
||||
\snippet drilldown/informationwindow.h 2
|
||||
|
||||
The \c createButtons() function is also a convenience function,
|
||||
provided to simplify the constructor. As mentioned above we store
|
||||
@ -114,15 +114,15 @@
|
||||
pointer to a QSqlRelationalTableModel object providing an editable
|
||||
data model (with foreign key support) for our database table.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 0
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 1
|
||||
\snippet drilldown/informationwindow.cpp 0
|
||||
\snippet drilldown/informationwindow.cpp 1
|
||||
|
||||
First we create the various widgets required to display the data
|
||||
contained in the database. Most of the widgets are created in a
|
||||
straight forward manner. But note the combobox displaying the
|
||||
name of the image file:
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 2
|
||||
\snippet drilldown/informationwindow.cpp 2
|
||||
|
||||
In this example, the information about the offices are stored in a
|
||||
database table called "offices". When creating the model,
|
||||
@ -143,7 +143,7 @@
|
||||
column we want to be visible using the QComboBox::setModelColumn()
|
||||
function.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 3
|
||||
\snippet drilldown/informationwindow.cpp 3
|
||||
|
||||
Then we create the mapper. The QDataWidgetMapper class allows us
|
||||
to create data-aware widgets by mapping them to sections of an
|
||||
@ -169,7 +169,7 @@
|
||||
combobox functionality for fields that are foreign keys into other
|
||||
tables (like "imagefile" in our "trolltechoffices" table).
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 4
|
||||
\snippet drilldown/informationwindow.cpp 4
|
||||
|
||||
Finally, we connect the "something's changed" signals in the
|
||||
editors to our custom \c enableButtons() slot, enabling the users
|
||||
@ -182,7 +182,7 @@
|
||||
our widget is in fact a window, with a window system frame and a
|
||||
title bar.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 5
|
||||
\snippet drilldown/informationwindow.cpp 5
|
||||
|
||||
When a window is created, it is not deleted until the main
|
||||
application exits (i.e., if the user closes the information
|
||||
@ -192,7 +192,7 @@
|
||||
determine whether a window already exists for a given location
|
||||
when the user requests information about it.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 6
|
||||
\snippet drilldown/informationwindow.cpp 6
|
||||
|
||||
The \c revert() slot is triggered whenever the user hits the \uicontrol
|
||||
Revert button.
|
||||
@ -204,7 +204,7 @@
|
||||
slot to reset the editor widgets, repopulating all widgets with
|
||||
the current data of the model.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 7
|
||||
\snippet drilldown/informationwindow.cpp 7
|
||||
|
||||
Likewise, the \c submit() slot is triggered whenever the users
|
||||
decide to submit their changes by pressing the \uicontrol Submit button.
|
||||
@ -223,7 +223,7 @@
|
||||
file names differ, we store the new file name and emit the \c
|
||||
imageChanged() signal.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 8
|
||||
\snippet drilldown/informationwindow.cpp 8
|
||||
|
||||
The \c createButtons() function is provided for convenience, i.e.,
|
||||
to simplify the constructor.
|
||||
@ -236,7 +236,7 @@
|
||||
Submit and \uicontrol Revert buttons to the corresponding \c submit()
|
||||
and \c revert() slots.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 9
|
||||
\snippet drilldown/informationwindow.cpp 9
|
||||
|
||||
The QDialogButtonBox class is a widget that presents buttons in a
|
||||
layout that is appropriate to the current widget style. Dialogs
|
||||
@ -258,7 +258,7 @@
|
||||
the user has made wil be preserved until the user expliclity
|
||||
revert or submit them.
|
||||
|
||||
\snippet examples/sql/drilldown/informationwindow.cpp 10
|
||||
\snippet drilldown/informationwindow.cpp 10
|
||||
|
||||
The \c enableButtons() slot is called to enable the buttons
|
||||
whenever the user changes the presented data. Likewise, when the
|
||||
@ -274,9 +274,9 @@
|
||||
The \c View class represents the main application window and
|
||||
inherits QGraphicsView:
|
||||
|
||||
\snippet examples/sql/drilldown/view.h 0
|
||||
\snippet drilldown/view.h 0
|
||||
\codeline
|
||||
\snippet examples/sql/drilldown/view.h 1
|
||||
\snippet drilldown/view.h 1
|
||||
|
||||
The QGraphicsView class is part of the \l {Graphics View
|
||||
Framework} which we will use to display the images of Nokia's
|
||||
@ -293,7 +293,7 @@
|
||||
{InformationWindow}'s \c imageChanged() signal that is emitted
|
||||
whenever the user changes a location's image.
|
||||
|
||||
\snippet examples/sql/drilldown/view.h 2
|
||||
\snippet drilldown/view.h 2
|
||||
|
||||
The \c addItems() function is a convenience function provided to
|
||||
simplify the constructor. It is called only once, creating the
|
||||
@ -307,7 +307,7 @@
|
||||
latter function is in turn called from our custom \c
|
||||
mouseReleaseEvent() implementation.
|
||||
|
||||
\snippet examples/sql/drilldown/view.h 3
|
||||
\snippet drilldown/view.h 3
|
||||
|
||||
Finally we declare a QSqlRelationalTableModel pointer. As
|
||||
previously mentioned, the QSqlRelationalTableModel class provides
|
||||
@ -328,7 +328,7 @@
|
||||
names of the available image files, we only have to create a
|
||||
QSqlRelationalTableModel object for the office table:
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 0
|
||||
\snippet drilldown/view.cpp 0
|
||||
|
||||
The reason is that once we have a model with the office details,
|
||||
we can create a relation to the available image files using
|
||||
@ -344,7 +344,7 @@
|
||||
{QSqlRelationalTableModel::}{select()} function to populate our
|
||||
model.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 1
|
||||
\snippet drilldown/view.cpp 1
|
||||
|
||||
Then we create the contents of our view, i.e., the scene and its
|
||||
items. The location labels are regular QGraphicsTextItem objects,
|
||||
@ -356,7 +356,7 @@
|
||||
Finally, we set the main application widget's size constraints and
|
||||
window title.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 3
|
||||
\snippet drilldown/view.cpp 3
|
||||
|
||||
The \c addItems() function is called only once, i.e., when
|
||||
creating the main application window. For each row in the database
|
||||
@ -377,7 +377,7 @@
|
||||
events). Please see the \l{Graphics View Framework} documentation
|
||||
and the \l{Graphics View Examples} for more details.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 5
|
||||
\snippet drilldown/view.cpp 5
|
||||
|
||||
We reimplement QGraphicsView's \l
|
||||
{QGraphicsView::}{mouseReleaseEvent()} event handler to respond to
|
||||
@ -390,7 +390,7 @@
|
||||
of a given type. Note that if the event is not related to any of
|
||||
our image items, we pass it on to the base class implementation.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 6
|
||||
\snippet drilldown/view.cpp 6
|
||||
|
||||
The \c showInformation() function is given an \c ImageItem object
|
||||
as argument, and starts off by extracting the item's location
|
||||
@ -407,14 +407,14 @@
|
||||
this widget's \c updateImage() slot, before we give it a suitable
|
||||
position and add it to the list of existing windows.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 7
|
||||
\snippet drilldown/view.cpp 7
|
||||
|
||||
The \c updateImage() slot takes a location ID and the name of an
|
||||
image files as arguments. It filters out the image items, and
|
||||
updates the one that correspond to the given location ID, with the
|
||||
provided image file.
|
||||
|
||||
\snippet examples/sql/drilldown/view.cpp 8
|
||||
\snippet drilldown/view.cpp 8
|
||||
|
||||
The \c findWindow() function simply searches through the list of
|
||||
existing windows, returning a pointer to the window that matches
|
||||
@ -428,7 +428,7 @@
|
||||
image items. It inherits QGraphicsPixmapItem and reimplements its
|
||||
hover event handlers:
|
||||
|
||||
\snippet examples/sql/drilldown/imageitem.h 0
|
||||
\snippet drilldown/imageitem.h 0
|
||||
|
||||
In addition, we implement a public \c id() function to be able to
|
||||
identify the associated location and a public \c adjust() function
|
||||
@ -456,7 +456,7 @@
|
||||
constructor's arguments (the pixmap, parent and scene) on to the
|
||||
base class constructor:
|
||||
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 0
|
||||
\snippet drilldown/imageitem.cpp 0
|
||||
|
||||
Then we store the ID for future reference, and ensure that our
|
||||
item will accept hover events. Hover events are delivered when
|
||||
@ -482,9 +482,9 @@
|
||||
Finally, we call \c adjust() to ensure that the item is given the
|
||||
preferred size.
|
||||
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 1
|
||||
\snippet drilldown/imageitem.cpp 1
|
||||
\codeline
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 2
|
||||
\snippet drilldown/imageitem.cpp 2
|
||||
|
||||
Whenever the mouse cursor enters or leave the image item, the
|
||||
corresponding event handlers are triggered: We first set the time
|
||||
@ -503,7 +503,7 @@
|
||||
item stack once the animation is completed. Finally, if the time
|
||||
line is not already running, we start it.
|
||||
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 3
|
||||
\snippet drilldown/imageitem.cpp 3
|
||||
|
||||
When the time line is running, it triggers the \c setFrame() slot
|
||||
whenever the current frame changes due to the connection we
|
||||
@ -520,11 +520,11 @@
|
||||
|
||||
In the end, only the following convenience functions remain:
|
||||
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 4
|
||||
\snippet drilldown/imageitem.cpp 4
|
||||
\codeline
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 5
|
||||
\snippet drilldown/imageitem.cpp 5
|
||||
\codeline
|
||||
\snippet examples/sql/drilldown/imageitem.cpp 6
|
||||
\snippet drilldown/imageitem.cpp 6
|
||||
|
||||
The \c adjust() function defines and applies a transformation
|
||||
matrix, ensuring that our image item appears with the preferred
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/masterdetail
|
||||
\example masterdetail
|
||||
\title Master Detail Example
|
||||
|
||||
The Master Detail Example shows how to present data from different
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/querymodel
|
||||
\example querymodel
|
||||
\title Query Model Example
|
||||
|
||||
The Query Model example shows how to make customized versions of
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/relationaltablemodel
|
||||
\example relationaltablemodel
|
||||
\title Relational Table Model Example
|
||||
|
||||
The Relational Table Model example shows how to use table views with a relational
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/sqlbrowser
|
||||
\example sqlbrowser
|
||||
\title SQL Browser
|
||||
|
||||
The SQL Browser example shows how a data browser can be used to visualize
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/sqlwidgetmapper
|
||||
\example sqlwidgetmapper
|
||||
\title SQL Widget Mapper Example
|
||||
|
||||
The SQL Widget Mapper example shows how to use a map information from a
|
||||
@ -50,7 +50,7 @@
|
||||
The class provides a constructor, a slot to keep the buttons up to date,
|
||||
and a private function to set up the model:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.h Window definition
|
||||
\snippet sqlwidgetmapper/window.h Window definition
|
||||
|
||||
In addition to the QDataWidgetMapper object and the controls used to make
|
||||
up the user interface, we use a QStandardItemModel to hold our data and
|
||||
@ -67,7 +67,7 @@
|
||||
we create a SQLite database containing a "person" table with primary key,
|
||||
name, address and type fields.
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Set up the main table
|
||||
\snippet sqlwidgetmapper/window.cpp Set up the main table
|
||||
|
||||
On each row of the table, we insert default values for these fields,
|
||||
including values for the address types that correspond to the address
|
||||
@ -78,7 +78,7 @@
|
||||
We create an "addresstype" table containing the identifiers used in the
|
||||
"person" table and the corresponding strings:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Set up the address type table
|
||||
\snippet sqlwidgetmapper/window.cpp Set up the address type table
|
||||
|
||||
The "typeid" field in the "person" table is related to the contents of
|
||||
the "addresstype" table via a relation in a QSqlRelationalTableModel.
|
||||
@ -98,7 +98,7 @@
|
||||
In the first part, we set up the model used to hold the data, then we set
|
||||
up the widgets used for the user interface:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Set up widgets
|
||||
\snippet sqlwidgetmapper/window.cpp Set up widgets
|
||||
|
||||
We obtain a model for the combo box from the main model, based on the
|
||||
relation we set up for the "typeid" field. The call to the combo box's
|
||||
@ -113,7 +113,7 @@
|
||||
Next, we set up the widget mapper, relating each input widget to a field
|
||||
in the model:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Set up the mapper
|
||||
\snippet sqlwidgetmapper/window.cpp Set up the mapper
|
||||
|
||||
For the combo box, we already know the index of the field in the model
|
||||
from the \c{setupModel()} function. We use a QSqlRelationalDelegate as
|
||||
@ -127,12 +127,12 @@
|
||||
The rest of the constructor is very similar to that of the
|
||||
\l{Simple Widget Mapper Example}:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Set up connections and layouts
|
||||
\snippet sqlwidgetmapper/window.cpp Set up connections and layouts
|
||||
|
||||
We show the implementation of the \c{updateButtons()} slot for
|
||||
completeness:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/window.cpp Slot for updating the buttons
|
||||
\snippet sqlwidgetmapper/window.cpp Slot for updating the buttons
|
||||
|
||||
\omit
|
||||
\section1 Delegate Class Definition and Implementation
|
||||
@ -140,7 +140,7 @@
|
||||
The delegate we use to mediate interaction between the widget mapper and
|
||||
the input widgets is a small QItemDelegate subclass:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/delegate.h Delegate class definition
|
||||
\snippet sqlwidgetmapper/delegate.h Delegate class definition
|
||||
|
||||
This provides implementations of the two standard functions used to pass
|
||||
data between editor widgets and the model (see the \l{Delegate Classes}
|
||||
@ -153,7 +153,7 @@
|
||||
referred to by the model index supplied and processes it according to
|
||||
the presence of a \c currentIndex property in the editor widget:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/delegate.cpp setEditorData implementation
|
||||
\snippet sqlwidgetmapper/delegate.cpp setEditorData implementation
|
||||
|
||||
If, like QComboBox, the editor widget has this property, it is set using
|
||||
the value from the model. Since we are passing around QVariant values,
|
||||
@ -168,7 +168,7 @@
|
||||
process, taking the value stored in the widget's \c currentIndex property
|
||||
and storing it back in the model:
|
||||
|
||||
\snippet examples/sql/sqlwidgetmapper/delegate.cpp setModelData implementation
|
||||
\snippet sqlwidgetmapper/delegate.cpp setModelData implementation
|
||||
\endomit
|
||||
|
||||
\section1 Summary and Further Reading
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example sql/tablemodel
|
||||
\example tablemodel
|
||||
\title Table Model Example
|
||||
|
||||
The Table Model example shows how to use a specialized SQL table model with table
|
@ -26,7 +26,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example tools/customcompleter
|
||||
\example customcompleter
|
||||
\title Custom Completer Example
|
||||
|
||||
The Custom Completer example shows how to provide string-completion
|
BIN
examples/widgets/doc/images/itemviewspuzzle-example.png
Normal file
After Width: | Height: | Size: 206 KiB |
@ -46,7 +46,7 @@
|
||||
\li Les entrées/sorties
|
||||
\endlist
|
||||
|
||||
Le code source du tutoriel est distribué avec Qt dans le dossier \c examples/tutorials/addressbook
|
||||
Le code source du tutoriel est distribué avec Qt dans le dossier \c tutorials/addressbook
|
||||
|
||||
Les chapitres du tutoriel:
|
||||
|
@ -56,7 +56,7 @@
|
||||
Tutorial contents:
|
||||
|
||||
\list 1
|
||||
\li \l{widgets/tutorials/addressbook/part1}{Designing the User Interface}
|
||||
\li \l{tutorials/addressbook/part1}{Designing the User Interface}
|
||||
\li \l{tutorials/addressbook/part2}{Adding Addresses}
|
||||
\li \l{tutorials/addressbook/part3}{Navigating between Entries}
|
||||
\li \l{tutorials/addressbook/part4}{Editing and Removing Addresses}
|
||||
@ -65,7 +65,7 @@
|
||||
\li \l{tutorials/addressbook/part7}{Additional Features}
|
||||
\endlist
|
||||
|
||||
The tutorial source code is located in \c{examples/tutorials/addressbook}.
|
||||
The tutorial source code is located in \c{tutorials/addressbook}.
|
||||
|
||||
Although this little application does not look much like a
|
||||
fully-fledged modern GUI application, it uses many of the basic
|
@ -40,7 +40,7 @@
|
||||
extension. You also need a \c .desktop file that gives the window manager
|
||||
hints about the application, such as name, type and icon.
|
||||
|
||||
\quotefile examples/widgets/applicationicon/applicationicon.desktop
|
||||
\quotefile applicationicon/applicationicon.desktop
|
||||
|
||||
The \c Icon field should also contain the name of the executable. On the
|
||||
device, application icons are stored in the
|
||||
@ -52,7 +52,7 @@
|
||||
For Maemo, we need to add that the \c .desktop and icon file should be
|
||||
installed.
|
||||
|
||||
\quotefile examples/widgets/applicationicon/applicationicon.pro
|
||||
\quotefile applicationicon/applicationicon.pro
|
||||
|
||||
Currently, Qt Creator doesn't include the icon and desktop files in the
|
||||
application package for Maemo, merely the executable file is included. As a
|