├── .gitignore
├── GPL.txt
├── changelog.txt
├── examples
├── interactions
│ ├── .gitignore
│ ├── interaction-example.pro
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ └── mainwindow.ui
├── plots
│ ├── .gitignore
│ ├── balboa.jpg
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── mainwindow.ui
│ ├── plot-examples.pro
│ ├── screenshots
│ │ ├── .gitignore
│ │ └── create-thumbs.py
│ ├── solarpanels.jpg
│ └── sun.png
├── scrollbar-axis-range-control
│ ├── .gitignore
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── mainwindow.ui
│ └── scrollbar-axis-range-control.pro
└── text-document-integration
│ ├── .gitignore
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── mainwindow.ui
│ ├── qcpdocumentobject.cpp
│ ├── qcpdocumentobject.h
│ └── text-document-integration.pro
├── qcustomplot.cpp
└── qcustomplot.h
/.gitignore:
--------------------------------------------------------------------------------
1 | # common
2 | *~
3 | *.a
4 | *.core
5 | *.moc
6 | *.o
7 | *.obj
8 | *.orig
9 | *.rej
10 | *.so
11 | *_pch.h.cpp
12 | *_resource.rc
13 | *.qm
14 | .#*
15 | *.*#
16 | tags
17 | .DS_Store
18 | *.debug
19 | Makefile*
20 | *.prl
21 | *.app
22 | moc_*.cpp
23 | ui_*.h
24 | qrc_*.cpp
25 | Thumbs.db
26 | # KDE
27 | .directory
28 |
29 | # python temporary files
30 | *.pyc
31 |
32 | # nsis files...
33 | nsis/dlls/*
34 | nsis/*.exe
35 |
36 | # qtcreator generated files
37 | *.pro.user*
38 | *.qmlproject.user*
39 | *.pluginspec
40 |
41 | # xemacs temporary files
42 | *.flc
43 |
44 | # Vim temporary files
45 | .*.swp
46 |
47 | # Visual Studio generated files
48 | *.ib_pdb_index
49 | *.idb
50 | *.ilk
51 | *.pdb
52 | *.sln
53 | *.suo
54 | *.vcproj
55 | *.vcxproj*
56 | *vcproj.*.*.user
57 | *vcxproj.*.*.user
58 | *.ncb
59 | *.opensdf
60 | *.sdf
61 |
62 | # MinGW generated files
63 | *.Debug
64 | *.Release
65 |
66 | # Directories to ignore
67 | # ---------------------
68 |
69 | temp
70 | debug
71 | lib/*
72 | lib64/*
73 | release
74 | doc/html/*
75 | ipch/*
76 |
77 | .rcc
78 | .pch
79 |
80 |
--------------------------------------------------------------------------------
/GPL.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | #### Version 1.3.0 released on 27.12.14 ####
2 |
3 | Added features:
4 | - New plottable class QCPFinancial allows display of candlestick/ohlc data
5 | - New class QCPBarsGroup allows horizontal grouping of multiple QCPBars plottables
6 | - Added QCPBars feature allowing non-zero base values (see property QCPBars::setBaseValue)
7 | - Added QCPBars width type, for more flexible bar widths (see property QCPBars::setWidthType)
8 | - New QCPCurve optimization algorithm, fixes bug which caused line flicker at deep zoom into curve segment
9 | - Item positions can now have different position types and anchors for their x and y coordinates (QCPItemPosition::setTypeX/Y, setParentAnchorX/Y)
10 | - QCPGraph and QCPCurve can now display gaps in their lines, when inserting quiet NaNs as values (std::numeric_limits::quiet_NaN())
11 | - QCPAxis now supports placing the tick labels inside the axis rect, for particularly space saving plots (QCPAxis::setTickLabelSide)
12 | Added features after beta:
13 | - Made code compatible with QT_NO_CAST_FROM_ASCII, QT_NO_CAST_TO_ASCII
14 | - Added compatibility with QT_NO_KEYWORDS after sending code files through a simple reg-ex script
15 | - Added possibility to inject own QCPAxis(-subclasses) via second, optional QCPAxisRect::addAxis parameter
16 | - Added parameter to QCPItemPixmap::setScaled to specify transformation mode
17 |
18 | Bugfixes:
19 | - Fixed bug in QCPCurve rendering of very zoomed-in curves (via new optimization algorithm)
20 | - Fixed conflict with MSVC-specific keyword "interface" in text-document-integration example
21 | - Fixed QCPScatterStyle bug ignoring the specified pen in the custom scatter shape constructor
22 | - Fixed bug (possible crash) during QCustomPlot teardown, when a QCPLegend that has no parent layout (i.e. was removed from layout manually) gets deleted
23 | Bugfixes after beta:
24 | - Fixed bug of QCPColorMap/QCPColorGradient colors being off by one color sampling step (only noticeable in special cases)
25 | - Fixed bug of QCPGraph adaptive sampling on vertical key axis, causing staggered look
26 | - Fixed low (float) precision in QCPCurve optimization algorithm, by not using QVector2D anymore
27 |
28 | Other:
29 | - Qt 5.3 and Qt 5.4 compatibility
30 |
31 | #### Version 1.2.1 released on 07.04.14 ####
32 |
33 | Bugfixes:
34 | - Fixed regression which garbled date-time tick labels on axes, if setTickLabelType is ltDateTime and setNumberFormat contains the "b" option
35 |
36 | #### Version 1.2.0 released on 14.03.14 ####
37 |
38 | Added features:
39 | - Adaptive Sampling for QCPGraph greatly improves performance for high data densities (see QCPGraph::setAdaptiveSampling)
40 | - QCPColorMap plottable with QCPColorScale layout element allows plotting of 2D color maps
41 | - QCustomPlot::savePdf now has additional optional parameters pdfCreator and pdfTitle to set according PDF metadata fields
42 | - QCustomPlot::replot now allows specifying whether the widget update is immediate (repaint) or queued (update)
43 | - QCPRange operators +, -, *, / with double operand for range shifting and scaling, and ==, != for range comparison
44 | - Layers now have a visibility property (QCPLayer::setVisible)
45 | - static functions QCPAxis::opposite and QCPAxis::orientation now offer more convenience when handling axis types
46 | - added notification signals for selectability change (selectableChanged) on all objects that have a selected/selectable property
47 | - added notification signal for QCPAxis scaleType property
48 | - added notification signal QCPLayerable::layerChanged
49 |
50 | Bugfixes:
51 | - Fixed assert halt, when QCPAxis auto tick labels not disabled but nevertheless a custom non-number tick label ending in "e" given
52 | - Fixed painting glitches when QCustomPlot resized inside a QMdiArea or under certain conditions inside a QLayout
53 | - If changing QCPAxis::scaleType and thus causing range sanitizing and a range modification, rangeChanged wouldn't be emitted
54 | - Fixed documentation bug that caused indentation to be lost in code examples
55 | Bugfixes after beta:
56 | - Fixed bug that caused crash if clicked-on legend item is removed in mousePressEvent.
57 | - On some systems, font size defaults to -1, which used to cause a debug output in QCPAxisPainterPrivate::TickLabelDataQCP. Now it's checked before setting values based on the default font size.
58 | - When using multiple axes on one side, setting one to invisible didn't properly compress the freed space.
59 | - Fixed bug that allowed selection of plottables when clicking in the bottom or top margin of a QCPAxisRect (outside the inner rect)
60 |
61 | Other:
62 | - In method QCPAbstractPlottable::getKeyRange/getValueRange, renamed parameter "validRange" to "foundRange", to better reflect its meaning (and contrast it from QCPRange::validRange)
63 | - QCPAxis low-level axis painting methods exported to QCPAxisPainterPrivate
64 |
65 | #### Version 1.1.1 released on 09.12.13 ####
66 |
67 | Bugfixes:
68 | - Fixed bug causing legends blocking input events from reaching underlying axis rect even if legend is invisible
69 | - Added missing Q_PROPERTY for QCPAxis::setDateTimeSpec
70 | - Fixed behaviour of QCPAxisRect::setupFullAxesBox (now transfers more properties from bottom/left to top/right axes and sets visibility of bottom/left axes to true)
71 | - Made sure PDF export doesn't default to grayscale output on some systems
72 |
73 | Other:
74 | - Plotting hint QCP::phForceRepaint is now enabled on all systems (and not only on windows) by default
75 | - Documentation improvements
76 |
77 | #### Version 1.1.0 released on 04.11.13 ####
78 |
79 | Added features:
80 | - Added QCPRange::expand and QCPRange::expanded
81 | - Added QCPAxis::rescale to rescale axis to all associated plottables
82 | - Added QCPAxis::setDateTimeSpec/dateTimeSpec to allow axis labels either in UTC or local time
83 | - QCPAxis now additionally emits a rangeChanged signal overload that provides the old range as second parameter
84 |
85 | Bugfixes:
86 | - Fixed QCustomPlot::rescaleAxes not rescaling properly if first plottable has an empty range
87 | - QCPGraph::rescaleAxes/rescaleKeyAxis/rescaleValueAxis are no longer virtual (never were in base class, was a mistake)
88 | - Fixed bugs in QCPAxis::items and QCPAxisRect::items not properly returning associated items and potentially stalling
89 |
90 | Other:
91 | - Internal change from QWeakPointer to QPointer, thus got rid of deprecated Qt functionality
92 | - Qt5.1 and Qt5.2 (beta1) compatibility
93 | - Release packages now extract to single subdirectory and don't place multiple files in current working directory
94 |
95 | #### Version 1.0.1 released on 05.09.13 ####
96 |
97 | Bugfixes:
98 | - using define flag QCUSTOMPLOT_CHECK_DATA caused debug output when data was correct, instead of invalid (fixed QCP::isInvalidData)
99 | - documentation images are now properly shown when viewed with Qt Assistant
100 | - fixed various documentation mistakes
101 |
102 | Other:
103 | - Adapted documentation style sheet to better match Qt5 documentation
104 |
105 | #### Version 1.0.0 released on 01.08.13 ####
106 |
107 | Quick Summary:
108 | - Layout system for multiple axis rects in one plot
109 | - Multiple axes per side
110 | - Qt5 compatibility
111 | - More flexible and consistent scatter configuration with QCPScatterStyle
112 | - Various interface cleanups/refactoring
113 | - Pixmap-cached axis labels for improved replot performance
114 |
115 | Changes that break backward compatibility:
116 | - QCustomPlot::axisRect() changed meaning due to the extensive changes to how axes and axis rects are handled
117 | it now returns a pointer to a QCPAxisRect and takes an integer index as parameter.
118 | - QCPAxis constructor changed to now take QCPAxisRect* as parent
119 | - setAutoMargin, setMarginLeft/Right/Top/Bottom removed due to the axis rect changes (see QCPAxisRect::setMargins/setAutoMargins)
120 | - setAxisRect removed due to the axis rect changes
121 | - setAxisBackground(-Scaled/-ScaledMode) now moved to QCPAxisRect as setBackground(-Scaled/ScaledMode) (access via QCustomPlot::axisRects())
122 | - QCPLegend now is a QCPLayoutElement
123 | - QCPAbstractPlottable::drawLegendIcon parameter "rect" changed from QRect to QRectF
124 | - QCPAbstractLegendItem::draw second parameter removed (position/size now handled via QCPLayoutElement base class)
125 | - removed QCPLegend::setMargin/setMarginLeft/Right/Top/Bottom (now inherits the capability from QCPLayoutElement::setMargins)
126 | - removed QCPLegend::setMinimumSize (now inherits the capability from QCPLayoutElement::setMinimumSize)
127 | - removed enum QCPLegend::PositionStyle, QCPLegend::positionStyle/setPositionStyle/position/setPosition (replaced by capabilities of QCPLayoutInset)
128 | - QCPLegend transformed to work with new layout system (almost everything changed)
129 | - removed entire title interface: QCustomPlot::setTitle/setTitleFont/setTitleColor/setTitleSelected/setTitleSelectedFont/setTitleSelectedColor and
130 | the QCustomPlot::iSelectTitle interaction flag (all functionality is now given by the layout element "QCPPlotTitle" which can be added to the plot layout)
131 | - selectTest functions now take two additional parameters: bool onlySelectable and QVariant *details=0
132 | - selectTest functions now ignores visibility of objects and (if parameter onlySelectable is true) does not anymore ignore selectability of the object
133 | - moved QCustomPlot::Interaction/Interactions to QCP namespace as QCP::Interaction/Interactions
134 | - moved QCustomPlot::setupFullAxesBox() to QCPAxisRect::setupFullAxesBox. Now also accepts parameter to decide whether to connect opposite axis ranges
135 | - moved range dragging/zooming interface from QCustomPlot to QCPAxisRect (setRangeDrag, setRangeZoom, setRangeDragAxes, setRangeZoomAxes,...)
136 | - rangeDrag/Zoom is now set to Qt::Horizontal|Qt::Vertical instead of 0 by default, on the other hand, iRangeDrag/Zoom is unset in interactions by
137 | default (this makes enabling dragging/zooming easier by just adding the interaction flags)
138 | - QCPScatterStyle takes over everything related to handling scatters in all plottables
139 | - removed setScatterPen/Size on QCPGraph and QCPCurve, removed setOutlierPen/Size on QCPStatisticalBox (now handled via QCPScatterStyle)
140 | - modified setScatterStyle on QCPGraph and QCPCurve, and setOutlierStyle on QCPStatisticalBox, to take QCPScatterStyle
141 | - axis grid and subgrid are now reachable via the QCPGrid *QCPAxis::grid() method. (e.g. instead of xAxis->setGrid(true), write xAxis->grid()->setVisible(true))
142 |
143 | Added features:
144 | - Axis tick labels are now pixmap-cached, thus increasing replot performance (in usual setups by about 24%). See plotting hint phCacheLabels which is set by default
145 | - Advanced layout system, including the classes QCPLayoutElement, QCPLayout, QCPLayoutGrid, QCPLayoutInset, QCPAxisRect
146 | - QCustomPlot::axisRects() returns all the axis rects in the QCustomPlot.
147 | - QCustomPlot::plotLayout() returns the top level layout (initially a QCPLayoutGrid with one QCPAxisRect inside)
148 | - QCPAxis now may have an offset to the axis rect (setOffset)
149 | - Multiple axes per QCPAxisRect side are now supported (see QCPAxisRect::addAxis)
150 | - QCustomPlot::toPixmap renders the plot into a pixmap and returns it
151 | - When setting tick label rotation to +90 or -90 degrees on a vertical axis, the labels are now centered vertically on the tick height
152 | (This allows space saving vertical tick labels by having the text direction parallel to the axis)
153 | - Substantially increased replot performance when using very large manual tick vectors (> 10000 ticks) via QCPAxis::setTickVector
154 | - QCPAxis and QCPAxisRect now allow easy access to all plottables(), graphs() and items() that are associated with them
155 | - Added QCustomPlot::hasItem method for consistency with plottable interface, hasPlottable
156 | - Added QCPAxisRect::setMinimumMargins as replacement for hardcoded minimum axis margin (15 px) when auto margin is enabled
157 | - Added Flags type QCPAxis::AxisTypes (from QCPAxis::AxisType), used in QCPAxisRect interface
158 | - Automatic margin calculation can now be enabled/disabled on a per-side basis, see QCPAxisRect::setAutoMargins
159 | - QCPAxisRect margins of multiple axis rects can be coupled via QCPMarginGroup
160 | - Added new default layers "background" and "legend" (QCPAxisRect draws its background on the "background" layer, QCPLegend is on the "legend" layer by default)
161 | - Custom scatter style via QCP::ssCustom and respective setCustomScatter functions that take a QPainterPath
162 | - Filled scatters via QCPScatterStyle::setBrush
163 | Added features after beta:
164 | - Added QCustomPlot::toPainter method, to allow rendering with existing painter
165 | - QCPItemEllipse now provides a center anchor
166 |
167 | Bugfixes:
168 | - Fixed compile error on ARM
169 | - Wrong legend icons were displayed if using pixmaps for scatters that are smaller than the legend icon rect
170 | - Fixed clipping inaccuracy for rotated tick labels (were hidden too early, because the non-rotated bounding box was used)
171 | - Fixed bug that caused wrong clipping of axis ticks and subticks when the ticks were given manually by QCPAxis::setTickVector
172 | - Fixed Qt5 crash when dragging graph out of view (iterator out of bounds in QCPGraph::getVisibleDataBounds)
173 | - Fixed QCPItemText not scaling properly when using scaled raster export
174 | Bugfixes after beta:
175 | - Fixed bug that clipped the rightmost pixel column of tick labels when caching activated (only visible on windows for superscript exponents)
176 | - Restored compatibility to Qt4.6
177 | - Restored support for -no-RTTI compilation
178 | - Empty manual tick labels are handled more gracefully (no QPainter qDebug messages anymore)
179 | - Fixed type ambiguity in QCPLineEnding::draw causing compile error on ARM
180 | - Fixed bug of grid layouts not propagating the minimum size from their child elements to the parent layout correctly
181 | - Fixed bug of child elements (e.g. axis rects) of inset layouts not properly receiving mouse events
182 |
183 | Other:
184 | - Opened up non-amalgamated project structure to public via git repository
185 |
186 | #### Version released on 09.06.12 ####
187 |
188 | Quick Summary:
189 | - Items (arrows, text,...)
190 | - Layers (easier control over rendering order)
191 | - New antialiasing system (Each objects controls own antialiasing with setAntialiased)
192 | - Performance Improvements
193 | - improved pixel-precise drawing
194 | - easier shared library creation/usage
195 |
196 | Changes that (might) break backward compatibility:
197 | - enum QCPGraph::ScatterSymbol was moved to QCP namespace (now QCP::ScatterSymbol).
198 | This replace should fix your code: "QCPGraph::ss" -> "QCP::ss"
199 | - enum QCustomPlot::AntialiasedElement and flag QCustomPlot::AntialiasedElements was moved to QCP namespace
200 | This replace should fix your code: "QCustomPlot::ae" -> "QCP::ae"
201 | - the meaning of QCustomPlot::setAntialiasedElements has changed slightly: It is now an override to force elements to be antialiased. If you want to force
202 | elements to not be drawn antialiased, use the new setNotAntialiasedElements. If an element is mentioned in neither of those functions, it now controls
203 | its antialiasing itself via its "setAntialiased" function(s). (e.g. QCPAxis::setAntialiased(bool), QCPAbstractPlottable::setAntialiased(bool),
204 | QCPAbstractPlottable::setAntialiasedScatters(bool), etc.)
205 | - QCPAxis::setTickVector and QCPAxis::setTickVectorLabels no longer take a pointer but a const reference of the respective QVector as parameter.
206 | (handing over a pointer didn't give any noticeable performance benefits but was inconsistent with the rest of the interface)
207 | - Equally QCPAxis::tickVector and QCPAxis::tickVectorLabels don't return by pointer but by value now
208 | - QCustomPlot::savePngScaled was removed, its purpose is now included as optional parameter "scale" of savePng.
209 | - If you have derived from QCPAbstractPlottable: all selectTest functions now consistently take the argument "const QPointF &pos" which is the test point in pixel coordinates.
210 | (the argument there was "double key, double value" in plot coordinates, before).
211 | - QCPAbstractPlottable, QCPAxis and QCPLegend now inherit from QCPLayerable
212 | - If you have derived from QCPAbstractPlottable: the draw method signature has changed from "draw (..) const" to "draw (..)", i.e. the method
213 | is not const anymore. This allows the draw function of your plottable to perform buffering/caching operations, if necessary.
214 |
215 | Added features:
216 | - Item system: QCPAbstractItem, QCPItemAnchor, QCPItemPosition, QCPLineEnding. Allows placing of lines, arrows, text, pixmaps etc.
217 | - New Items: QCPItemStraightLine, QCPItemLine, QCPItemCurve, QCPItemEllipse, QCPItemRect, QCPItemPixmap, QCPItemText, QCPItemBracket, QCPItemTracer
218 | - QCustomPlot::addItem/itemCount/item/removeItem/selectedItems
219 | - signals QCustomPlot::itemClicked/itemDoubleClicked
220 | - the QCustomPlot interactions property now includes iSelectItems (for selection of QCPAbstractItem)
221 | - QCPLineEnding. Represents the different styles a line/curve can end (e.g. different arrows, circle, square, bar, etc.), see e.g. QCPItemCurve::setHead
222 | - Layer system: QCPLayerable, QCPLayer. Allows more sophisticated control over drawing order and a kind of grouping.
223 | - QCPAbstractPlottable, QCPAbstractItem, QCPAxis, QCPGrid, QCPLegend are layerables and derive from QCPLayerable
224 | - QCustomPlot::addLayer/moveLayer/removeLayer/setCurrentLayer/layer/currentLayer/layerCount
225 | - Initially there are three layers: "grid", "main", and "axes". The "main" layer is initially empty and set as current layer, so new plottables/items are put there.
226 | - QCustomPlot::viewport now makes the previously inaccessible viewport rect read-only-accessible (needed that for item-interface)
227 | - PNG export now allows transparent background by calling QCustomPlot::setColor(Qt::transparent) before savePng
228 | - QCPStatisticalBox outlier symbols may now be all scatter symbols, not only hardcoded circles.
229 | - perfect precision of scatter symbol/error bar drawing and clipping in both antialiased and non-antialiased mode, by introducing QCPPainter
230 | that works around some QPainter bugs/inconveniences. Further, more complex symbols like ssCrossSquare used to look crooked, now they look good.
231 | - new antialiasing control system: Each drawing element now has its own "setAntialiased" function to control whether it is drawn antialiased.
232 | - QCustomPlot::setAntialiasedElements and QCustomPlot::setNotAntialiasedElements can be used to override the individual settings.
233 | - Subclasses of QCPAbstractPlottable can now use the convenience functions like applyFillAntialiasingHint or applyScattersAntialiasingHint to
234 | easily make their drawing code comply with the overall antialiasing system.
235 | - QCustomPlot::setNoAntialiasingOnDrag allows greatly improved performance and responsiveness by temporarily disabling all antialiasing while
236 | the user is dragging axis ranges
237 | - QCPGraph can now show scatter symbols at data points and hide its line (see QCPGraph::setScatterStyle, setScatterSize, setScatterPixmap, setLineStyle)
238 | - Grid drawing code was sourced out from QCPAxis to QCPGrid. QCPGrid is mainly an internal class and every QCPAxis owns one. The grid interface still
239 | works through QCPAxis and hasn't changed. The separation allows the grid to be drawn on a different layer as the axes, such that e.g. a graph can
240 | be above the grid but below the axes.
241 | - QCustomPlot::hasPlottable(plottable), returns whether the QCustomPlot contains the plottable
242 | - QCustomPlot::setPlottingHint/setPlottingHints, plotting hints control details about the plotting quality/speed
243 | - export to jpg and bmp added (QCustomPlot::saveJpg/saveBmp), as well as control over compression quality for png and jpg
244 | - multi-select-modifier may now be specified with QCustomPlot::setMultiSelectModifier and is not fixed to Ctrl anymore
245 |
246 | Bugfixes:
247 | - fixed QCustomPlot ignores replot after it had size (0,0) even if size becomes valid again
248 | - on Windows, a repaint used to be delayed during dragging/zooming of a complex plot, until the drag operation was done.
249 | This was fixed, i.e. repaints are forced after a replot() call. See QCP::phForceRepaint and setPlottingHints.
250 | - when using the raster paintengine and exporting to scaled PNG, pen widths are now scaled correctly (QPainter bug workaround via QCPPainter)
251 | - PDF export now respects QCustomPlot background color (QCustomPlot::setColor), also Qt::transparent
252 | - fixed a bug on QCPBars and QCPStatisticalBox where auto-rescaling of axis would fail when all data is very small (< 1e-11)
253 | - fixed mouse event propagation bug that prevented range dragging from working on KDE (GNU/Linux)
254 | - fixed a compiler warning on 64-bit systems due to pointer cast to int instead of quintptr in a qDebug output
255 |
256 | Other:
257 | - Added support for easier shared library creation (including examples for compiling and using QCustomPlot as shared library)
258 | - QCustomPlot now has the Qt::WA_OpaquePaintEvent widget attribute (gives slightly improved performance).
259 | - QCP::aeGraphs (enum QCP::AntialiasedElement, previously QCustomPlot::aeGraphs) has been marked deprecated since version 02.02.12 and
260 | was now removed. Use QCP::aePlottables instead.
261 | - optional performance-quality-tradeoff for solid graph lines (see QCustomPlot::setPlottingHints).
262 | - marked data classes and QCPRange as Q_MOVABLE_TYPE
263 | - replaced usage of own macro FUNCNAME with Qt macro Q_FUNC_INFO
264 | - QCustomPlot now returns a minimum size hint of 50*50
265 |
266 | #### Version released on 31.03.12 ####
267 |
268 | Changes that (might) break backward compatibility:
269 | - QCPAbstractLegendItem now inherits from QObject
270 | - mousePress, mouseMove and mouseRelease signals are now emitted before and not after any QCustomPlot processing (range dragging, selecting, etc.)
271 |
272 | Added features:
273 | - Interaction system: now allows selecting of objects like plottables, axes, legend and plot title, see QCustomPlot::setInteractions documentation
274 | - Interaction system for plottables:
275 | - setSelectable, setSelected, setSelectedPen, setSelectedBrush, selectTest on QCPAbstractPlottable and all derived plottables
276 | - setSelectionTolerance on QCustomPlot
277 | - selectedPlottables and selectedGraphs on QCustomPlot (returns the list of currently selected plottables/graphs)
278 | - Interaction system for axes:
279 | - setSelectable, setSelected, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen, setSelectedLabelFont, setSelectedTickLabelFont,
280 | setSelectedLabelColor, setSelectedTickLabelColor, selectTest on QCPAxis
281 | - selectedAxes on QCustomPlot (returns a list of the axes that currently have selected parts)
282 | - Interaction system for legend:
283 | - setSelectable, setSelected, setSelectedBorderPen, setSelectedIconBorderPen, setSelectedBrush, setSelectedFont, setSelectedTextColor, selectedItems on QCPLegend
284 | - setSelectedFont, setSelectedTextColor, setSelectable, setSelected on QCPAbstractLegendItem
285 | - selectedLegends on QCustomPlot
286 | - Interaction system for title:
287 | - setSelectedTitleFont, setSelectedTitleColor, setTitleSelected on QCustomPlot
288 | - new signals in accordance with the interaction system:
289 | - selectionChangedByUser on QCustomPlot
290 | - selectionChanged on QCPAbstractPlottable
291 | - selectionChanged on QCPAxis
292 | - selectionChanged on QCPLegend and QCPAbstractLegendItem
293 | - plottableClick, legendClick, axisClick, titleClick, plottableDoubleClick, legendDoubleClick, axisDoubleClick, titleDoubleClick on QCustomPlot
294 | - QCustomPlot::deselectAll (deselects everything, i.e. axes and plottables)
295 | - QCPAbstractPlottable::pixelsToCoords (inverse function to the already existing coordsToPixels function)
296 | - QCPRange::contains(double value)
297 | - QCPAxis::setLabelColor and setTickLabelColor
298 | - QCustomPlot::setTitleColor
299 | - QCustomPlot now emits beforeReplot and afterReplot signals. Note that it is safe to make two customPlots mutually call eachothers replot functions
300 | in one of these slots, it will not cause an infinite loop. (usefull for synchronizing axes ranges between two customPlots, because setRange alone doesn't replot)
301 | - If the Qt version is 4.7 or greater, the tick label strings in date-time-mode now support sub-second accuracy (e.g. with format like "hh:mm:ss.zzz").
302 |
303 | Bugfixes:
304 | - tick labels/margins should no longer oscillate by one pixel when dragging range or replotting repeatedly while changing e.g. data. This
305 | was caused by a bug in Qt's QFontMetrics::boundingRect function when the font has an integer point size (probably some rounding problem).
306 | The fix hence consists of creating a temporary font (only for bounding-box calculation) which is 0.05pt larger and thus avoiding the
307 | jittering rounding outcome.
308 | - tick label, axis label and plot title colors used to be undefined. This was fixed by providing explicit color properties.
309 |
310 | Other:
311 | - fixed some glitches in the documentation
312 | - QCustomPlot::replot and QCustomPlot::rescaleAxes are now slots
313 |
314 | #### Version released on 02.02.12 ####
315 |
316 | Changes that break backward compatibility:
317 | - renamed all secondary classes from QCustomPlot[...] to QCP[...]:
318 | QCustomPlotAxis -> QCPAxis
319 | QCustomPlotGraph -> QCPGraph
320 | QCustomPlotRange -> QCPRange
321 | QCustomPlotData -> QCPData
322 | QCustomPlotDataMap -> QCPDataMap
323 | QCustomPlotLegend -> QCPLegend
324 | QCustomPlotDataMapIterator -> QCPDataMapIterator
325 | QCustomPlotDataMutableMapIterator -> QCPDataMutableMapIterator
326 | A simple search and replace on all code files should make your code run again, e.g. consider the regex "QCustomPlot(?=[AGRDL])" -> "QCP".
327 | Make sure not to just replace "QCustomPlot" with "QCP" because the main class QCustomPlot hasn't changed to QCP.
328 | This change was necessary because class names became unhandy, pardon my bad naming decision in the beginning.
329 | - QCPAxis::tickLength() and QCPAxis::subTickLength() now each split into two functions for inward and outward ticks (tickLengthIn/tickLengthOut).
330 | - QCPLegend now uses QCPAbstractLegendItem to carry item data (before, the legend was passed QCPGraphs directly)
331 | - QCustomPlot::addGraph() now doesn't return the index of the created graph anymore, but a pointer to the created QCPGraph.
332 | - QCustomPlot::setAutoAddGraphToLegend is replaced by setAutoAddPlottableToLegend
333 |
334 | Added features:
335 | - Reversed axis range with QCPAxis::setRangeReversed(bool)
336 | - Tick labels are now only drawn if not clipped by the viewport (widget border) on the sides (e.g. left and right on a horizontal axis).
337 | - Zerolines. Like grid lines only with a separate pen (QCPAxis::setZeroLinePen), at tick position zero.
338 | - Outward ticks. QCPAxis::setTickLength/setSubTickLength now accepts two arguments for inward and outward tick length. This doesn't break
339 | backward compatibility because the second argument (outward) has default value zero and thereby a call with one argument hasn't changed its meaning.
340 | - QCPGraph now inherits from QCPAbstractPlottable
341 | - QCustomPlot::addPlottable/plottable/removePlottable/clearPlottables added to interface with the new QCPAbstractPlottable-based system. The simpler interface
342 | which only acts on QCPGraphs (addGraph, graph, removeGraph, etc.) was adapted internally and is kept for backward compatibility and ease of use.
343 | - QCPLegend items for plottables (e.g. graphs) can automatically wrap their texts to fit the widths, see QCPLegend::setMinimumSize and QCPPlottableLegendItem::setTextWrap.
344 | - QCustomPlot::rescaleAxes. Adapts axis ranges to show all plottables/graphs, by calling QCPAbstractPlottable::rescaleAxes on all plottables in the plot.
345 | - QCPCurve. For plotting of parametric curves.
346 | - QCPBars. For plotting of bar charts.
347 | - QCPStatisticalBox. For statistical box plots.
348 |
349 | Bugfixes:
350 | - Fixed QCustomPlot::removeGraph(int) not being able to remove graph index 0
351 | - made QCustomPlot::replot() abort painting when painter initialization fails (e.g. because width/height of QCustomPlot is zero)
352 | - The distance of the axis label from the axis ignored the tick label padding, this could have caused overlapping axis labels and tick labels
353 | - fixed memory leak in QCustomPlot (dtor didn't delete legend)
354 | - fixed bug that prevented QCPAxis::setRangeLower/Upper from setting the value to exactly 0.
355 |
356 | Other:
357 | - Changed default error bar handle size (QCustomPlotGraph::setErrorBarSize) from 4 to 6.
358 | - Removed QCustomPlotDataFetcher. Was deprecated and not used class.
359 | - Extended documentation, especially class descriptions.
360 |
361 | #### Version released on 15.01.12 ####
362 |
363 | Changes that (might) break backward compatibility:
364 | - QCustomPlotGraph now inherits from QObject
365 |
366 | Added features:
367 | - Added axis background pixmap (QCustomPlot::setAxisBackground, setAxisBackgroundScaled, setAxisBackgroundScaledMode)
368 | - Added width and height parameter on PDF export function QCustomPlot::savePdf(). This now allows PDF export to
369 | have arbitrary dimensions, independent of the current geometry of the QCustomPlot.
370 | - Added overload of QCustomPlot::removeGraph that takes QCustomPlotGraph* as parameter, instead the index of the graph
371 | - Added all enums to the Qt meta system via Q_ENUMS(). The enums can now be transformed
372 | to QString values easily with the Qt meta system, which makes saving state e.g. as XML
373 | significantly nicer.
374 | - added typedef QMapIterator QCustomPlotDataMapIterator
375 | and typedef QMutableMapIterator QCustomPlotDataMutableMapIterator
376 | for improved information hiding, when using iterators outside QCustomPlot code
377 |
378 | Bugfixes:
379 | - Fixed savePngScaled. Axis/label drawing functions used to reset the painter transform
380 | and thereby break savePngScaled. Now they buffer the current transform and restore it afterwards.
381 | - Fixed some glitches in the doxygen comments (affects documentation only)
382 |
383 | Other:
384 | - Changed the default tickLabelPadding of top axis from 3 to 6 pixels. Looks better.
385 | - Changed the default QCustomPlot::setAntialiasedElements setting: Graph fills are now antialiased
386 | by default. That's a bit slower, but makes fill borders look better.
387 |
388 | #### Version released on 19.11.11 ####
389 |
390 | Changes that break backward compatibility:
391 | - QCustomPlotAxis: tickFont and setTickFont renamed to tickLabelFont and setTickLabelFont (for naming consistency)
392 |
393 | Other:
394 | - QCustomPlotAxis: Added rotated tick labels, see setTickLabelRotation
395 |
396 |
--------------------------------------------------------------------------------
/examples/interactions/.gitignore:
--------------------------------------------------------------------------------
1 | interaction-example
--------------------------------------------------------------------------------
/examples/interactions/interaction-example.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2012-03-04T23:24:55
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
9 |
10 | TARGET = interaction-example
11 | TEMPLATE = app
12 |
13 | SOURCES += main.cpp\
14 | mainwindow.cpp \
15 | ../../qcustomplot.cpp
16 |
17 | HEADERS += mainwindow.h \
18 | ../../qcustomplot.h
19 |
20 | FORMS += mainwindow.ui
21 |
22 |
--------------------------------------------------------------------------------
/examples/interactions/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "mainwindow.h"
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/examples/interactions/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "ui_mainwindow.h"
3 |
4 | MainWindow::MainWindow(QWidget *parent) :
5 | QMainWindow(parent),
6 | ui(new Ui::MainWindow)
7 | {
8 | srand(QDateTime::currentDateTime().toTime_t());
9 | ui->setupUi(this);
10 |
11 | ui->customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
12 | QCP::iSelectLegend | QCP::iSelectPlottables);
13 | ui->customPlot->xAxis->setRange(-8, 8);
14 | ui->customPlot->yAxis->setRange(-5, 5);
15 | ui->customPlot->axisRect()->setupFullAxesBox();
16 |
17 | ui->customPlot->plotLayout()->insertRow(0);
18 | ui->customPlot->plotLayout()->addElement(0, 0, new QCPPlotTitle(ui->customPlot, "Interaction Example"));
19 |
20 | ui->customPlot->xAxis->setLabel("x Axis");
21 | ui->customPlot->yAxis->setLabel("y Axis");
22 | ui->customPlot->legend->setVisible(true);
23 | QFont legendFont = font();
24 | legendFont.setPointSize(10);
25 | ui->customPlot->legend->setFont(legendFont);
26 | ui->customPlot->legend->setSelectedFont(legendFont);
27 | ui->customPlot->legend->setSelectableParts(QCPLegend::spItems); // legend box shall not be selectable, only legend items
28 |
29 | addRandomGraph();
30 | addRandomGraph();
31 | addRandomGraph();
32 | addRandomGraph();
33 |
34 | // connect slot that ties some axis selections together (especially opposite axes):
35 | connect(ui->customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
36 | // connect slots that takes care that when an axis is selected, only that direction can be dragged and zoomed:
37 | connect(ui->customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
38 | connect(ui->customPlot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
39 |
40 | // make bottom and left axes transfer their ranges to top and right axes:
41 | connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->xAxis2, SLOT(setRange(QCPRange)));
42 | connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->yAxis2, SLOT(setRange(QCPRange)));
43 |
44 | // connect some interaction slots:
45 | connect(ui->customPlot, SIGNAL(titleDoubleClick(QMouseEvent*,QCPPlotTitle*)), this, SLOT(titleDoubleClick(QMouseEvent*,QCPPlotTitle*)));
46 | connect(ui->customPlot, SIGNAL(axisDoubleClick(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)), this, SLOT(axisLabelDoubleClick(QCPAxis*,QCPAxis::SelectablePart)));
47 | connect(ui->customPlot, SIGNAL(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*,QMouseEvent*)), this, SLOT(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*)));
48 |
49 | // connect slot that shows a message in the status bar when a graph is clicked:
50 | connect(ui->customPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*)));
51 |
52 | // setup policy and connect slot for context menu popup:
53 | ui->customPlot->setContextMenuPolicy(Qt::CustomContextMenu);
54 | connect(ui->customPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
55 | }
56 |
57 | MainWindow::~MainWindow()
58 | {
59 | delete ui;
60 | }
61 |
62 | void MainWindow::titleDoubleClick(QMouseEvent* event, QCPPlotTitle* title)
63 | {
64 | Q_UNUSED(event)
65 | // Set the plot title by double clicking on it
66 | bool ok;
67 | QString newTitle = QInputDialog::getText(this, "QCustomPlot example", "New plot title:", QLineEdit::Normal, title->text(), &ok);
68 | if (ok)
69 | {
70 | title->setText(newTitle);
71 | ui->customPlot->replot();
72 | }
73 | }
74 |
75 | void MainWindow::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part)
76 | {
77 | // Set an axis label by double clicking on it
78 | if (part == QCPAxis::spAxisLabel) // only react when the actual axis label is clicked, not tick label or axis backbone
79 | {
80 | bool ok;
81 | QString newLabel = QInputDialog::getText(this, "QCustomPlot example", "New axis label:", QLineEdit::Normal, axis->label(), &ok);
82 | if (ok)
83 | {
84 | axis->setLabel(newLabel);
85 | ui->customPlot->replot();
86 | }
87 | }
88 | }
89 |
90 | void MainWindow::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item)
91 | {
92 | // Rename a graph by double clicking on its legend item
93 | Q_UNUSED(legend)
94 | if (item) // only react if item was clicked (user could have clicked on border padding of legend where there is no item, then item is 0)
95 | {
96 | QCPPlottableLegendItem *plItem = qobject_cast(item);
97 | bool ok;
98 | QString newName = QInputDialog::getText(this, "QCustomPlot example", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok);
99 | if (ok)
100 | {
101 | plItem->plottable()->setName(newName);
102 | ui->customPlot->replot();
103 | }
104 | }
105 | }
106 |
107 | void MainWindow::selectionChanged()
108 | {
109 | /*
110 | normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
111 | the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
112 | and the axis base line together. However, the axis label shall be selectable individually.
113 |
114 | The selection state of the left and right axes shall be synchronized as well as the state of the
115 | bottom and top axes.
116 |
117 | Further, we want to synchronize the selection of the graphs with the selection state of the respective
118 | legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
119 | or on its legend item.
120 | */
121 |
122 | // make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
123 | if (ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
124 | ui->customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
125 | {
126 | ui->customPlot->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
127 | ui->customPlot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
128 | }
129 | // make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
130 | if (ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
131 | ui->customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
132 | {
133 | ui->customPlot->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
134 | ui->customPlot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
135 | }
136 |
137 | // synchronize selection of graphs with selection of corresponding legend items:
138 | for (int i=0; icustomPlot->graphCount(); ++i)
139 | {
140 | QCPGraph *graph = ui->customPlot->graph(i);
141 | QCPPlottableLegendItem *item = ui->customPlot->legend->itemWithPlottable(graph);
142 | if (item->selected() || graph->selected())
143 | {
144 | item->setSelected(true);
145 | graph->setSelected(true);
146 | }
147 | }
148 | }
149 |
150 | void MainWindow::mousePress()
151 | {
152 | // if an axis is selected, only allow the direction of that axis to be dragged
153 | // if no axis is selected, both directions may be dragged
154 |
155 | if (ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
156 | ui->customPlot->axisRect()->setRangeDrag(ui->customPlot->xAxis->orientation());
157 | else if (ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
158 | ui->customPlot->axisRect()->setRangeDrag(ui->customPlot->yAxis->orientation());
159 | else
160 | ui->customPlot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
161 | }
162 |
163 | void MainWindow::mouseWheel()
164 | {
165 | // if an axis is selected, only allow the direction of that axis to be zoomed
166 | // if no axis is selected, both directions may be zoomed
167 |
168 | if (ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
169 | ui->customPlot->axisRect()->setRangeZoom(ui->customPlot->xAxis->orientation());
170 | else if (ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
171 | ui->customPlot->axisRect()->setRangeZoom(ui->customPlot->yAxis->orientation());
172 | else
173 | ui->customPlot->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);
174 | }
175 |
176 | void MainWindow::addRandomGraph()
177 | {
178 | int n = 50; // number of points in graph
179 | double xScale = (rand()/(double)RAND_MAX + 0.5)*2;
180 | double yScale = (rand()/(double)RAND_MAX + 0.5)*2;
181 | double xOffset = (rand()/(double)RAND_MAX - 0.5)*4;
182 | double yOffset = (rand()/(double)RAND_MAX - 0.5)*5;
183 | double r1 = (rand()/(double)RAND_MAX - 0.5)*2;
184 | double r2 = (rand()/(double)RAND_MAX - 0.5)*2;
185 | double r3 = (rand()/(double)RAND_MAX - 0.5)*2;
186 | double r4 = (rand()/(double)RAND_MAX - 0.5)*2;
187 | QVector x(n), y(n);
188 | for (int i=0; icustomPlot->addGraph();
195 | ui->customPlot->graph()->setName(QString("New graph %1").arg(ui->customPlot->graphCount()-1));
196 | ui->customPlot->graph()->setData(x, y);
197 | ui->customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(rand()%5+1));
198 | if (rand()%100 > 75)
199 | ui->customPlot->graph()->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)(rand()%9+1)));
200 | QPen graphPen;
201 | graphPen.setColor(QColor(rand()%245+10, rand()%245+10, rand()%245+10));
202 | graphPen.setWidthF(rand()/(double)RAND_MAX*2+1);
203 | ui->customPlot->graph()->setPen(graphPen);
204 | ui->customPlot->replot();
205 | }
206 |
207 | void MainWindow::removeSelectedGraph()
208 | {
209 | if (ui->customPlot->selectedGraphs().size() > 0)
210 | {
211 | ui->customPlot->removeGraph(ui->customPlot->selectedGraphs().first());
212 | ui->customPlot->replot();
213 | }
214 | }
215 |
216 | void MainWindow::removeAllGraphs()
217 | {
218 | ui->customPlot->clearGraphs();
219 | ui->customPlot->replot();
220 | }
221 |
222 | void MainWindow::contextMenuRequest(QPoint pos)
223 | {
224 | QMenu *menu = new QMenu(this);
225 | menu->setAttribute(Qt::WA_DeleteOnClose);
226 |
227 | if (ui->customPlot->legend->selectTest(pos, false) >= 0) // context menu on legend requested
228 | {
229 | menu->addAction("Move to top left", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignLeft));
230 | menu->addAction("Move to top center", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignHCenter));
231 | menu->addAction("Move to top right", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignRight));
232 | menu->addAction("Move to bottom right", this, SLOT(moveLegend()))->setData((int)(Qt::AlignBottom|Qt::AlignRight));
233 | menu->addAction("Move to bottom left", this, SLOT(moveLegend()))->setData((int)(Qt::AlignBottom|Qt::AlignLeft));
234 | } else // general context menu on graphs requested
235 | {
236 | menu->addAction("Add random graph", this, SLOT(addRandomGraph()));
237 | if (ui->customPlot->selectedGraphs().size() > 0)
238 | menu->addAction("Remove selected graph", this, SLOT(removeSelectedGraph()));
239 | if (ui->customPlot->graphCount() > 0)
240 | menu->addAction("Remove all graphs", this, SLOT(removeAllGraphs()));
241 | }
242 |
243 | menu->popup(ui->customPlot->mapToGlobal(pos));
244 | }
245 |
246 | void MainWindow::moveLegend()
247 | {
248 | if (QAction* contextAction = qobject_cast(sender())) // make sure this slot is really called by a context menu action, so it carries the data we need
249 | {
250 | bool ok;
251 | int dataInt = contextAction->data().toInt(&ok);
252 | if (ok)
253 | {
254 | ui->customPlot->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
255 | ui->customPlot->replot();
256 | }
257 | }
258 | }
259 |
260 | void MainWindow::graphClicked(QCPAbstractPlottable *plottable)
261 | {
262 | ui->statusBar->showMessage(QString("Clicked on graph '%1'.").arg(plottable->name()), 1000);
263 | }
264 |
265 |
266 |
267 |
268 |
--------------------------------------------------------------------------------
/examples/interactions/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 | #include "../../qcustomplot.h"
7 |
8 | namespace Ui {
9 | class MainWindow;
10 | }
11 |
12 | class MainWindow : public QMainWindow
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit MainWindow(QWidget *parent = 0);
18 | ~MainWindow();
19 |
20 | private slots:
21 | void titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title);
22 | void axisLabelDoubleClick(QCPAxis* axis, QCPAxis::SelectablePart part);
23 | void legendDoubleClick(QCPLegend* legend, QCPAbstractLegendItem* item);
24 | void selectionChanged();
25 | void mousePress();
26 | void mouseWheel();
27 | void addRandomGraph();
28 | void removeSelectedGraph();
29 | void removeAllGraphs();
30 | void contextMenuRequest(QPoint pos);
31 | void moveLegend();
32 | void graphClicked(QCPAbstractPlottable *plottable);
33 |
34 | private:
35 | Ui::MainWindow *ui;
36 | };
37 |
38 | #endif // MAINWINDOW_H
39 |
--------------------------------------------------------------------------------
/examples/interactions/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 621
10 | 515
11 |
12 |
13 |
14 | QCustomPlot Interaction Example
15 |
16 |
17 |
18 | -
19 |
20 |
21 | QFrame::StyledPanel
22 |
23 |
24 | QFrame::Sunken
25 |
26 |
27 | 1
28 |
29 |
30 | 0
31 |
32 |
33 |
34 | 0
35 |
36 |
37 | 0
38 |
39 |
-
40 |
41 |
42 |
43 | 0
44 | 0
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | -
53 |
54 |
55 | QFrame::StyledPanel
56 |
57 |
58 | QFrame::Raised
59 |
60 |
61 |
-
62 |
63 |
64 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
65 | <html><head><meta name="qrichtext" content="1" /><style type="text/css">
66 | p, li { white-space: pre-wrap; }
67 | </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
68 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Select the axes</span> to drag and zoom them individually.</p>
69 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Double click labels</span> or legend items to set user specified strings.</p>
70 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Left click</span> on graphs or legend to select graphs.</p>
71 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Right click</span> for a popup menu to add/remove graphs and move the legend</p></body></html>
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
90 |
91 |
92 |
93 |
94 |
95 | QCustomPlot
96 | QWidget
97 |
98 | 1
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/examples/plots/.gitignore:
--------------------------------------------------------------------------------
1 | plot-examples
2 |
--------------------------------------------------------------------------------
/examples/plots/balboa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbzhang800/QCustomPlot/d1d69480e3f7af8959ecd3d3b3c8bbfffc7b1292/examples/plots/balboa.jpg
--------------------------------------------------------------------------------
/examples/plots/main.cpp:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #include
27 | #include "mainwindow.h"
28 |
29 | int main(int argc, char *argv[])
30 | {
31 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
32 | QApplication::setGraphicsSystem("raster");
33 | #endif
34 | QApplication a(argc, argv);
35 | MainWindow w;
36 | w.show();
37 |
38 | return a.exec();
39 | }
40 |
--------------------------------------------------------------------------------
/examples/plots/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | /************************************************************************************************************
27 | ** **
28 | ** This is the example code for QCustomPlot. **
29 | ** **
30 | ** It demonstrates basic and some advanced capabilities of the widget. The interesting code is inside **
31 | ** the "setup(...)Demo" functions of MainWindow. **
32 | ** **
33 | ** In order to see a demo in action, call the respective "setup(...)Demo" function inside the **
34 | ** MainWindow constructor. Alternatively you may call setupDemo(i) where i is the index of the demo **
35 | ** you want (for those, see MainWindow constructor comments). All other functions here are merely a **
36 | ** way to easily create screenshots of all demos for the website. I.e. a timer is set to successively **
37 | ** setup all the demos and make a screenshot of the window area and save it in the ./screenshots **
38 | ** directory. **
39 | ** **
40 | *************************************************************************************************************/
41 |
42 | #include "mainwindow.h"
43 | #include "ui_mainwindow.h"
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 |
50 | MainWindow::MainWindow(QWidget *parent) :
51 | QMainWindow(parent),
52 | ui(new Ui::MainWindow)
53 | {
54 | ui->setupUi(this);
55 | setGeometry(400, 250, 542, 390);
56 |
57 | setupDemo(0);
58 | //setupPlayground(ui->customPlot);
59 | // 0: setupQuadraticDemo(ui->customPlot);
60 | // 1: setupSimpleDemo(ui->customPlot);
61 | // 2: setupSincScatterDemo(ui->customPlot);
62 | // 3: setupScatterStyleDemo(ui->customPlot);
63 | // 4: setupScatterPixmapDemo(ui->customPlot);
64 | // 5: setupLineStyleDemo(ui->customPlot);
65 | // 6: setupDateDemo(ui->customPlot);
66 | // 7: setupTextureBrushDemo(ui->customPlot);
67 | // 8: setupMultiAxisDemo(ui->customPlot);
68 | // 9: setupLogarithmicDemo(ui->customPlot);
69 | // 10: setupRealtimeDataDemo(ui->customPlot);
70 | // 11: setupParametricCurveDemo(ui->customPlot);
71 | // 12: setupBarChartDemo(ui->customPlot);
72 | // 13: setupStatisticalDemo(ui->customPlot);
73 | // 14: setupSimpleItemDemo(ui->customPlot);
74 | // 15: setupItemDemo(ui->customPlot);
75 | // 16: setupStyledDemo(ui->customPlot);
76 | // 17: setupAdvancedAxesDemo(ui->customPlot);
77 | // 18: setupColorMapDemo(ui->customPlot);
78 | // 19: setupFinancialDemo(ui->customPlot);
79 |
80 | // for making screenshots of the current demo or all demos (for website screenshots):
81 | //QTimer::singleShot(1500, this, SLOT(allScreenShots()));
82 | //QTimer::singleShot(4000, this, SLOT(screenShot()));
83 | }
84 |
85 | void MainWindow::setupDemo(int demoIndex)
86 | {
87 | switch (demoIndex)
88 | {
89 | case 0: setupQuadraticDemo(ui->customPlot); break;
90 | case 1: setupSimpleDemo(ui->customPlot); break;
91 | case 2: setupSincScatterDemo(ui->customPlot); break;
92 | case 3: setupScatterStyleDemo(ui->customPlot); break;
93 | case 4: setupScatterPixmapDemo(ui->customPlot); break;
94 | case 5: setupLineStyleDemo(ui->customPlot); break;
95 | case 6: setupDateDemo(ui->customPlot); break;
96 | case 7: setupTextureBrushDemo(ui->customPlot); break;
97 | case 8: setupMultiAxisDemo(ui->customPlot); break;
98 | case 9: setupLogarithmicDemo(ui->customPlot); break;
99 | case 10: setupRealtimeDataDemo(ui->customPlot); break;
100 | case 11: setupParametricCurveDemo(ui->customPlot); break;
101 | case 12: setupBarChartDemo(ui->customPlot); break;
102 | case 13: setupStatisticalDemo(ui->customPlot); break;
103 | case 14: setupSimpleItemDemo(ui->customPlot); break;
104 | case 15: setupItemDemo(ui->customPlot); break;
105 | case 16: setupStyledDemo(ui->customPlot); break;
106 | case 17: setupAdvancedAxesDemo(ui->customPlot); break;
107 | case 18: setupColorMapDemo(ui->customPlot); break;
108 | case 19: setupFinancialDemo(ui->customPlot); break;
109 | }
110 | setWindowTitle("QCustomPlot: "+demoName);
111 | statusBar()->clearMessage();
112 | currentDemoIndex = demoIndex;
113 | ui->customPlot->replot();
114 | }
115 |
116 | void MainWindow::setupQuadraticDemo(QCustomPlot *customPlot)
117 | {
118 | demoName = "Quadratic Demo";
119 | // generate some data:
120 | QVector x(101), y(101); // initialize with entries 0..100
121 | for (int i=0; i<101; ++i)
122 | {
123 | x[i] = i/50.0 - 1; // x goes from -1 to 1
124 | y[i] = x[i]*x[i]; // let's plot a quadratic function
125 | }
126 | // create graph and assign data to it:
127 | customPlot->addGraph();
128 | customPlot->graph(0)->setData(x, y);
129 | // give the axes some labels:
130 | customPlot->xAxis->setLabel("x");
131 | customPlot->yAxis->setLabel("y");
132 | // set axes ranges, so we see all data:
133 | customPlot->xAxis->setRange(-1, 1);
134 | customPlot->yAxis->setRange(0, 1);
135 | }
136 |
137 | void MainWindow::setupSimpleDemo(QCustomPlot *customPlot)
138 | {
139 | demoName = "Simple Demo";
140 |
141 | // add two new graphs and set their look:
142 | customPlot->addGraph();
143 | customPlot->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph
144 | customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
145 | customPlot->addGraph();
146 | customPlot->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph
147 | // generate some points of data (y0 for first, y1 for second graph):
148 | QVector x(250), y0(250), y1(250);
149 | for (int i=0; i<250; ++i)
150 | {
151 | x[i] = i;
152 | y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosine
153 | y1[i] = qExp(-i/150.0); // exponential envelope
154 | }
155 | // configure right and top axis to show ticks but no labels:
156 | // (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
157 | customPlot->xAxis2->setVisible(true);
158 | customPlot->xAxis2->setTickLabels(false);
159 | customPlot->yAxis2->setVisible(true);
160 | customPlot->yAxis2->setTickLabels(false);
161 | // make left and bottom axes always transfer their ranges to right and top axes:
162 | connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
163 | connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
164 | // pass data points to graphs:
165 | customPlot->graph(0)->setData(x, y0);
166 | customPlot->graph(1)->setData(x, y1);
167 | // let the ranges scale themselves so graph 0 fits perfectly in the visible area:
168 | customPlot->graph(0)->rescaleAxes();
169 | // same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
170 | customPlot->graph(1)->rescaleAxes(true);
171 | // Note: we could have also just called customPlot->rescaleAxes(); instead
172 | // Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
173 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
174 | }
175 |
176 | void MainWindow::setupSincScatterDemo(QCustomPlot *customPlot)
177 | {
178 | demoName = "Sinc Scatter Demo";
179 | customPlot->legend->setVisible(true);
180 | customPlot->legend->setFont(QFont("Helvetica",9));
181 | // set locale to english, so we get english decimal separator:
182 | customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));
183 | // add confidence band graphs:
184 | customPlot->addGraph();
185 | QPen pen;
186 | pen.setStyle(Qt::DotLine);
187 | pen.setWidth(1);
188 | pen.setColor(QColor(180,180,180));
189 | customPlot->graph(0)->setName("Confidence Band 68%");
190 | customPlot->graph(0)->setPen(pen);
191 | customPlot->graph(0)->setBrush(QBrush(QColor(255,50,30,20)));
192 | customPlot->addGraph();
193 | customPlot->legend->removeItem(customPlot->legend->itemCount()-1); // don't show two confidence band graphs in legend
194 | customPlot->graph(1)->setPen(pen);
195 | customPlot->graph(0)->setChannelFillGraph(customPlot->graph(1));
196 | // add theory curve graph:
197 | customPlot->addGraph();
198 | pen.setStyle(Qt::DashLine);
199 | pen.setWidth(2);
200 | pen.setColor(Qt::red);
201 | customPlot->graph(2)->setPen(pen);
202 | customPlot->graph(2)->setName("Theory Curve");
203 | // add data point graph:
204 | customPlot->addGraph();
205 | customPlot->graph(3)->setPen(QPen(Qt::blue));
206 | customPlot->graph(3)->setLineStyle(QCPGraph::lsNone);
207 | customPlot->graph(3)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCross, 4));
208 | customPlot->graph(3)->setErrorType(QCPGraph::etValue);
209 | customPlot->graph(3)->setErrorPen(QPen(QColor(180,180,180)));
210 | customPlot->graph(3)->setName("Measurement");
211 |
212 | // generate ideal sinc curve data and some randomly perturbed data for scatter plot:
213 | QVector x0(250), y0(250);
214 | QVector yConfUpper(250), yConfLower(250);
215 | for (int i=0; i<250; ++i)
216 | {
217 | x0[i] = (i/249.0-0.5)*30+0.01; // by adding a small offset we make sure not do divide by zero in next code line
218 | y0[i] = qSin(x0[i])/x0[i]; // sinc function
219 | yConfUpper[i] = y0[i]+0.15;
220 | yConfLower[i] = y0[i]-0.15;
221 | x0[i] *= 1000;
222 | }
223 | QVector x1(50), y1(50), y1err(50);
224 | for (int i=0; i<50; ++i)
225 | {
226 | // generate a gaussian distributed random number:
227 | double tmp1 = rand()/(double)RAND_MAX;
228 | double tmp2 = rand()/(double)RAND_MAX;
229 | double r = qSqrt(-2*qLn(tmp1))*qCos(2*M_PI*tmp2); // box-muller transform for gaussian distribution
230 | // set y1 to value of y0 plus a random gaussian pertubation:
231 | x1[i] = (i/50.0-0.5)*30+0.25;
232 | y1[i] = qSin(x1[i])/x1[i]+r*0.15;
233 | x1[i] *= 1000;
234 | y1err[i] = 0.15;
235 | }
236 | // pass data to graphs and let QCustomPlot determine the axes ranges so the whole thing is visible:
237 | customPlot->graph(0)->setData(x0, yConfUpper);
238 | customPlot->graph(1)->setData(x0, yConfLower);
239 | customPlot->graph(2)->setData(x0, y0);
240 | customPlot->graph(3)->setDataValueError(x1, y1, y1err);
241 | customPlot->graph(2)->rescaleAxes();
242 | customPlot->graph(3)->rescaleAxes(true);
243 | // setup look of bottom tick labels:
244 | customPlot->xAxis->setTickLabelRotation(30);
245 | customPlot->xAxis->setAutoTickCount(9);
246 | customPlot->xAxis->setNumberFormat("ebc");
247 | customPlot->xAxis->setNumberPrecision(1);
248 | customPlot->xAxis->moveRange(-10);
249 | // make top right axes clones of bottom left axes. Looks prettier:
250 | customPlot->axisRect()->setupFullAxesBox();
251 | }
252 |
253 | void MainWindow::setupScatterStyleDemo(QCustomPlot *customPlot)
254 | {
255 | demoName = "Scatter Style Demo";
256 | customPlot->legend->setVisible(true);
257 | customPlot->legend->setFont(QFont("Helvetica", 9));
258 | customPlot->legend->setRowSpacing(-3);
259 | QVector shapes;
260 | shapes << QCPScatterStyle::ssCross;
261 | shapes << QCPScatterStyle::ssPlus;
262 | shapes << QCPScatterStyle::ssCircle;
263 | shapes << QCPScatterStyle::ssDisc;
264 | shapes << QCPScatterStyle::ssSquare;
265 | shapes << QCPScatterStyle::ssDiamond;
266 | shapes << QCPScatterStyle::ssStar;
267 | shapes << QCPScatterStyle::ssTriangle;
268 | shapes << QCPScatterStyle::ssTriangleInverted;
269 | shapes << QCPScatterStyle::ssCrossSquare;
270 | shapes << QCPScatterStyle::ssPlusSquare;
271 | shapes << QCPScatterStyle::ssCrossCircle;
272 | shapes << QCPScatterStyle::ssPlusCircle;
273 | shapes << QCPScatterStyle::ssPeace;
274 | shapes << QCPScatterStyle::ssCustom;
275 |
276 | QPen pen;
277 | // add graphs with different scatter styles:
278 | for (int i=0; iaddGraph();
281 | pen.setColor(QColor(qSin(i*0.3)*100+100, qSin(i*0.6+0.7)*100+100, qSin(i*0.4+0.6)*100+100));
282 | // generate data:
283 | QVector x(10), y(10);
284 | for (int k=0; k<10; ++k)
285 | {
286 | x[k] = k/10.0 * 4*3.14 + 0.01;
287 | y[k] = 7*qSin(x[k])/x[k] + (shapes.size()-i)*5;
288 | }
289 | customPlot->graph()->setData(x, y);
290 | customPlot->graph()->rescaleAxes(true);
291 | customPlot->graph()->setPen(pen);
292 | customPlot->graph()->setName(QCPScatterStyle::staticMetaObject.enumerator(QCPScatterStyle::staticMetaObject.indexOfEnumerator("ScatterShape")).valueToKey(shapes.at(i)));
293 | customPlot->graph()->setLineStyle(QCPGraph::lsLine);
294 | // set scatter style:
295 | if (shapes.at(i) != QCPScatterStyle::ssCustom)
296 | {
297 | customPlot->graph()->setScatterStyle(QCPScatterStyle(shapes.at(i), 10));
298 | }
299 | else
300 | {
301 | QPainterPath customScatterPath;
302 | for (int i=0; i<3; ++i)
303 | customScatterPath.cubicTo(qCos(2*M_PI*i/3.0)*9, qSin(2*M_PI*i/3.0)*9, qCos(2*M_PI*(i+0.9)/3.0)*9, qSin(2*M_PI*(i+0.9)/3.0)*9, 0, 0);
304 | customPlot->graph()->setScatterStyle(QCPScatterStyle(customScatterPath, QPen(Qt::black, 0), QColor(40, 70, 255, 50), 10));
305 | }
306 | }
307 | // set blank axis lines:
308 | customPlot->rescaleAxes();
309 | customPlot->xAxis->setTicks(false);
310 | customPlot->yAxis->setTicks(false);
311 | customPlot->xAxis->setTickLabels(false);
312 | customPlot->yAxis->setTickLabels(false);
313 | // make top right axes clones of bottom left axes:
314 | customPlot->axisRect()->setupFullAxesBox();
315 | }
316 |
317 | void MainWindow::setupLineStyleDemo(QCustomPlot *customPlot)
318 | {
319 | demoName = "Line Style Demo";
320 | customPlot->legend->setVisible(true);
321 | customPlot->legend->setFont(QFont("Helvetica", 9));
322 | QPen pen;
323 | QStringList lineNames;
324 | lineNames << "lsNone" << "lsLine" << "lsStepLeft" << "lsStepRight"
325 | << "lsStepCenter" << "lsImpulse";
326 | // add graphs with different line styles:
327 | for (int i=QCPGraph::lsNone; i<=QCPGraph::lsImpulse; ++i)
328 | {
329 | customPlot->addGraph();
330 | pen.setColor(QColor(qSin(i*1+1.2)*80+80, qSin(i*0.3+0)*80+80, qSin(i*0.3+1.5)*80+80));
331 | customPlot->graph()->setPen(pen);
332 | customPlot->graph()->setName(lineNames.at(i-QCPGraph::lsNone));
333 | customPlot->graph()->setLineStyle((QCPGraph::LineStyle)i);
334 | customPlot->graph()->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
335 | // generate data:
336 | QVector x(15), y(15);
337 | for (int j=0; j<15; ++j)
338 | {
339 | x[j] = j/15.0 * 5*3.14 + 0.01;
340 | y[j] = 7*qSin(x[j])/x[j] - (i-QCPGraph::lsNone)*5 + (QCPGraph::lsImpulse)*5 + 2;
341 | }
342 | customPlot->graph()->setData(x, y);
343 | customPlot->graph()->rescaleAxes(true);
344 | }
345 | // zoom out a bit:
346 | customPlot->yAxis->scaleRange(1.1, customPlot->yAxis->range().center());
347 | customPlot->xAxis->scaleRange(1.1, customPlot->xAxis->range().center());
348 | // set blank axis lines:
349 | customPlot->xAxis->setTicks(false);
350 | customPlot->yAxis->setTicks(true);
351 | customPlot->xAxis->setTickLabels(false);
352 | customPlot->yAxis->setTickLabels(true);
353 | // make top right axes clones of bottom left axes:
354 | customPlot->axisRect()->setupFullAxesBox();
355 | }
356 |
357 | void MainWindow::setupScatterPixmapDemo(QCustomPlot *customPlot)
358 | {
359 | demoName = "Scatter Pixmap Demo";
360 | customPlot->axisRect()->setBackground(QPixmap("./solarpanels.jpg"));
361 | customPlot->addGraph();
362 | customPlot->graph()->setLineStyle(QCPGraph::lsLine);
363 | QPen pen;
364 | pen.setColor(QColor(255, 200, 20, 200));
365 | pen.setStyle(Qt::DashLine);
366 | pen.setWidthF(2.5);
367 | customPlot->graph()->setPen(pen);
368 | customPlot->graph()->setBrush(QBrush(QColor(255,200,20,70)));
369 | customPlot->graph()->setScatterStyle(QCPScatterStyle(QPixmap("./sun.png")));
370 | // set graph name, will show up in legend next to icon:
371 | customPlot->graph()->setName("Data from Photovoltaic\nenergy barometer 2011");
372 | // set data:
373 | QVector year, value;
374 | year << 2005 << 2006 << 2007 << 2008 << 2009 << 2010;
375 | value << 2.17 << 3.42 << 4.94 << 10.38 << 15.86 << 29.33;
376 | customPlot->graph()->setData(year, value);
377 |
378 | // set title of plot:
379 | customPlot->plotLayout()->insertRow(0);
380 | customPlot->plotLayout()->addElement(0, 0, new QCPPlotTitle(customPlot, "Regenerative Energies"));
381 | // set a fixed tick-step to one tick per year value:
382 | customPlot->xAxis->setAutoTickStep(false);
383 | customPlot->xAxis->setTickStep(1);
384 | customPlot->xAxis->setSubTickCount(3);
385 | // other axis configurations:
386 | customPlot->xAxis->setLabel("Year");
387 | customPlot->yAxis->setLabel("Installed Gigawatts of\nphotovoltaic in the European Union");
388 | customPlot->xAxis2->setVisible(true);
389 | customPlot->yAxis2->setVisible(true);
390 | customPlot->xAxis2->setTickLabels(false);
391 | customPlot->yAxis2->setTickLabels(false);
392 | customPlot->xAxis2->setTicks(false);
393 | customPlot->yAxis2->setTicks(false);
394 | customPlot->xAxis2->setSubTickCount(0);
395 | customPlot->yAxis2->setSubTickCount(0);
396 | customPlot->xAxis->setRange(2004.5, 2010.5);
397 | customPlot->yAxis->setRange(0, 30);
398 | // setup legend:
399 | customPlot->legend->setFont(QFont(font().family(), 7));
400 | customPlot->legend->setIconSize(50, 20);
401 | customPlot->legend->setVisible(true);
402 | }
403 |
404 | void MainWindow::setupDateDemo(QCustomPlot *customPlot)
405 | {
406 | demoName = "Date Demo";
407 | // set locale to english, so we get english month names:
408 | customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));
409 | // seconds of current time, we'll use it as starting point in time for data:
410 | double now = QDateTime::currentDateTime().toTime_t();
411 | srand(8); // set the random seed, so we always get the same random data
412 | // create multiple graphs:
413 | for (int gi=0; gi<5; ++gi)
414 | {
415 | customPlot->addGraph();
416 | QPen pen;
417 | pen.setColor(QColor(0, 0, 255, 200));
418 | customPlot->graph()->setLineStyle(QCPGraph::lsLine);
419 | customPlot->graph()->setPen(pen);
420 | customPlot->graph()->setBrush(QBrush(QColor(255/4.0*gi,160,50,150)));
421 | // generate random walk data:
422 | QVector time(250), value(250);
423 | for (int i=0; i<250; ++i)
424 | {
425 | time[i] = now + 24*3600*i;
426 | if (i == 0)
427 | value[i] = (i/50.0+1)*(rand()/(double)RAND_MAX-0.5);
428 | else
429 | value[i] = qFabs(value[i-1])*(1+0.02/4.0*(4-gi)) + (i/50.0+1)*(rand()/(double)RAND_MAX-0.5);
430 | }
431 | customPlot->graph()->setData(time, value);
432 | }
433 | // configure bottom axis to show date and time instead of number:
434 | customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
435 | customPlot->xAxis->setDateTimeFormat("MMMM\nyyyy");
436 | // set a more compact font size for bottom and left axis tick labels:
437 | customPlot->xAxis->setTickLabelFont(QFont(QFont().family(), 8));
438 | customPlot->yAxis->setTickLabelFont(QFont(QFont().family(), 8));
439 | // set a fixed tick-step to one tick per month:
440 | customPlot->xAxis->setAutoTickStep(false);
441 | customPlot->xAxis->setTickStep(2628000); // one month in seconds
442 | customPlot->xAxis->setSubTickCount(3);
443 | // apply manual tick and tick label for left axis:
444 | customPlot->yAxis->setAutoTicks(false);
445 | customPlot->yAxis->setAutoTickLabels(false);
446 | customPlot->yAxis->setTickVector(QVector() << 5 << 55);
447 | customPlot->yAxis->setTickVectorLabels(QVector() << "Not so\nhigh" << "Very\nhigh");
448 | // set axis labels:
449 | customPlot->xAxis->setLabel("Date");
450 | customPlot->yAxis->setLabel("Random wobbly lines value");
451 | // make top and right axes visible but without ticks and labels:
452 | customPlot->xAxis2->setVisible(true);
453 | customPlot->yAxis2->setVisible(true);
454 | customPlot->xAxis2->setTicks(false);
455 | customPlot->yAxis2->setTicks(false);
456 | customPlot->xAxis2->setTickLabels(false);
457 | customPlot->yAxis2->setTickLabels(false);
458 | // set axis ranges to show all data:
459 | customPlot->xAxis->setRange(now, now+24*3600*249);
460 | customPlot->yAxis->setRange(0, 60);
461 | // show legend:
462 | customPlot->legend->setVisible(true);
463 | }
464 |
465 | void MainWindow::setupTextureBrushDemo(QCustomPlot *customPlot)
466 | {
467 | demoName = "Texture Brush Demo";
468 | // add two graphs with a textured fill:
469 | customPlot->addGraph();
470 | QPen redDotPen;
471 | redDotPen.setStyle(Qt::DotLine);
472 | redDotPen.setColor(QColor(170, 100, 100, 180));
473 | redDotPen.setWidthF(2);
474 | customPlot->graph(0)->setPen(redDotPen);
475 | customPlot->graph(0)->setBrush(QBrush(QPixmap("./balboa.jpg"))); // fill with texture of specified image
476 |
477 | customPlot->addGraph();
478 | customPlot->graph(1)->setPen(QPen(Qt::red));
479 |
480 | // activate channel fill for graph 0 towards graph 1:
481 | customPlot->graph(0)->setChannelFillGraph(customPlot->graph(1));
482 |
483 | // generate data:
484 | QVector x(250);
485 | QVector y0(250), y1(250);
486 | for (int i=0; i<250; ++i)
487 | {
488 | // just playing with numbers, not much to learn here
489 | x[i] = 3*i/250.0;
490 | y0[i] = 1+qExp(-x[i]*x[i]*0.8)*(x[i]*x[i]+x[i]);
491 | y1[i] = 1-qExp(-x[i]*x[i]*0.4)*(x[i]*x[i])*0.1;
492 | }
493 |
494 | // pass data points to graphs:
495 | customPlot->graph(0)->setData(x, y0);
496 | customPlot->graph(1)->setData(x, y1);
497 | // activate top and right axes, which are invisible by default:
498 | customPlot->xAxis2->setVisible(true);
499 | customPlot->yAxis2->setVisible(true);
500 | // make tick labels invisible on top and right axis:
501 | customPlot->xAxis2->setTickLabels(false);
502 | customPlot->yAxis2->setTickLabels(false);
503 | // set ranges:
504 | customPlot->xAxis->setRange(0, 2.5);
505 | customPlot->yAxis->setRange(0.9, 1.6);
506 | // assign top/right axes same properties as bottom/left:
507 | customPlot->axisRect()->setupFullAxesBox();
508 | }
509 |
510 | void MainWindow::setupMultiAxisDemo(QCustomPlot *customPlot)
511 | {
512 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
513 | demoName = "Multi Axis Demo";
514 |
515 | customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom)); // period as decimal separator and comma as thousand separator
516 | customPlot->legend->setVisible(true);
517 | QFont legendFont = font(); // start out with MainWindow's font..
518 | legendFont.setPointSize(9); // and make a bit smaller for legend
519 | customPlot->legend->setFont(legendFont);
520 | customPlot->legend->setBrush(QBrush(QColor(255,255,255,230)));
521 | // by default, the legend is in the inset layout of the main axis rect. So this is how we access it to change legend placement:
522 | customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignBottom|Qt::AlignRight);
523 |
524 | // setup for graph 0: key axis left, value axis bottom
525 | // will contain left maxwell-like function
526 | customPlot->addGraph(customPlot->yAxis, customPlot->xAxis);
527 | customPlot->graph(0)->setPen(QPen(QColor(255, 100, 0)));
528 | customPlot->graph(0)->setBrush(QBrush(QPixmap("./balboa.jpg"))); // fill with texture of specified image
529 | customPlot->graph(0)->setLineStyle(QCPGraph::lsLine);
530 | customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));
531 | customPlot->graph(0)->setName("Left maxwell function");
532 |
533 | // setup for graph 1: key axis bottom, value axis left (those are the default axes)
534 | // will contain bottom maxwell-like function
535 | customPlot->addGraph();
536 | customPlot->graph(1)->setPen(QPen(Qt::red));
537 | customPlot->graph(1)->setBrush(QBrush(QPixmap("./balboa.jpg"))); // same fill as we used for graph 0
538 | customPlot->graph(1)->setLineStyle(QCPGraph::lsStepCenter);
539 | customPlot->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::red, Qt::white, 7));
540 | customPlot->graph(1)->setErrorType(QCPGraph::etValue);
541 | customPlot->graph(1)->setName("Bottom maxwell function");
542 |
543 | // setup for graph 2: key axis top, value axis right
544 | // will contain high frequency sine with low frequency beating:
545 | customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
546 | customPlot->graph(2)->setPen(QPen(Qt::blue));
547 | customPlot->graph(2)->setName("High frequency sine");
548 |
549 | // setup for graph 3: same axes as graph 2
550 | // will contain low frequency beating envelope of graph 2
551 | customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
552 | QPen blueDotPen;
553 | blueDotPen.setColor(QColor(30, 40, 255, 150));
554 | blueDotPen.setStyle(Qt::DotLine);
555 | blueDotPen.setWidthF(4);
556 | customPlot->graph(3)->setPen(blueDotPen);
557 | customPlot->graph(3)->setName("Sine envelope");
558 |
559 | // setup for graph 4: key axis right, value axis top
560 | // will contain parabolically distributed data points with some random perturbance
561 | customPlot->addGraph(customPlot->yAxis2, customPlot->xAxis2);
562 | customPlot->graph(4)->setPen(QColor(50, 50, 50, 255));
563 | customPlot->graph(4)->setLineStyle(QCPGraph::lsNone);
564 | customPlot->graph(4)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 4));
565 | customPlot->graph(4)->setName("Some random data around\na quadratic function");
566 |
567 | // generate data, just playing with numbers, not much to learn here:
568 | QVector x0(25), y0(25);
569 | QVector x1(15), y1(15), y1err(15);
570 | QVector x2(250), y2(250);
571 | QVector x3(250), y3(250);
572 | QVector x4(250), y4(250);
573 | for (int i=0; i<25; ++i) // data for graph 0
574 | {
575 | x0[i] = 3*i/25.0;
576 | y0[i] = qExp(-x0[i]*x0[i]*0.8)*(x0[i]*x0[i]+x0[i]);
577 | }
578 | for (int i=0; i<15; ++i) // data for graph 1
579 | {
580 | x1[i] = 3*i/15.0;;
581 | y1[i] = qExp(-x1[i]*x1[i])*(x1[i]*x1[i])*2.6;
582 | y1err[i] = y1[i]*0.25;
583 | }
584 | for (int i=0; i<250; ++i) // data for graphs 2, 3 and 4
585 | {
586 | x2[i] = i/250.0*3*M_PI;
587 | x3[i] = x2[i];
588 | x4[i] = i/250.0*100-50;
589 | y2[i] = qSin(x2[i]*12)*qCos(x2[i])*10;
590 | y3[i] = qCos(x3[i])*10;
591 | y4[i] = 0.01*x4[i]*x4[i] + 1.5*(rand()/(double)RAND_MAX-0.5) + 1.5*M_PI;
592 | }
593 |
594 | // pass data points to graphs:
595 | customPlot->graph(0)->setData(x0, y0);
596 | customPlot->graph(1)->setDataValueError(x1, y1, y1err);
597 | customPlot->graph(2)->setData(x2, y2);
598 | customPlot->graph(3)->setData(x3, y3);
599 | customPlot->graph(4)->setData(x4, y4);
600 | // activate top and right axes, which are invisible by default:
601 | customPlot->xAxis2->setVisible(true);
602 | customPlot->yAxis2->setVisible(true);
603 | // set ranges appropriate to show data:
604 | customPlot->xAxis->setRange(0, 2.7);
605 | customPlot->yAxis->setRange(0, 2.6);
606 | customPlot->xAxis2->setRange(0, 3.0*M_PI);
607 | customPlot->yAxis2->setRange(-70, 35);
608 | // set pi ticks on top axis:
609 | QVector piTicks;
610 | QVector piLabels;
611 | piTicks << 0 << 0.5*M_PI << M_PI << 1.5*M_PI << 2*M_PI << 2.5*M_PI << 3*M_PI;
612 | piLabels << "0" << QString::fromUtf8("½π") << QString::fromUtf8("π") << QString::fromUtf8("1½π") << QString::fromUtf8("2π") << QString::fromUtf8("2½π") << QString::fromUtf8("3π");
613 | customPlot->xAxis2->setAutoTicks(false);
614 | customPlot->xAxis2->setAutoTickLabels(false);
615 | customPlot->xAxis2->setTickVector(piTicks);
616 | customPlot->xAxis2->setTickVectorLabels(piLabels);
617 | // add title layout element:
618 | customPlot->plotLayout()->insertRow(0);
619 | customPlot->plotLayout()->addElement(0, 0, new QCPPlotTitle(customPlot, "Way too many graphs in one plot"));
620 | // set labels:
621 | customPlot->xAxis->setLabel("Bottom axis with outward ticks");
622 | customPlot->yAxis->setLabel("Left axis label");
623 | customPlot->xAxis2->setLabel("Top axis label");
624 | customPlot->yAxis2->setLabel("Right axis label");
625 | // make ticks on bottom axis go outward:
626 | customPlot->xAxis->setTickLength(0, 5);
627 | customPlot->xAxis->setSubTickLength(0, 3);
628 | // make ticks on right axis go inward and outward:
629 | customPlot->yAxis2->setTickLength(3, 3);
630 | customPlot->yAxis2->setSubTickLength(1, 1);
631 | }
632 |
633 | void MainWindow::setupLogarithmicDemo(QCustomPlot *customPlot)
634 | {
635 | demoName = "Logarithmic Demo";
636 | customPlot->setNoAntialiasingOnDrag(true); // more performance/responsiveness during dragging
637 | customPlot->addGraph();
638 | QPen pen;
639 | pen.setColor(QColor(255,170,100));
640 | pen.setWidth(2);
641 | pen.setStyle(Qt::DotLine);
642 | customPlot->graph(0)->setPen(pen);
643 | customPlot->graph(0)->setName("x");
644 |
645 | customPlot->addGraph();
646 | customPlot->graph(1)->setPen(QPen(Qt::red));
647 | customPlot->graph(1)->setBrush(QBrush(QColor(255, 0, 0, 20)));
648 | customPlot->graph(1)->setErrorType(QCPGraph::etBoth);
649 | customPlot->graph(1)->setName("-sin(x)exp(x)");
650 |
651 | customPlot->addGraph();
652 | customPlot->graph(2)->setPen(QPen(Qt::blue));
653 | customPlot->graph(2)->setBrush(QBrush(QColor(0, 0, 255, 20)));
654 | customPlot->graph(2)->setName(" sin(x)exp(x)");
655 |
656 | customPlot->addGraph();
657 | pen.setColor(QColor(0,0,0));
658 | pen.setWidth(1);
659 | pen.setStyle(Qt::DashLine);
660 | customPlot->graph(3)->setPen(pen);
661 | customPlot->graph(3)->setBrush(QBrush(QColor(0,0,0,15)));
662 | customPlot->graph(3)->setLineStyle(QCPGraph::lsStepCenter);
663 | customPlot->graph(3)->setName("x!");
664 |
665 | QVector x0(200), y0(200);
666 | QVector x1(200), y1(200);
667 | QVector x2(200), y2(200);
668 | QVector x3(21), y3(21);
669 | for (int i=0; i<200; ++i)
670 | {
671 | x0[i] = i/10.0;
672 | y0[i] = x0[i];
673 | x1[i] = i/10.0;
674 | y1[i] = -qSin(x1[i])*qExp(x1[i]);
675 | x2[i] = i/10.0;
676 | y2[i] = qSin(x2[i])*qExp(x2[i]);
677 | }
678 | for (int i=0; i<21; ++i)
679 | {
680 | x3[i] = i;
681 | y3[i] = 1;
682 | for (int k=1; k<=i; ++k) y3[i] *= k; // factorial
683 | }
684 | customPlot->graph(0)->setData(x0, y0);
685 | customPlot->graph(1)->setData(x1, y1);
686 | customPlot->graph(2)->setData(x2, y2);
687 | customPlot->graph(3)->setData(x3, y3);
688 |
689 | customPlot->yAxis->grid()->setSubGridVisible(true);
690 | customPlot->xAxis->grid()->setSubGridVisible(true);
691 | customPlot->yAxis->setScaleType(QCPAxis::stLogarithmic);
692 | customPlot->yAxis->setScaleLogBase(100);
693 | customPlot->yAxis->setNumberFormat("eb"); // e = exponential, b = beautiful decimal powers
694 | customPlot->yAxis->setNumberPrecision(0); // makes sure "1*10^4" is displayed only as "10^4"
695 | customPlot->yAxis->setSubTickCount(10);
696 | customPlot->xAxis->setRange(0, 19.9);
697 | customPlot->yAxis->setRange(1e-2, 1e10);
698 | // make range draggable and zoomable:
699 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
700 |
701 | // make top right axes clones of bottom left axes:
702 | customPlot->axisRect()->setupFullAxesBox();
703 | // connect signals so top and right axes move in sync with bottom and left axes:
704 | connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
705 | connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
706 |
707 | customPlot->legend->setVisible(true);
708 | customPlot->legend->setBrush(QBrush(QColor(255,255,255,150)));
709 | customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignLeft|Qt::AlignTop); // make legend align in top left corner or axis rect
710 | }
711 |
712 | void MainWindow::setupRealtimeDataDemo(QCustomPlot *customPlot)
713 | {
714 | #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
715 | QMessageBox::critical(this, "", "You're using Qt < 4.7, the realtime data demo needs functions that are available with Qt 4.7 to work properly");
716 | #endif
717 | demoName = "Real Time Data Demo";
718 |
719 | // include this section to fully disable antialiasing for higher performance:
720 | /*
721 | customPlot->setNotAntialiasedElements(QCP::aeAll);
722 | QFont font;
723 | font.setStyleStrategy(QFont::NoAntialias);
724 | customPlot->xAxis->setTickLabelFont(font);
725 | customPlot->yAxis->setTickLabelFont(font);
726 | customPlot->legend->setFont(font);
727 | */
728 | customPlot->addGraph(); // blue line
729 | customPlot->graph(0)->setPen(QPen(Qt::blue));
730 | customPlot->graph(0)->setBrush(QBrush(QColor(240, 255, 200)));
731 | customPlot->graph(0)->setAntialiasedFill(false);
732 | customPlot->addGraph(); // red line
733 | customPlot->graph(1)->setPen(QPen(Qt::red));
734 | customPlot->graph(0)->setChannelFillGraph(customPlot->graph(1));
735 |
736 | customPlot->addGraph(); // blue dot
737 | customPlot->graph(2)->setPen(QPen(Qt::blue));
738 | customPlot->graph(2)->setLineStyle(QCPGraph::lsNone);
739 | customPlot->graph(2)->setScatterStyle(QCPScatterStyle::ssDisc);
740 | customPlot->addGraph(); // red dot
741 | customPlot->graph(3)->setPen(QPen(Qt::red));
742 | customPlot->graph(3)->setLineStyle(QCPGraph::lsNone);
743 | customPlot->graph(3)->setScatterStyle(QCPScatterStyle::ssDisc);
744 |
745 | customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
746 | customPlot->xAxis->setDateTimeFormat("hh:mm:ss");
747 | customPlot->xAxis->setAutoTickStep(false);
748 | customPlot->xAxis->setTickStep(2);
749 | customPlot->axisRect()->setupFullAxesBox();
750 |
751 | // make left and bottom axes transfer their ranges to right and top axes:
752 | connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
753 | connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
754 |
755 | // setup a timer that repeatedly calls MainWindow::realtimeDataSlot:
756 | connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
757 | dataTimer.start(0); // Interval 0 means to refresh as fast as possible
758 | }
759 |
760 | void MainWindow::setupParametricCurveDemo(QCustomPlot *customPlot)
761 | {
762 | demoName = "Parametric Curves Demo";
763 |
764 | // create empty curve objects and add them to customPlot:
765 | QCPCurve *fermatSpiral1 = new QCPCurve(customPlot->xAxis, customPlot->yAxis);
766 | QCPCurve *fermatSpiral2 = new QCPCurve(customPlot->xAxis, customPlot->yAxis);
767 | QCPCurve *deltoidRadial = new QCPCurve(customPlot->xAxis, customPlot->yAxis);
768 | customPlot->addPlottable(fermatSpiral1);
769 | customPlot->addPlottable(fermatSpiral2);
770 | customPlot->addPlottable(deltoidRadial);
771 | // generate the curve data points:
772 | int pointCount = 500;
773 | QVector x1(pointCount), y1(pointCount);
774 | QVector x2(pointCount), y2(pointCount);
775 | QVector x3(pointCount), y3(pointCount);
776 | for (int i=0; isetData(x1, y1);
789 | fermatSpiral2->setData(x2, y2);
790 | deltoidRadial->setData(x3, y3);
791 | // color the curves:
792 | fermatSpiral1->setPen(QPen(Qt::blue));
793 | fermatSpiral1->setBrush(QBrush(QColor(0, 0, 255, 20)));
794 | fermatSpiral2->setPen(QPen(QColor(255, 120, 0)));
795 | fermatSpiral2->setBrush(QBrush(QColor(255, 120, 0, 30)));
796 | QRadialGradient radialGrad(QPointF(310, 180), 200);
797 | radialGrad.setColorAt(0, QColor(170, 20, 240, 100));
798 | radialGrad.setColorAt(0.5, QColor(20, 10, 255, 40));
799 | radialGrad.setColorAt(1,QColor(120, 20, 240, 10));
800 | deltoidRadial->setPen(QPen(QColor(170, 20, 240)));
801 | deltoidRadial->setBrush(QBrush(radialGrad));
802 | // set some basic customPlot config:
803 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
804 | customPlot->axisRect()->setupFullAxesBox();
805 | customPlot->rescaleAxes();
806 | }
807 |
808 | void MainWindow::setupBarChartDemo(QCustomPlot *customPlot)
809 | {
810 | demoName = "Bar Chart Demo";
811 | // create empty bar chart objects:
812 | QCPBars *regen = new QCPBars(customPlot->xAxis, customPlot->yAxis);
813 | QCPBars *nuclear = new QCPBars(customPlot->xAxis, customPlot->yAxis);
814 | QCPBars *fossil = new QCPBars(customPlot->xAxis, customPlot->yAxis);
815 | customPlot->addPlottable(regen);
816 | customPlot->addPlottable(nuclear);
817 | customPlot->addPlottable(fossil);
818 | // set names and colors:
819 | QPen pen;
820 | pen.setWidthF(1.2);
821 | fossil->setName("Fossil fuels");
822 | pen.setColor(QColor(255, 131, 0));
823 | fossil->setPen(pen);
824 | fossil->setBrush(QColor(255, 131, 0, 50));
825 | nuclear->setName("Nuclear");
826 | pen.setColor(QColor(1, 92, 191));
827 | nuclear->setPen(pen);
828 | nuclear->setBrush(QColor(1, 92, 191, 50));
829 | regen->setName("Regenerative");
830 | pen.setColor(QColor(150, 222, 0));
831 | regen->setPen(pen);
832 | regen->setBrush(QColor(150, 222, 0, 70));
833 | // stack bars ontop of each other:
834 | nuclear->moveAbove(fossil);
835 | regen->moveAbove(nuclear);
836 |
837 | // prepare x axis with country labels:
838 | QVector ticks;
839 | QVector labels;
840 | ticks << 1 << 2 << 3 << 4 << 5 << 6 << 7;
841 | labels << "USA" << "Japan" << "Germany" << "France" << "UK" << "Italy" << "Canada";
842 | customPlot->xAxis->setAutoTicks(false);
843 | customPlot->xAxis->setAutoTickLabels(false);
844 | customPlot->xAxis->setTickVector(ticks);
845 | customPlot->xAxis->setTickVectorLabels(labels);
846 | customPlot->xAxis->setTickLabelRotation(60);
847 | customPlot->xAxis->setSubTickCount(0);
848 | customPlot->xAxis->setTickLength(0, 4);
849 | customPlot->xAxis->grid()->setVisible(true);
850 | customPlot->xAxis->setRange(0, 8);
851 |
852 | // prepare y axis:
853 | customPlot->yAxis->setRange(0, 12.1);
854 | customPlot->yAxis->setPadding(5); // a bit more space to the left border
855 | customPlot->yAxis->setLabel("Power Consumption in\nKilowatts per Capita (2007)");
856 | customPlot->yAxis->grid()->setSubGridVisible(true);
857 | QPen gridPen;
858 | gridPen.setStyle(Qt::SolidLine);
859 | gridPen.setColor(QColor(0, 0, 0, 25));
860 | customPlot->yAxis->grid()->setPen(gridPen);
861 | gridPen.setStyle(Qt::DotLine);
862 | customPlot->yAxis->grid()->setSubGridPen(gridPen);
863 |
864 | // Add data:
865 | QVector fossilData, nuclearData, regenData;
866 | fossilData << 0.86*10.5 << 0.83*5.5 << 0.84*5.5 << 0.52*5.8 << 0.89*5.2 << 0.90*4.2 << 0.67*11.2;
867 | nuclearData << 0.08*10.5 << 0.12*5.5 << 0.12*5.5 << 0.40*5.8 << 0.09*5.2 << 0.00*4.2 << 0.07*11.2;
868 | regenData << 0.06*10.5 << 0.05*5.5 << 0.04*5.5 << 0.06*5.8 << 0.02*5.2 << 0.07*4.2 << 0.25*11.2;
869 | fossil->setData(ticks, fossilData);
870 | nuclear->setData(ticks, nuclearData);
871 | regen->setData(ticks, regenData);
872 |
873 | // setup legend:
874 | customPlot->legend->setVisible(true);
875 | customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop|Qt::AlignHCenter);
876 | customPlot->legend->setBrush(QColor(255, 255, 255, 200));
877 | QPen legendPen;
878 | legendPen.setColor(QColor(130, 130, 130, 200));
879 | customPlot->legend->setBorderPen(legendPen);
880 | QFont legendFont = font();
881 | legendFont.setPointSize(10);
882 | customPlot->legend->setFont(legendFont);
883 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
884 | }
885 |
886 | void MainWindow::setupStatisticalDemo(QCustomPlot *customPlot)
887 | {
888 | demoName = "Statistical Demo";
889 | // create empty statistical box plottables:
890 | QCPStatisticalBox *sample1 = new QCPStatisticalBox(customPlot->xAxis, customPlot->yAxis);
891 | QCPStatisticalBox *sample2 = new QCPStatisticalBox(customPlot->xAxis, customPlot->yAxis);
892 | QCPStatisticalBox *sample3 = new QCPStatisticalBox(customPlot->xAxis, customPlot->yAxis);
893 | customPlot->addPlottable(sample1);
894 | customPlot->addPlottable(sample2);
895 | customPlot->addPlottable(sample3);
896 | QBrush boxBrush(QColor(60, 60, 255, 100));
897 | boxBrush.setStyle(Qt::Dense6Pattern); // make it look oldschool
898 | sample1->setBrush(boxBrush);
899 | sample2->setBrush(boxBrush);
900 | sample3->setBrush(boxBrush);
901 |
902 | // set data:
903 | sample1->setKey(1);
904 | sample1->setMinimum(1.1);
905 | sample1->setLowerQuartile(1.9);
906 | sample1->setMedian(2.25);
907 | sample1->setUpperQuartile(2.7);
908 | sample1->setMaximum(4.2);
909 |
910 | sample2->setKey(2);
911 | sample2->setMinimum(0.8);
912 | sample2->setLowerQuartile(1.6);
913 | sample2->setMedian(2.2);
914 | sample2->setUpperQuartile(3.2);
915 | sample2->setMaximum(4.9);
916 | sample2->setOutliers(QVector() << 0.7 << 0.39 << 0.45 << 6.2 << 5.84);
917 |
918 | sample3->setKey(3);
919 | sample3->setMinimum(0.2);
920 | sample3->setLowerQuartile(0.7);
921 | sample3->setMedian(1.1);
922 | sample3->setUpperQuartile(1.6);
923 | sample3->setMaximum(2.9);
924 |
925 | // prepare manual x axis labels:
926 | customPlot->xAxis->setSubTickCount(0);
927 | customPlot->xAxis->setTickLength(0, 4);
928 | customPlot->xAxis->setTickLabelRotation(20);
929 | customPlot->xAxis->setAutoTicks(false);
930 | customPlot->xAxis->setAutoTickLabels(false);
931 | customPlot->xAxis->setTickVector(QVector() << 1 << 2 << 3);
932 | customPlot->xAxis->setTickVectorLabels(QVector() << "Sample 1" << "Sample 2" << "Control Group");
933 |
934 | // prepare axes:
935 | customPlot->yAxis->setLabel(QString::fromUtf8("O₂ Absorption [mg]"));
936 | customPlot->rescaleAxes();
937 | customPlot->xAxis->scaleRange(1.7, customPlot->xAxis->range().center());
938 | customPlot->yAxis->setRange(0, 7);
939 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
940 | }
941 |
942 | void MainWindow::setupSimpleItemDemo(QCustomPlot *customPlot)
943 | {
944 | demoName = "Simple Item Demo";
945 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
946 |
947 | // add the text label at the top:
948 | QCPItemText *textLabel = new QCPItemText(customPlot);
949 | customPlot->addItem(textLabel);
950 | textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);
951 | textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
952 | textLabel->position->setCoords(0.5, 0); // place position at center/top of axis rect
953 | textLabel->setText("Text Item Demo");
954 | textLabel->setFont(QFont(font().family(), 16)); // make font a bit larger
955 | textLabel->setPen(QPen(Qt::black)); // show black border around text
956 |
957 | // add the arrow:
958 | QCPItemLine *arrow = new QCPItemLine(customPlot);
959 | customPlot->addItem(arrow);
960 | arrow->start->setParentAnchor(textLabel->bottom);
961 | arrow->end->setCoords(4, 1.6); // point to (4, 1.6) in x-y-plot coordinates
962 | arrow->setHead(QCPLineEnding::esSpikeArrow);
963 | }
964 |
965 | void MainWindow::setupItemDemo(QCustomPlot *customPlot)
966 | {
967 | #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
968 | QMessageBox::critical(this, "", "You're using Qt < 4.7, the animation of the item demo needs functions that are available with Qt 4.7 to work properly");
969 | #endif
970 |
971 | demoName = "Item Demo";
972 |
973 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
974 | QCPGraph *graph = customPlot->addGraph();
975 | int n = 500;
976 | double phase = 0;
977 | double k = 3;
978 | QVector x(n), y(n);
979 | for (int i=0; isetData(x, y);
985 | graph->setPen(QPen(Qt::blue));
986 | graph->rescaleKeyAxis();
987 | customPlot->yAxis->setRange(-1.45, 1.65);
988 | customPlot->xAxis->grid()->setZeroLinePen(Qt::NoPen);
989 |
990 | // add the bracket at the top:
991 | QCPItemBracket *bracket = new QCPItemBracket(customPlot);
992 | customPlot->addItem(bracket);
993 | bracket->left->setCoords(-8, 1.1);
994 | bracket->right->setCoords(8, 1.1);
995 | bracket->setLength(13);
996 |
997 | // add the text label at the top:
998 | QCPItemText *wavePacketText = new QCPItemText(customPlot);
999 | customPlot->addItem(wavePacketText);
1000 | wavePacketText->position->setParentAnchor(bracket->center);
1001 | wavePacketText->position->setCoords(0, -10); // move 10 pixels to the top from bracket center anchor
1002 | wavePacketText->setPositionAlignment(Qt::AlignBottom|Qt::AlignHCenter);
1003 | wavePacketText->setText("Wavepacket");
1004 | wavePacketText->setFont(QFont(font().family(), 10));
1005 |
1006 | // add the phase tracer (red circle) which sticks to the graph data (and gets updated in bracketDataSlot by timer event):
1007 | QCPItemTracer *phaseTracer = new QCPItemTracer(customPlot);
1008 | customPlot->addItem(phaseTracer);
1009 | itemDemoPhaseTracer = phaseTracer; // so we can access it later in the bracketDataSlot for animation
1010 | phaseTracer->setGraph(graph);
1011 | phaseTracer->setGraphKey((M_PI*1.5-phase)/k);
1012 | phaseTracer->setInterpolating(true);
1013 | phaseTracer->setStyle(QCPItemTracer::tsCircle);
1014 | phaseTracer->setPen(QPen(Qt::red));
1015 | phaseTracer->setBrush(Qt::red);
1016 | phaseTracer->setSize(7);
1017 |
1018 | // add label for phase tracer:
1019 | QCPItemText *phaseTracerText = new QCPItemText(customPlot);
1020 | customPlot->addItem(phaseTracerText);
1021 | phaseTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
1022 | phaseTracerText->setPositionAlignment(Qt::AlignRight|Qt::AlignBottom);
1023 | phaseTracerText->position->setCoords(1.0, 0.95); // lower right corner of axis rect
1024 | phaseTracerText->setText("Points of fixed\nphase define\nphase velocity vp");
1025 | phaseTracerText->setTextAlignment(Qt::AlignLeft);
1026 | phaseTracerText->setFont(QFont(font().family(), 9));
1027 | phaseTracerText->setPadding(QMargins(8, 0, 0, 0));
1028 |
1029 | // add arrow pointing at phase tracer, coming from label:
1030 | QCPItemCurve *phaseTracerArrow = new QCPItemCurve(customPlot);
1031 | customPlot->addItem(phaseTracerArrow);
1032 | phaseTracerArrow->start->setParentAnchor(phaseTracerText->left);
1033 | phaseTracerArrow->startDir->setParentAnchor(phaseTracerArrow->start);
1034 | phaseTracerArrow->startDir->setCoords(-40, 0); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
1035 | phaseTracerArrow->end->setParentAnchor(phaseTracer->position);
1036 | phaseTracerArrow->end->setCoords(10, 10);
1037 | phaseTracerArrow->endDir->setParentAnchor(phaseTracerArrow->end);
1038 | phaseTracerArrow->endDir->setCoords(30, 30);
1039 | phaseTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
1040 | phaseTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, (phaseTracerText->bottom->pixelPoint().y()-phaseTracerText->top->pixelPoint().y())*0.85));
1041 |
1042 | // add the group velocity tracer (green circle):
1043 | QCPItemTracer *groupTracer = new QCPItemTracer(customPlot);
1044 | customPlot->addItem(groupTracer);
1045 | groupTracer->setGraph(graph);
1046 | groupTracer->setGraphKey(5.5);
1047 | groupTracer->setInterpolating(true);
1048 | groupTracer->setStyle(QCPItemTracer::tsCircle);
1049 | groupTracer->setPen(QPen(Qt::green));
1050 | groupTracer->setBrush(Qt::green);
1051 | groupTracer->setSize(7);
1052 |
1053 | // add label for group tracer:
1054 | QCPItemText *groupTracerText = new QCPItemText(customPlot);
1055 | customPlot->addItem(groupTracerText);
1056 | groupTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
1057 | groupTracerText->setPositionAlignment(Qt::AlignRight|Qt::AlignTop);
1058 | groupTracerText->position->setCoords(1.0, 0.20); // lower right corner of axis rect
1059 | groupTracerText->setText("Fixed positions in\nwave packet define\ngroup velocity vg");
1060 | groupTracerText->setTextAlignment(Qt::AlignLeft);
1061 | groupTracerText->setFont(QFont(font().family(), 9));
1062 | groupTracerText->setPadding(QMargins(8, 0, 0, 0));
1063 |
1064 | // add arrow pointing at group tracer, coming from label:
1065 | QCPItemCurve *groupTracerArrow = new QCPItemCurve(customPlot);
1066 | customPlot->addItem(groupTracerArrow);
1067 | groupTracerArrow->start->setParentAnchor(groupTracerText->left);
1068 | groupTracerArrow->startDir->setParentAnchor(groupTracerArrow->start);
1069 | groupTracerArrow->startDir->setCoords(-40, 0); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
1070 | groupTracerArrow->end->setCoords(5.5, 0.4);
1071 | groupTracerArrow->endDir->setParentAnchor(groupTracerArrow->end);
1072 | groupTracerArrow->endDir->setCoords(0, -40);
1073 | groupTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
1074 | groupTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, (groupTracerText->bottom->pixelPoint().y()-groupTracerText->top->pixelPoint().y())*0.85));
1075 |
1076 | // add dispersion arrow:
1077 | QCPItemCurve *arrow = new QCPItemCurve(customPlot);
1078 | customPlot->addItem(arrow);
1079 | arrow->start->setCoords(1, -1.1);
1080 | arrow->startDir->setCoords(-1, -1.3);
1081 | arrow->endDir->setCoords(-5, -0.3);
1082 | arrow->end->setCoords(-10, -0.2);
1083 | arrow->setHead(QCPLineEnding::esSpikeArrow);
1084 |
1085 | // add the dispersion arrow label:
1086 | QCPItemText *dispersionText = new QCPItemText(customPlot);
1087 | customPlot->addItem(dispersionText);
1088 | dispersionText->position->setCoords(-6, -0.9);
1089 | dispersionText->setRotation(40);
1090 | dispersionText->setText("Dispersion with\nvp < vg");
1091 | dispersionText->setFont(QFont(font().family(), 10));
1092 |
1093 | // setup a timer that repeatedly calls MainWindow::realtimeDataSlot:
1094 | connect(&dataTimer, SIGNAL(timeout()), this, SLOT(bracketDataSlot()));
1095 | dataTimer.start(0); // Interval 0 means to refresh as fast as possible
1096 | }
1097 |
1098 | void MainWindow::setupStyledDemo(QCustomPlot *customPlot)
1099 | {
1100 | demoName = "Styled Demo";
1101 |
1102 | // prepare data:
1103 | QVector x1(20), y1(20);
1104 | QVector x2(100), y2(100);
1105 | QVector x3(20), y3(20);
1106 | QVector x4(20), y4(20);
1107 | for (int i=0; iaddGraph();
1130 | graph1->setData(x1, y1);
1131 | graph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 9));
1132 | graph1->setPen(QPen(QColor(120, 120, 120), 2));
1133 |
1134 | QCPGraph *graph2 = customPlot->addGraph();
1135 | graph2->setData(x2, y2);
1136 | graph2->setPen(Qt::NoPen);
1137 | graph2->setBrush(QColor(200, 200, 200, 20));
1138 | graph2->setChannelFillGraph(graph1);
1139 |
1140 | QCPBars *bars1 = new QCPBars(customPlot->xAxis, customPlot->yAxis);
1141 | customPlot->addPlottable(bars1);
1142 | bars1->setWidth(9/(double)x3.size());
1143 | bars1->setData(x3, y3);
1144 | bars1->setPen(Qt::NoPen);
1145 | bars1->setBrush(QColor(10, 140, 70, 160));
1146 |
1147 | QCPBars *bars2 = new QCPBars(customPlot->xAxis, customPlot->yAxis);
1148 | customPlot->addPlottable(bars2);
1149 | bars2->setWidth(9/(double)x4.size());
1150 | bars2->setData(x4, y4);
1151 | bars2->setPen(Qt::NoPen);
1152 | bars2->setBrush(QColor(10, 100, 50, 70));
1153 | bars2->moveAbove(bars1);
1154 |
1155 | // move bars above graphs and grid below bars:
1156 | customPlot->addLayer("abovemain", customPlot->layer("main"), QCustomPlot::limAbove);
1157 | customPlot->addLayer("belowmain", customPlot->layer("main"), QCustomPlot::limBelow);
1158 | graph1->setLayer("abovemain");
1159 | customPlot->xAxis->grid()->setLayer("belowmain");
1160 | customPlot->yAxis->grid()->setLayer("belowmain");
1161 |
1162 | // set some pens, brushes and backgrounds:
1163 | customPlot->xAxis->setBasePen(QPen(Qt::white, 1));
1164 | customPlot->yAxis->setBasePen(QPen(Qt::white, 1));
1165 | customPlot->xAxis->setTickPen(QPen(Qt::white, 1));
1166 | customPlot->yAxis->setTickPen(QPen(Qt::white, 1));
1167 | customPlot->xAxis->setSubTickPen(QPen(Qt::white, 1));
1168 | customPlot->yAxis->setSubTickPen(QPen(Qt::white, 1));
1169 | customPlot->xAxis->setTickLabelColor(Qt::white);
1170 | customPlot->yAxis->setTickLabelColor(Qt::white);
1171 | customPlot->xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
1172 | customPlot->yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
1173 | customPlot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
1174 | customPlot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
1175 | customPlot->xAxis->grid()->setSubGridVisible(true);
1176 | customPlot->yAxis->grid()->setSubGridVisible(true);
1177 | customPlot->xAxis->grid()->setZeroLinePen(Qt::NoPen);
1178 | customPlot->yAxis->grid()->setZeroLinePen(Qt::NoPen);
1179 | customPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
1180 | customPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
1181 | QLinearGradient plotGradient;
1182 | plotGradient.setStart(0, 0);
1183 | plotGradient.setFinalStop(0, 350);
1184 | plotGradient.setColorAt(0, QColor(80, 80, 80));
1185 | plotGradient.setColorAt(1, QColor(50, 50, 50));
1186 | customPlot->setBackground(plotGradient);
1187 | QLinearGradient axisRectGradient;
1188 | axisRectGradient.setStart(0, 0);
1189 | axisRectGradient.setFinalStop(0, 350);
1190 | axisRectGradient.setColorAt(0, QColor(80, 80, 80));
1191 | axisRectGradient.setColorAt(1, QColor(30, 30, 30));
1192 | customPlot->axisRect()->setBackground(axisRectGradient);
1193 |
1194 | customPlot->rescaleAxes();
1195 | customPlot->yAxis->setRange(0, 2);
1196 | }
1197 |
1198 | void MainWindow::setupAdvancedAxesDemo(QCustomPlot *customPlot)
1199 | {
1200 | demoName = "Advanced Axes Demo";
1201 |
1202 | // configure axis rect:
1203 | customPlot->plotLayout()->clear(); // clear default axis rect so we can start from scratch
1204 | QCPAxisRect *wideAxisRect = new QCPAxisRect(customPlot);
1205 | wideAxisRect->setupFullAxesBox(true);
1206 | wideAxisRect->axis(QCPAxis::atRight, 0)->setTickLabels(true);
1207 | wideAxisRect->addAxis(QCPAxis::atLeft)->setTickLabelColor(QColor("#6050F8")); // add an extra axis on the left and color its numbers
1208 | QCPLayoutGrid *subLayout = new QCPLayoutGrid;
1209 | customPlot->plotLayout()->addElement(0, 0, wideAxisRect); // insert axis rect in first row
1210 | customPlot->plotLayout()->addElement(1, 0, subLayout); // sub layout in second row (grid layout will grow accordingly)
1211 | //customPlot->plotLayout()->setRowStretchFactor(1, 2);
1212 | // prepare axis rects that will be placed in the sublayout:
1213 | QCPAxisRect *subRectLeft = new QCPAxisRect(customPlot, false); // false means to not setup default axes
1214 | QCPAxisRect *subRectRight = new QCPAxisRect(customPlot, false);
1215 | subLayout->addElement(0, 0, subRectLeft);
1216 | subLayout->addElement(0, 1, subRectRight);
1217 | subRectRight->setMaximumSize(150, 150); // make bottom right axis rect size fixed 150x150
1218 | subRectRight->setMinimumSize(150, 150); // make bottom right axis rect size fixed 150x150
1219 | // setup axes in sub layout axis rects:
1220 | subRectLeft->addAxes(QCPAxis::atBottom | QCPAxis::atLeft);
1221 | subRectRight->addAxes(QCPAxis::atBottom | QCPAxis::atRight);
1222 | subRectLeft->axis(QCPAxis::atLeft)->setAutoTickCount(2);
1223 | subRectRight->axis(QCPAxis::atRight)->setAutoTickCount(2);
1224 | subRectRight->axis(QCPAxis::atBottom)->setAutoTickCount(2);
1225 | subRectLeft->axis(QCPAxis::atBottom)->grid()->setVisible(true);
1226 | // synchronize the left and right margins of the top and bottom axis rects:
1227 | QCPMarginGroup *marginGroup = new QCPMarginGroup(customPlot);
1228 | subRectLeft->setMarginGroup(QCP::msLeft, marginGroup);
1229 | subRectRight->setMarginGroup(QCP::msRight, marginGroup);
1230 | wideAxisRect->setMarginGroup(QCP::msLeft | QCP::msRight, marginGroup);
1231 | // move newly created axes on "axes" layer and grids on "grid" layer:
1232 | foreach (QCPAxisRect *rect, customPlot->axisRects())
1233 | {
1234 | foreach (QCPAxis *axis, rect->axes())
1235 | {
1236 | axis->setLayer("axes");
1237 | axis->grid()->setLayer("grid");
1238 | }
1239 | }
1240 |
1241 | // prepare data:
1242 | QVector x1a(20), y1a(20);
1243 | QVector x1b(50), y1b(50);
1244 | QVector x2(100), y2(100);
1245 | QVector x3, y3;
1246 | qsrand(3);
1247 | for (int i=0; iaddGraph(wideAxisRect->axis(QCPAxis::atBottom), wideAxisRect->axis(QCPAxis::atLeft));
1267 | mainGraph1->setData(x1a, y1a);
1268 | mainGraph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black), QBrush(Qt::white), 6));
1269 | mainGraph1->setPen(QPen(QColor(120, 120, 120), 2));
1270 | QCPGraph *mainGraph2 = customPlot->addGraph(wideAxisRect->axis(QCPAxis::atBottom), wideAxisRect->axis(QCPAxis::atLeft, 1));
1271 | mainGraph2->setData(x1b, y1b);
1272 | mainGraph2->setPen(QPen(QColor("#8070B8"), 2));
1273 | mainGraph2->setBrush(QColor(110, 170, 110, 30));
1274 | mainGraph1->setChannelFillGraph(mainGraph2);
1275 | mainGraph1->setBrush(QColor(255, 161, 0, 50));
1276 |
1277 | QCPGraph *graph2 = customPlot->addGraph(subRectLeft->axis(QCPAxis::atBottom), subRectLeft->axis(QCPAxis::atLeft));
1278 | graph2->setData(x2, y2);
1279 | graph2->setLineStyle(QCPGraph::lsImpulse);
1280 | graph2->setPen(QPen(QColor("#FFA100"), 1.5));
1281 |
1282 | QCPBars *bars1 = new QCPBars(subRectRight->axis(QCPAxis::atBottom), subRectRight->axis(QCPAxis::atRight));
1283 | customPlot->addPlottable(bars1);
1284 | bars1->setWidth(3/(double)x3.size());
1285 | bars1->setData(x3, y3);
1286 | bars1->setPen(QPen(Qt::black));
1287 | bars1->setAntialiased(false);
1288 | bars1->setAntialiasedFill(false);
1289 | bars1->setBrush(QColor("#705BE8"));
1290 | bars1->keyAxis()->setAutoTicks(false);
1291 | bars1->keyAxis()->setTickVector(x3);
1292 | bars1->keyAxis()->setSubTickCount(0);
1293 |
1294 | // rescale axes according to graph's data:
1295 | mainGraph1->rescaleAxes();
1296 | mainGraph2->rescaleAxes();
1297 | graph2->rescaleAxes();
1298 | bars1->rescaleAxes();
1299 | wideAxisRect->axis(QCPAxis::atLeft, 1)->setRangeLower(0);
1300 | }
1301 |
1302 | void MainWindow::setupColorMapDemo(QCustomPlot *customPlot)
1303 | {
1304 | demoName = "Color Map Demo";
1305 |
1306 | // configure axis rect:
1307 | customPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom); // this will also allow rescaling the color scale by dragging/zooming
1308 | customPlot->axisRect()->setupFullAxesBox(true);
1309 | customPlot->xAxis->setLabel("x");
1310 | customPlot->yAxis->setLabel("y");
1311 |
1312 | // set up the QCPColorMap:
1313 | QCPColorMap *colorMap = new QCPColorMap(customPlot->xAxis, customPlot->yAxis);
1314 | customPlot->addPlottable(colorMap);
1315 | int nx = 200;
1316 | int ny = 200;
1317 | colorMap->data()->setSize(nx, ny); // we want the color map to have nx * ny data points
1318 | colorMap->data()->setRange(QCPRange(-4, 4), QCPRange(-4, 4)); // and span the coordinate range -4..4 in both key (x) and value (y) dimensions
1319 | // now we assign some data, by accessing the QCPColorMapData instance of the color map:
1320 | double x, y, z;
1321 | for (int xIndex=0; xIndexdata()->cellToCoord(xIndex, yIndex, &x, &y);
1326 | double r = 3*qSqrt(x*x+y*y)+1e-2;
1327 | z = 2*x*(qCos(r+2)/r-qSin(r+2)/r); // the B field strength of dipole radiation (modulo physical constants)
1328 | colorMap->data()->setCell(xIndex, yIndex, z);
1329 | }
1330 | }
1331 |
1332 | // add a color scale:
1333 | QCPColorScale *colorScale = new QCPColorScale(customPlot);
1334 | customPlot->plotLayout()->addElement(0, 1, colorScale); // add it to the right of the main axis rect
1335 | colorScale->setType(QCPAxis::atRight); // scale shall be vertical bar with tick/axis labels right (actually atRight is already the default)
1336 | colorMap->setColorScale(colorScale); // associate the color map with the color scale
1337 | colorScale->axis()->setLabel("Magnetic Field Strength");
1338 |
1339 | // set the color gradient of the color map to one of the presets:
1340 | colorMap->setGradient(QCPColorGradient::gpPolar);
1341 | // we could have also created a QCPColorGradient instance and added own colors to
1342 | // the gradient, see the documentation of QCPColorGradient for what's possible.
1343 |
1344 | // rescale the data dimension (color) such that all data points lie in the span visualized by the color gradient:
1345 | colorMap->rescaleDataRange();
1346 |
1347 | // make sure the axis rect and color scale synchronize their bottom and top margins (so they line up):
1348 | QCPMarginGroup *marginGroup = new QCPMarginGroup(customPlot);
1349 | customPlot->axisRect()->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
1350 | colorScale->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
1351 |
1352 | // rescale the key (x) and value (y) axes so the whole color map is visible:
1353 | customPlot->rescaleAxes();
1354 | }
1355 |
1356 | void MainWindow::setupFinancialDemo(QCustomPlot *customPlot)
1357 | {
1358 | demoName = "Financial Charts Demo";
1359 | customPlot->legend->setVisible(true);
1360 |
1361 | // generate two sets of random walk data (one for candlestick and one for ohlc chart):
1362 | int n = 500;
1363 | QVector time(n), value1(n), value2(n);
1364 | QDateTime start = QDateTime(QDate(2014, 6, 11));
1365 | start.setTimeSpec(Qt::UTC);
1366 | double startTime = start.toTime_t();
1367 | double binSize = 3600*24; // bin data in 1 day intervals
1368 | time[0] = startTime;
1369 | value1[0] = 60;
1370 | value2[0] = 20;
1371 | qsrand(9);
1372 | for (int i=1; ixAxis, customPlot->yAxis);
1381 | customPlot->addPlottable(candlesticks);
1382 | QCPFinancialDataMap data1 = QCPFinancial::timeSeriesToOhlc(time, value1, binSize, startTime);
1383 | candlesticks->setName("Candlestick");
1384 | candlesticks->setChartStyle(QCPFinancial::csCandlestick);
1385 | candlesticks->setData(&data1, true);
1386 | candlesticks->setWidth(binSize*0.9);
1387 | candlesticks->setTwoColored(true);
1388 | candlesticks->setBrushPositive(QColor(245, 245, 245));
1389 | candlesticks->setBrushNegative(QColor(0, 0, 0));
1390 | candlesticks->setPenPositive(QPen(QColor(0, 0, 0)));
1391 | candlesticks->setPenNegative(QPen(QColor(0, 0, 0)));
1392 |
1393 | // create ohlc chart:
1394 | QCPFinancial *ohlc = new QCPFinancial(customPlot->xAxis, customPlot->yAxis);
1395 | customPlot->addPlottable(ohlc);
1396 | QCPFinancialDataMap data2 = QCPFinancial::timeSeriesToOhlc(time, value2, binSize/3.0, startTime); // divide binSize by 3 just to make the ohlc bars a bit denser
1397 | ohlc->setName("OHLC");
1398 | ohlc->setChartStyle(QCPFinancial::csOhlc);
1399 | ohlc->setData(&data2, true);
1400 | ohlc->setWidth(binSize*0.2);
1401 | ohlc->setTwoColored(true);
1402 |
1403 | // create bottom axis rect for volume bar chart:
1404 | QCPAxisRect *volumeAxisRect = new QCPAxisRect(customPlot);
1405 | customPlot->plotLayout()->addElement(1, 0, volumeAxisRect);
1406 | volumeAxisRect->setMaximumSize(QSize(QWIDGETSIZE_MAX, 100));
1407 | volumeAxisRect->axis(QCPAxis::atBottom)->setLayer("axes");
1408 | volumeAxisRect->axis(QCPAxis::atBottom)->grid()->setLayer("grid");
1409 | // bring bottom and main axis rect closer together:
1410 | customPlot->plotLayout()->setRowSpacing(0);
1411 | volumeAxisRect->setAutoMargins(QCP::msLeft|QCP::msRight|QCP::msBottom);
1412 | volumeAxisRect->setMargins(QMargins(0, 0, 0, 0));
1413 | // create two bar plottables, for positive (green) and negative (red) volume bars:
1414 | QCPBars *volumePos = new QCPBars(volumeAxisRect->axis(QCPAxis::atBottom), volumeAxisRect->axis(QCPAxis::atLeft));
1415 | QCPBars *volumeNeg = new QCPBars(volumeAxisRect->axis(QCPAxis::atBottom), volumeAxisRect->axis(QCPAxis::atLeft));
1416 | for (int i=0; iaddData(startTime+3600*5.0*i, qAbs(v)); // add data to either volumeNeg or volumePos, depending on sign of v
1420 | }
1421 | customPlot->setAutoAddPlottableToLegend(false);
1422 | customPlot->addPlottable(volumePos);
1423 | customPlot->addPlottable(volumeNeg);
1424 | volumePos->setWidth(3600*4);
1425 | volumePos->setPen(Qt::NoPen);
1426 | volumePos->setBrush(QColor(100, 180, 110));
1427 | volumeNeg->setWidth(3600*4);
1428 | volumeNeg->setPen(Qt::NoPen);
1429 | volumeNeg->setBrush(QColor(180, 90, 90));
1430 |
1431 | // interconnect x axis ranges of main and bottom axis rects:
1432 | connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), volumeAxisRect->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
1433 | connect(volumeAxisRect->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis, SLOT(setRange(QCPRange)));
1434 | // configure axes of both main and bottom axis rect:
1435 | volumeAxisRect->axis(QCPAxis::atBottom)->setAutoTickStep(false);
1436 | volumeAxisRect->axis(QCPAxis::atBottom)->setTickStep(3600*24*4); // 4 day tickstep
1437 | volumeAxisRect->axis(QCPAxis::atBottom)->setTickLabelType(QCPAxis::ltDateTime);
1438 | volumeAxisRect->axis(QCPAxis::atBottom)->setDateTimeSpec(Qt::UTC);
1439 | volumeAxisRect->axis(QCPAxis::atBottom)->setDateTimeFormat("dd. MMM");
1440 | volumeAxisRect->axis(QCPAxis::atBottom)->setTickLabelRotation(15);
1441 | volumeAxisRect->axis(QCPAxis::atLeft)->setAutoTickCount(3);
1442 | customPlot->xAxis->setBasePen(Qt::NoPen);
1443 | customPlot->xAxis->setTickLabels(false);
1444 | customPlot->xAxis->setTicks(false); // only want vertical grid in main axis rect, so hide xAxis backbone, ticks, and labels
1445 | customPlot->xAxis->setAutoTickStep(false);
1446 | customPlot->xAxis->setTickStep(3600*24*4); // 4 day tickstep
1447 | customPlot->rescaleAxes();
1448 | customPlot->xAxis->scaleRange(1.025, customPlot->xAxis->range().center());
1449 | customPlot->yAxis->scaleRange(1.1, customPlot->yAxis->range().center());
1450 |
1451 | // make axis rects' left side line up:
1452 | QCPMarginGroup *group = new QCPMarginGroup(customPlot);
1453 | customPlot->axisRect()->setMarginGroup(QCP::msLeft|QCP::msRight, group);
1454 | volumeAxisRect->setMarginGroup(QCP::msLeft|QCP::msRight, group);
1455 | }
1456 |
1457 | void MainWindow::realtimeDataSlot()
1458 | {
1459 | // calculate two new data points:
1460 | #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
1461 | double key = 0;
1462 | #else
1463 | double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
1464 | #endif
1465 | static double lastPointKey = 0;
1466 | if (key-lastPointKey > 0.01) // at most add point every 10 ms
1467 | {
1468 | double value0 = qSin(key); //qSin(key*1.6+qCos(key*1.7)*2)*10 + qSin(key*1.2+0.56)*20 + 26;
1469 | double value1 = qCos(key); //qSin(key*1.3+qCos(key*1.2)*1.2)*7 + qSin(key*0.9+0.26)*24 + 26;
1470 | // add data to lines:
1471 | ui->customPlot->graph(0)->addData(key, value0);
1472 | ui->customPlot->graph(1)->addData(key, value1);
1473 | // set data of dots:
1474 | ui->customPlot->graph(2)->clearData();
1475 | ui->customPlot->graph(2)->addData(key, value0);
1476 | ui->customPlot->graph(3)->clearData();
1477 | ui->customPlot->graph(3)->addData(key, value1);
1478 | // remove data of lines that's outside visible range:
1479 | ui->customPlot->graph(0)->removeDataBefore(key-8);
1480 | ui->customPlot->graph(1)->removeDataBefore(key-8);
1481 | // rescale value (vertical) axis to fit the current data:
1482 | ui->customPlot->graph(0)->rescaleValueAxis();
1483 | ui->customPlot->graph(1)->rescaleValueAxis(true);
1484 | lastPointKey = key;
1485 | }
1486 | // make key axis range scroll with the data (at a constant range size of 8):
1487 | ui->customPlot->xAxis->setRange(key+0.25, 8, Qt::AlignRight);
1488 | ui->customPlot->replot();
1489 |
1490 | // calculate frames per second:
1491 | static double lastFpsKey;
1492 | static int frameCount;
1493 | ++frameCount;
1494 | if (key-lastFpsKey > 2) // average fps over 2 seconds
1495 | {
1496 | ui->statusBar->showMessage(
1497 | QString("%1 FPS, Total Data points: %2")
1498 | .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
1499 | .arg(ui->customPlot->graph(0)->data()->count()+ui->customPlot->graph(1)->data()->count())
1500 | , 0);
1501 | lastFpsKey = key;
1502 | frameCount = 0;
1503 | }
1504 | }
1505 |
1506 | void MainWindow::bracketDataSlot()
1507 | {
1508 | #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
1509 | double secs = 0;
1510 | #else
1511 | double secs = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
1512 | #endif
1513 |
1514 | // update data to make phase move:
1515 | int n = 500;
1516 | double phase = secs*5;
1517 | double k = 3;
1518 | QVector x(n), y(n);
1519 | for (int i=0; icustomPlot->graph()->setData(x, y);
1525 |
1526 | itemDemoPhaseTracer->setGraphKey((8*M_PI+fmod(M_PI*1.5-phase, 6*M_PI))/k);
1527 |
1528 | ui->customPlot->replot();
1529 |
1530 | // calculate frames per second:
1531 | double key = secs;
1532 | static double lastFpsKey;
1533 | static int frameCount;
1534 | ++frameCount;
1535 | if (key-lastFpsKey > 2) // average fps over 2 seconds
1536 | {
1537 | ui->statusBar->showMessage(
1538 | QString("%1 FPS, Total Data points: %2")
1539 | .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
1540 | .arg(ui->customPlot->graph(0)->data()->count())
1541 | , 0);
1542 | lastFpsKey = key;
1543 | frameCount = 0;
1544 | }
1545 | }
1546 |
1547 | void MainWindow::setupPlayground(QCustomPlot *customPlot)
1548 | {
1549 | Q_UNUSED(customPlot)
1550 | }
1551 |
1552 | MainWindow::~MainWindow()
1553 | {
1554 | delete ui;
1555 | }
1556 |
1557 | void MainWindow::screenShot()
1558 | {
1559 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
1560 | QPixmap pm = QPixmap::grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
1561 | #else
1562 | QPixmap pm = qApp->primaryScreen()->grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
1563 | #endif
1564 | QString fileName = demoName.toLower()+".png";
1565 | fileName.replace(" ", "");
1566 | pm.save("./screenshots/"+fileName);
1567 | qApp->quit();
1568 | }
1569 |
1570 | void MainWindow::allScreenShots()
1571 | {
1572 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
1573 | QPixmap pm = QPixmap::grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
1574 | #else
1575 | QPixmap pm = qApp->primaryScreen()->grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
1576 | #endif
1577 | QString fileName = demoName.toLower()+".png";
1578 | fileName.replace(" ", "");
1579 | pm.save("./screenshots/"+fileName);
1580 |
1581 | if (currentDemoIndex < 19)
1582 | {
1583 | if (dataTimer.isActive())
1584 | dataTimer.stop();
1585 | dataTimer.disconnect();
1586 | delete ui->customPlot;
1587 | ui->customPlot = new QCustomPlot(ui->centralWidget);
1588 | ui->verticalLayout->addWidget(ui->customPlot);
1589 | setupDemo(currentDemoIndex+1);
1590 | // setup delay for demos that need time to develop proper look:
1591 | int delay = 250;
1592 | if (currentDemoIndex == 10) // Next is Realtime data demo
1593 | delay = 12000;
1594 | else if (currentDemoIndex == 15) // Next is Item demo
1595 | delay = 5000;
1596 | QTimer::singleShot(delay, this, SLOT(allScreenShots()));
1597 | } else
1598 | {
1599 | qApp->quit();
1600 | }
1601 | }
1602 |
1603 |
1604 |
1605 |
1606 |
1607 |
1608 |
1609 |
1610 |
1611 |
1612 |
1613 |
1614 |
1615 |
1616 |
1617 |
1618 |
1619 |
1620 |
1621 |
1622 |
1623 |
1624 |
1625 |
1626 |
1627 |
1628 |
1629 |
1630 |
1631 |
1632 |
1633 |
1634 |
1635 |
1636 |
1637 |
1638 |
1639 |
1640 |
1641 |
--------------------------------------------------------------------------------
/examples/plots/mainwindow.h:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | /************************************************************************************************************
27 | ** **
28 | ** This is the example code for QCustomPlot. **
29 | ** **
30 | ** It demonstrates basic and some advanced capabilities of the widget. The interesting code is inside **
31 | ** the "setup(...)Demo" functions of MainWindow. **
32 | ** **
33 | ** In order to see a demo in action, call the respective "setup(...)Demo" function inside the **
34 | ** MainWindow constructor. Alternatively you may call setupDemo(i) where i is the index of the demo **
35 | ** you want (for those, see MainWindow constructor comments). All other functions here are merely a **
36 | ** way to easily create screenshots of all demos for the website. I.e. a timer is set to successively **
37 | ** setup all the demos and make a screenshot of the window area and save it in the ./screenshots **
38 | ** directory. **
39 | ** **
40 | *************************************************************************************************************/
41 |
42 | #ifndef MAINWINDOW_H
43 | #define MAINWINDOW_H
44 |
45 | #include
46 | #include
47 | #include "../../qcustomplot.h" // the header file of QCustomPlot. Don't forget to add it to your project, if you use an IDE, so it gets compiled.
48 |
49 | namespace Ui {
50 | class MainWindow;
51 | }
52 |
53 | class MainWindow : public QMainWindow
54 | {
55 | Q_OBJECT
56 |
57 | public:
58 | explicit MainWindow(QWidget *parent = 0);
59 | ~MainWindow();
60 |
61 | void setupDemo(int demoIndex);
62 | void setupQuadraticDemo(QCustomPlot *customPlot);
63 | void setupSimpleDemo(QCustomPlot *customPlot);
64 | void setupSincScatterDemo(QCustomPlot *customPlot);
65 | void setupScatterStyleDemo(QCustomPlot *customPlot);
66 | void setupLineStyleDemo(QCustomPlot *customPlot);
67 | void setupScatterPixmapDemo(QCustomPlot *customPlot);
68 | void setupDateDemo(QCustomPlot *customPlot);
69 | void setupTextureBrushDemo(QCustomPlot *customPlot);
70 | void setupMultiAxisDemo(QCustomPlot *customPlot);
71 | void setupLogarithmicDemo(QCustomPlot *customPlot);
72 | void setupRealtimeDataDemo(QCustomPlot *customPlot);
73 | void setupParametricCurveDemo(QCustomPlot *customPlot);
74 | void setupBarChartDemo(QCustomPlot *customPlot);
75 | void setupStatisticalDemo(QCustomPlot *customPlot);
76 | void setupSimpleItemDemo(QCustomPlot *customPlot);
77 | void setupItemDemo(QCustomPlot *customPlot);
78 | void setupStyledDemo(QCustomPlot *customPlot);
79 | void setupAdvancedAxesDemo(QCustomPlot *customPlot);
80 | void setupColorMapDemo(QCustomPlot *customPlot);
81 | void setupFinancialDemo(QCustomPlot *customPlot);
82 |
83 | void setupPlayground(QCustomPlot *customPlot);
84 |
85 | private slots:
86 | void realtimeDataSlot();
87 | void bracketDataSlot();
88 | void screenShot();
89 | void allScreenShots();
90 |
91 | private:
92 | Ui::MainWindow *ui;
93 | QString demoName;
94 | QTimer dataTimer;
95 | QCPItemTracer *itemDemoPhaseTracer;
96 | int currentDemoIndex;
97 | };
98 |
99 | #endif // MAINWINDOW_H
100 |
--------------------------------------------------------------------------------
/examples/plots/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 548
10 | 420
11 |
12 |
13 |
14 | QCustomPlot plot examples
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | QCustomPlot
29 | QWidget
30 |
31 | 1
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/examples/plots/plot-examples.pro:
--------------------------------------------------------------------------------
1 | #
2 | # QCustomPlot Plot Examples
3 | #
4 |
5 | QT += core gui
6 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
7 |
8 | TARGET = plot-examples
9 | TEMPLATE = app
10 |
11 | SOURCES += main.cpp\
12 | mainwindow.cpp \
13 | ../../qcustomplot.cpp
14 |
15 | HEADERS += mainwindow.h \
16 | ../../qcustomplot.h
17 |
18 | FORMS += mainwindow.ui
19 |
20 |
--------------------------------------------------------------------------------
/examples/plots/screenshots/.gitignore:
--------------------------------------------------------------------------------
1 | *.png
2 |
--------------------------------------------------------------------------------
/examples/plots/screenshots/create-thumbs.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os, shutil, distutils.dir_util, sys, subprocess
3 |
4 | os.chdir(sys.path[0]); # change current working dir to script dir
5 |
6 | if not os.path.isdir("./thumbs"):
7 | os.mkdir("./thumbs");
8 | elif len(os.listdir("./thumbs")) > 0:
9 | if raw_input("Warning: ./thumbs not empty! Continue anyway? (y/n): ") != "y":
10 | sys.exit();
11 |
12 | #sizes = ["264x200"];
13 | sizes = ["220x168"];
14 |
15 | for fileName in os.listdir("./"):
16 | if os.path.isfile(fileName) and "." in fileName and fileName.split(".")[1] == "png":
17 | print "processing "+fileName;
18 | for size in sizes:
19 | subprocess.call("convert -resize "+size+" "+fileName+" -sharpen 0x1 ./thumbs/"+fileName.split(".")[0]+"-thumb.png", shell=True);
20 | #subprocess.call("convert -crop 548x288+0+66 "+fileName+" ./thumbs/"+fileName.split(".")[0]+"-548x288.png", shell=True);
21 | shutil.copy2("./"+fileName, "./thumbs");
22 |
23 | # f = open("main.cpp", "r");
24 | # content = f.read();
25 | # f.close();
26 | # content = content.replace("q"+name.lower()+"hash.h", "../q"+name.lower()+"hash.h");
27 | # f = open("main.cpp", "w");
28 | # f.write(content);
29 | # f.close();
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/examples/plots/solarpanels.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbzhang800/QCustomPlot/d1d69480e3f7af8959ecd3d3b3c8bbfffc7b1292/examples/plots/solarpanels.jpg
--------------------------------------------------------------------------------
/examples/plots/sun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbzhang800/QCustomPlot/d1d69480e3f7af8959ecd3d3b3c8bbfffc7b1292/examples/plots/sun.png
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/.gitignore:
--------------------------------------------------------------------------------
1 | scrollbar-axis-range-control
2 |
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #include "mainwindow.h"
27 | #include "ui_mainwindow.h"
28 |
29 | MainWindow::MainWindow(QWidget *parent) :
30 | QMainWindow(parent),
31 | ui(new Ui::MainWindow)
32 | {
33 | ui->setupUi(this);
34 | setupPlot();
35 |
36 | // configure scroll bars:
37 | // Since scroll bars only support integer values, we'll set a high default range of -500..500 and
38 | // divide scroll bar position values by 100 to provide a scroll range -5..5 in floating point
39 | // axis coordinates. if you want to dynamically grow the range accessible with the scroll bar,
40 | // just increase the the minimum/maximum values of the scroll bars as needed.
41 | ui->horizontalScrollBar->setRange(-500, 500);
42 | ui->verticalScrollBar->setRange(-500, 500);
43 |
44 | // create connection between axes and scroll bars:
45 | connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(horzScrollBarChanged(int)));
46 | connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(vertScrollBarChanged(int)));
47 | connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange)));
48 | connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange)));
49 |
50 | // initialize axis range (and scroll bar positions via signals we just connected):
51 | ui->plot->xAxis->setRange(0, 6, Qt::AlignCenter);
52 | ui->plot->yAxis->setRange(0, 10, Qt::AlignCenter);
53 | }
54 |
55 | MainWindow::~MainWindow()
56 | {
57 | delete ui;
58 | }
59 |
60 | void MainWindow::setupPlot()
61 | {
62 | // The following plot setup is mostly taken from the plot demos:
63 | ui->plot->addGraph();
64 | ui->plot->graph()->setPen(QPen(Qt::blue));
65 | ui->plot->graph()->setBrush(QBrush(QColor(0, 0, 255, 20)));
66 | ui->plot->addGraph();
67 | ui->plot->graph()->setPen(QPen(Qt::red));
68 | QVector x(500), y0(500), y1(500);
69 | for (int i=0; i<500; ++i)
70 | {
71 | x[i] = (i/499.0-0.5)*10;
72 | y0[i] = qExp(-x[i]*x[i]*0.25)*qSin(x[i]*5)*5;
73 | y1[i] = qExp(-x[i]*x[i]*0.25)*5;
74 | }
75 | ui->plot->graph(0)->setData(x, y0);
76 | ui->plot->graph(1)->setData(x, y1);
77 | ui->plot->axisRect()->setupFullAxesBox(true);
78 | ui->plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
79 | }
80 |
81 | void MainWindow::horzScrollBarChanged(int value)
82 | {
83 | if (qAbs(ui->plot->xAxis->range().center()-value/100.0) > 0.01) // if user is dragging plot, we don't want to replot twice
84 | {
85 | ui->plot->xAxis->setRange(value/100.0, ui->plot->xAxis->range().size(), Qt::AlignCenter);
86 | ui->plot->replot();
87 | }
88 | }
89 |
90 | void MainWindow::vertScrollBarChanged(int value)
91 | {
92 | if (qAbs(ui->plot->yAxis->range().center()+value/100.0) > 0.01) // if user is dragging plot, we don't want to replot twice
93 | {
94 | ui->plot->yAxis->setRange(-value/100.0, ui->plot->yAxis->range().size(), Qt::AlignCenter);
95 | ui->plot->replot();
96 | }
97 | }
98 |
99 | void MainWindow::xAxisChanged(QCPRange range)
100 | {
101 | ui->horizontalScrollBar->setValue(qRound(range.center()*100.0)); // adjust position of scroll bar slider
102 | ui->horizontalScrollBar->setPageStep(qRound(range.size()*100.0)); // adjust size of scroll bar slider
103 | }
104 |
105 | void MainWindow::yAxisChanged(QCPRange range)
106 | {
107 | ui->verticalScrollBar->setValue(qRound(-range.center()*100.0)); // adjust position of scroll bar slider
108 | ui->verticalScrollBar->setPageStep(qRound(range.size()*100.0)); // adjust size of scroll bar slider
109 | }
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/mainwindow.h:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #ifndef MAINWINDOW_H
27 | #define MAINWINDOW_H
28 |
29 | #include
30 | #include "../../qcustomplot.h"
31 |
32 | namespace Ui {
33 | class MainWindow;
34 | }
35 |
36 | class MainWindow : public QMainWindow
37 | {
38 | Q_OBJECT
39 |
40 | public:
41 | explicit MainWindow(QWidget *parent = 0);
42 | ~MainWindow();
43 |
44 | void setupPlot();
45 |
46 | private slots:
47 | void horzScrollBarChanged(int value);
48 | void vertScrollBarChanged(int value);
49 | void xAxisChanged(QCPRange range);
50 | void yAxisChanged(QCPRange range);
51 |
52 | private:
53 | Ui::MainWindow *ui;
54 | };
55 |
56 | #endif // MAINWINDOW_H
57 |
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 469
10 | 357
11 |
12 |
13 |
14 | QCustomPlot Scrollbar Axis Range Control Demo
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 0
23 | 0
24 |
25 |
26 |
27 |
28 | -
29 |
30 |
31 | Qt::Vertical
32 |
33 |
34 |
35 | -
36 |
37 |
38 | Qt::Horizontal
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Insert Plot
48 |
49 |
50 |
51 |
52 | Save Document...
53 |
54 |
55 |
56 |
57 |
58 |
59 | QCustomPlot
60 | QWidget
61 |
62 | 1
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/examples/scrollbar-axis-range-control/scrollbar-axis-range-control.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2013-07-25T20:43:22
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
10 |
11 | TARGET = scrollbar-axis-range-control
12 | TEMPLATE = app
13 |
14 |
15 | SOURCES += main.cpp\
16 | mainwindow.cpp \
17 | ../../qcustomplot.cpp
18 |
19 | HEADERS += mainwindow.h \
20 | ../../qcustomplot.h
21 |
22 | FORMS += mainwindow.ui
23 |
--------------------------------------------------------------------------------
/examples/text-document-integration/.gitignore:
--------------------------------------------------------------------------------
1 | text-document-integration
2 |
--------------------------------------------------------------------------------
/examples/text-document-integration/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/examples/text-document-integration/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #include "mainwindow.h"
27 | #include "ui_mainwindow.h"
28 |
29 | MainWindow::MainWindow(QWidget *parent) :
30 | QMainWindow(parent),
31 | ui(new Ui::MainWindow)
32 | {
33 | ui->setupUi(this);
34 | connect(ui->cbUseCurrentSize, SIGNAL(toggled(bool)), ui->sbWidth, SLOT(setDisabled(bool)));
35 | connect(ui->cbUseCurrentSize, SIGNAL(toggled(bool)), ui->sbHeight, SLOT(setDisabled(bool)));
36 |
37 | ui->plot->axisRect()->setMinimumSize(300, 180);
38 | setupPlot();
39 |
40 | // register the plot document object (only needed once, no matter how many plots will be in the QTextDocument):
41 | QCPDocumentObject *plotObjectHandler = new QCPDocumentObject(this);
42 | ui->textEdit->document()->documentLayout()->registerHandler(QCPDocumentObject::PlotTextFormat, plotObjectHandler);
43 | }
44 |
45 | MainWindow::~MainWindow()
46 | {
47 | delete ui;
48 | }
49 |
50 | void MainWindow::setupPlot()
51 | {
52 | // The following plot setup is taken from the sine demo:
53 | // add two new graphs and set their look:
54 | ui->plot->addGraph();
55 | ui->plot->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph
56 | ui->plot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
57 | ui->plot->addGraph();
58 | ui->plot->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph
59 | // generate some points of data (y0 for first, y1 for second graph):
60 | QVector x(250), y0(250), y1(250);
61 | for (int i=0; i<250; ++i)
62 | {
63 | x[i] = i;
64 | y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosine
65 | y1[i] = qExp(-i/150.0); // exponential envelope
66 | }
67 | // configure right and top axis to show ticks but no labels:
68 | // (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
69 | ui->plot->xAxis2->setVisible(true);
70 | ui->plot->xAxis2->setTickLabels(false);
71 | ui->plot->yAxis2->setVisible(true);
72 | ui->plot->yAxis2->setTickLabels(false);
73 | // make left and bottom axes always transfer their ranges to right and top axes:
74 | connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->xAxis2, SLOT(setRange(QCPRange)));
75 | connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->yAxis2, SLOT(setRange(QCPRange)));
76 | // pass data points to graphs:
77 | ui->plot->graph(0)->setData(x, y0);
78 | ui->plot->graph(1)->setData(x, y1);
79 | // let the ranges scale themselves so graph 0 fits perfectly in the visible area:
80 | ui->plot->graph(0)->rescaleAxes();
81 | // same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
82 | ui->plot->graph(1)->rescaleAxes(true);
83 | // Note: we could have also just called customPlot->rescaleAxes(); instead
84 | // Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
85 | ui->plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
86 | }
87 |
88 | void MainWindow::on_actionInsert_Plot_triggered()
89 | {
90 | QTextCursor cursor = ui->textEdit->textCursor();
91 |
92 | // insert the current plot at the cursor position. QCPDocumentObject::generatePlotFormat creates a
93 | // vectorized snapshot of the passed plot (with the specified width and height) which gets inserted
94 | // into the text document.
95 | double width = ui->cbUseCurrentSize->isChecked() ? 0 : ui->sbWidth->value();
96 | double height = ui->cbUseCurrentSize->isChecked() ? 0 : ui->sbHeight->value();
97 | cursor.insertText(QString(QChar::ObjectReplacementCharacter), QCPDocumentObject::generatePlotFormat(ui->plot, width, height));
98 |
99 | ui->textEdit->setTextCursor(cursor);
100 | }
101 |
102 | void MainWindow::on_actionSave_Document_triggered()
103 | {
104 | QString fileName = QFileDialog::getSaveFileName(this, "Save document...", qApp->applicationDirPath(), "*.pdf");
105 | if (!fileName.isEmpty())
106 | {
107 | QPrinter printer;
108 | printer.setFullPage(true);
109 | printer.setPaperSize(QPrinter::A4);
110 | printer.setOrientation(QPrinter::Portrait);
111 | printer.setOutputFormat(QPrinter::PdfFormat);
112 | printer.setOutputFileName(fileName);
113 | ui->textEdit->document()->print(&printer);
114 | }
115 | }
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/examples/text-document-integration/mainwindow.h:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #ifndef MAINWINDOW_H
27 | #define MAINWINDOW_H
28 |
29 | #include
30 | #include
31 | #include
32 | #include "qcpdocumentobject.h"
33 |
34 | namespace Ui {
35 | class MainWindow;
36 | }
37 |
38 | class MainWindow : public QMainWindow
39 | {
40 | Q_OBJECT
41 |
42 | public:
43 | explicit MainWindow(QWidget *parent = 0);
44 | ~MainWindow();
45 |
46 | void setupPlot();
47 |
48 | private slots:
49 | void on_actionInsert_Plot_triggered();
50 | void on_actionSave_Document_triggered();
51 |
52 | private:
53 | Ui::MainWindow *ui;
54 | };
55 |
56 | #endif // MAINWINDOW_H
57 |
--------------------------------------------------------------------------------
/examples/text-document-integration/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 786
10 | 440
11 |
12 |
13 |
14 | QCustomPlot Document Insertion Demo
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 400
23 | 0
24 |
25 |
26 |
27 |
28 | -
29 |
30 |
-
31 |
32 |
33 |
34 | 0
35 | 0
36 |
37 |
38 |
39 |
40 | -
41 |
42 |
-
43 |
44 |
45 | <html><head/><body><p>Size of plot<br/>in document:</p></body></html>
46 |
47 |
48 |
49 | -
50 |
51 |
52 |
53 | 0
54 | 0
55 |
56 |
57 |
58 | 1
59 |
60 |
61 | 9999
62 |
63 |
64 | 480
65 |
66 |
67 |
68 | -
69 |
70 |
71 | x
72 |
73 |
74 |
75 | -
76 |
77 |
78 |
79 | 0
80 | 0
81 |
82 |
83 |
84 | 1
85 |
86 |
87 | 9999
88 |
89 |
90 | 340
91 |
92 |
93 |
94 | -
95 |
96 |
97 | Use current
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | TopToolBarArea
110 |
111 |
112 | false
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | Insert Plot
121 |
122 |
123 |
124 |
125 | Save Document...
126 |
127 |
128 |
129 |
130 |
131 |
132 | QCustomPlot
133 | QWidget
134 |
135 | 1
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/examples/text-document-integration/qcpdocumentobject.cpp:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #include "qcpdocumentobject.h"
27 |
28 | QCPDocumentObject::QCPDocumentObject(QObject *parent) :
29 | QObject(parent)
30 | {
31 | }
32 |
33 | QSizeF QCPDocumentObject::intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format)
34 | {
35 | Q_UNUSED(doc)
36 | Q_UNUSED(posInDocument)
37 | QPicture pic = qvariant_cast(format.property(PicturePropertyId));
38 | if (pic.isNull())
39 | {
40 | qDebug() << Q_FUNC_INFO << "Plot object is empty";
41 | return QSizeF(10, 10);
42 | } else
43 | return QSizeF(pic.boundingRect().size());
44 | }
45 |
46 | void QCPDocumentObject::drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format)
47 | {
48 | Q_UNUSED(doc)
49 | Q_UNUSED(posInDocument)
50 | QPicture pic = qvariant_cast(format.property(PicturePropertyId));
51 | if (pic.isNull())
52 | return;
53 |
54 | QSize finalSize = pic.boundingRect().size();
55 | finalSize.scale(rect.size().toSize(), Qt::KeepAspectRatio);
56 | double scaleFactor = finalSize.width()/(double)pic.boundingRect().size().width();
57 | painter->save();
58 | painter->scale(scaleFactor, scaleFactor);
59 | painter->setClipRect(rect);
60 | painter->drawPicture(rect.topLeft(), pic);
61 | painter->restore();
62 | }
63 |
64 | QTextCharFormat QCPDocumentObject::generatePlotFormat(QCustomPlot *plot, int width, int height)
65 | {
66 | QPicture picture;
67 | QCPPainter qcpPainter;
68 | qcpPainter.begin(&picture);
69 | plot->toPainter(&qcpPainter, width, height);
70 | qcpPainter.end();
71 |
72 | QTextCharFormat result;
73 | result.setObjectType(QCPDocumentObject::PlotTextFormat);
74 | result.setProperty(QCPDocumentObject::PicturePropertyId, QVariant::fromValue(picture));
75 | return result;
76 | }
77 |
--------------------------------------------------------------------------------
/examples/text-document-integration/qcpdocumentobject.h:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | ** **
3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 | ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 | ** **
6 | ** This program is free software: you can redistribute it and/or modify **
7 | ** it under the terms of the GNU General Public License as published by **
8 | ** the Free Software Foundation, either version 3 of the License, or **
9 | ** (at your option) any later version. **
10 | ** **
11 | ** This program is distributed in the hope that it will be useful, **
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
14 | ** GNU General Public License for more details. **
15 | ** **
16 | ** You should have received a copy of the GNU General Public License **
17 | ** along with this program. If not, see http://www.gnu.org/licenses/. **
18 | ** **
19 | ****************************************************************************
20 | ** Author: Emanuel Eichhammer **
21 | ** Website/Contact: http://www.qcustomplot.com/ **
22 | ** Date: 27.12.14 **
23 | ** Version: 1.3.0 **
24 | ****************************************************************************/
25 |
26 | #ifndef QCPDOCUMENTOBJECT_H
27 | #define QCPDOCUMENTOBJECT_H
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include "../../qcustomplot.h"
35 |
36 | class QCPDocumentObject : public QObject, public QTextObjectInterface
37 | {
38 | Q_OBJECT
39 | Q_INTERFACES(QTextObjectInterface)
40 |
41 | public:
42 | enum { PlotTextFormat = QTextFormat::UserObject + 3902 }; // if your application already uses the id (QTextFormat::UserObject + 3902), just change the id here
43 | enum { PicturePropertyId = 1 };
44 |
45 | explicit QCPDocumentObject(QObject *parent = 0);
46 | QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format);
47 | void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
48 |
49 | static QTextCharFormat generatePlotFormat(QCustomPlot *plot, int width=0, int height=0);
50 |
51 | };
52 | Q_DECLARE_METATYPE(QPicture)
53 |
54 | #endif // QCPDOCUMENTOBJECT_H
55 |
--------------------------------------------------------------------------------
/examples/text-document-integration/text-document-integration.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2013-07-06T18:51:44
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
10 |
11 | TARGET = text-document-integration
12 | TEMPLATE = app
13 |
14 |
15 | SOURCES += main.cpp\
16 | mainwindow.cpp \
17 | qcpdocumentobject.cpp \
18 | ../../qcustomplot.cpp
19 |
20 | HEADERS += mainwindow.h \
21 | qcpdocumentobject.h \
22 | ../../qcustomplot.h
23 |
24 | FORMS += mainwindow.ui
25 |
--------------------------------------------------------------------------------