Difference between revisions of "GUI toolkit notes"

From Helpful
Jump to: navigation, search
m (Connections: Slots and signals)
m (Simple and complex types, files, and helpers)
 
Line 432: Line 432:
 
* QPoint QPointF QLine QLineF QRect QRectF QSize QSizeF
 
* QPoint QPointF QLine QLineF QRect QRectF QSize QSizeF
  
* QThread QWaitCondition QMutex QMutexLocker QSemaphore QReadLocker QWriteLocker QReadWriteLock  
+
* QThread QWaitCondition QMutex QMutexLocker QSemaphore QReadLocker QWriteLocker QReadWriteLock QProcess
QProcess
+
<!--QThreadPool-->
  
 
====Unsorted====
 
====Unsorted====

Latest revision as of 00:23, 27 June 2020

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)
This hasn't been updated for a while, so could be outdated (particularly if it's about something that evolves constantly, such as software).


Overview

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


High level / fuller-featured

Qt

cross-platform (win, lin, osx)
Comparable to GTK/Clutter in cleanliness and widget set.
has its own widget set it draws; ignores native look, opting instead to look consistent across playforms (while trying to draw it as low-level as it can, for speed)
comes with a a respectable class library (including networking, etc; this functionality can occasionally be a boon in crossplatform programming)
commercial applications need a (paid) license, or choose to play by GPL.


GTK (formerly GTK+, GIMP Toolkit)

originally developed to replace Motif backend that GIMP used at the time.
became the basis of GNOME desktop
cross-platform (win, lin, osx)
LGPL license.
Related:
Clutter[1] is basically hardware accelerated GNOME-style GUI
Cogl[2] is a lower-level set of useful tools, used to implement Clutter.


WxWidgets

cross-platform (win, lin, osx)
Basically 'the third modern good choice'
LGPL license


Lightweight

Tk [3]

crossplatform (win, lin, osx)
minimal, considered almost as dead in the water as (the X-only) Motif
Comes with Python (tkinter wrapper), so if you use/teach python, Tk gives a quick-and-dirty GUI with a few lines and no further installs
(Tk was also included with tcl, which is its own programming language, that you may have little use for)

FLTK [4]

crossplatform (win, lin, osx)
lightweight enough to be sensible to statically link
Unrelated to tk(verify)


See also:



Web style

There are various frameworks that basically let you do HTML/JS/CSS style interfaces within a desktop app. Some of them are little more than standalone hosting, some of them also take care to make it easier to interface with more other code, like node stuff, or native code.

Electron



Java

Java, plus Swing, or AWT, or SWT, is one of the simplest options to get a GUI across many platforms, but is neither very fast or fancy, though that varies with which GUI choice you make, and it ties to you to only use Java code.

AWT (Abstract Widget Toolit)

Swing (by Sun)

SWT (Standard Widget Toolkit) (by IBM)


SWT versus Swing:

  • SWT can render faster, but its use of JNI may mean that larger-scale data transfer and/or frequent data updates incur more lag.
  • SWT can be harder to extend (though this is not that commonly needed)
  • Swing is part of Java, SWT is not (and since it relies on native code, it must be ported to every platform. It exists for all major platforms, of course)



Qt and PyQt notes

Models, Views and Delegates

Qt is a model-view type of system supported by event signaling.

Models are classes that provide data to view,
while views are GUI elements that mediate layout, painting, model editing.
Delegates are the code that do the view's actual work.
Communication between these elements is done via signals and slots.

Most of this is faily readable and easy to handle, though becomes slightly more code-intensive when you start writing your own models, view, slots and/or delegates.


Views may store selections (based on QItemSelectionModel), which are sensibly updated collections of model indices. The view-side selection model may be shared between views (note this may not always make so much visual sense with different types of and with custom views)


Models

You won't need abstract models when the provided models do what you want. If they don't, see creating new models. The basic model inheritance:

  • QAbstractItemModel (inherits only from QObject)
    • QStandardItemModel
    • QAbstractListModel
      • QStringListModel (list of QStrings)
    • QDirModel (filesystem)
    • QAbstractProxyModel
      • QSortFilterProxyModel
    • QAbstractTableModel
      • QSqlQueryModel (read-only)
        • QSqlTableModel (read-write)
          • QSqlRelationalTableModel (supports foreign keys)

Indices to items: accessing the Model

Model data (internally made of QVariant, a union of Qt types) is stored in a sparse, optionally nested structure that has conventions and functions to make it look like a list, table or tree (see [6]). For example:

toplevelthing = QModelIndex(0,0,QModelIndex())  //row 0, column 0, top-level
sub1          = QModelIndex(0,0,toplevelthing)  //row 0, column 0 child of the thing indexed aboce
                            //this would likely representing a tree
//Or in this style:
sub2 = model->index(1,0,toplevelthing)
 
model->data(sub1);           //get data. Optional role parameter defaults to DisplayRole
model->setData(sub2, value); //set data. Optional role parameter defaults to EditRole

A QModelIndex (introduced to separate view from the data; only the model needs to know how to access the data) may have a valid row(), column() or parent() yielding another QModelIndex. It will return an invalid index (also what QModelIndex() without parameters generates) to mean first or root element.

Note that if a model chooses to reorganize (will likely happen for a filesystem model), QModelIndex may refer to another item or become invalid (and therefore likely refer to a top item). In this case, you could wish to use QPersistentModelIndex which will last as long as the model. (Note that the view will change anyway)


Data contain a few types of state. They can for example be individually flagged (in the model) to be draggable and/or be drop targets (see also [7]).

Items will often be text, but be represented in the view with widgets like perhaps checkboxes, etc. ((verify) how).


Roles

An model's data items may contain information representable in multiple conceptual domains.

  • minimal items have only a DisplayRole (the data viewed, often text), but items may may also include
  • an EditRole (the data suited for the edit widget),
  • Help details like a StatusTipRole, ToolTipRole and WhatsThisRole
  • a DecorationRole (e.g. a color)
  • GUI details like SizeHintRole, FontRole, FontColorRole, etc.

See [8] for a list.

Note: roles may refer to different parts of data, or be views on it.

Views

Those models can back the three main views. Data is fetched from an enumeration imposed on the data model, which separates data from GUI addressing (a good thing, really) and makes different data models minimally compatible (e.g. a tree model will show the top level elements in a list and table). The classes:

  • QAbstractItemView
    • HeaderView
    • QListView
      • (QListWidget (contains instantiations of QListWidgetItem))
    • QTableView
      • (QTableWidget (contains instantiations of QTableWidgetItem))
    • QTreeView
      • (QTreeWidget (contains instantiations of QTreeWidgetItem. See also QTreeWidgetItemIterator))

Avoid these *Widgets (and their respective *WidgetItems - though note model-view also talks about items of data); they are Qt3-style interfaces provided for easy forwards porting (reimplemented for Qt4-style model-view). They have more decisions than in views and as such are apparently not as flexibly linkable with models, nor as fast. (verify) Use Model-view for anything new you write.

Delegates

For read-only views:

  • On change, model signals view that data changed.
    • On need to paint, triggers delegate to do so.
    • View will most likely trigger delegate to fetch data, and realize it needs to repaint

For editable views, also:

  • On some event, trigger delegate to create temporary edit widget (note: cleaned by the view)
  • On edit: trigger delegate, which changes model

Things have sensible default delegates. When you want custom behaviour, such as editing table elements, you subclass QItemDelegate (assuming you want some default functions, otherwise you can subclass QAbstractItemDelegate) to create an editable widget on-demand (automatically cleaned by the view).

Connections: Slots and signals

A connection is a one-way signal from one QObject to another QObject, that does not require an object to know details about the other object. Think event relayers, message handlers.

They also work between QThreads, but note they are are always executed in the calling thread.


Signals send messages, slots receive them. They are connected with e.g.:

QObject::connect( quitButton,  SIGNAL(clicked()), 
                  app,         SLOT(quit()) );
 
QObject::connect( scroll,      SIGNAL(valueChanged(int)),
                  label,       SLOT(setNum(int)) );

Connections are many-to-many in that

a SIGNAL can connect to many SLOTs (called in an undefined order), and
a slot can have multiple signals going to it.

connect returns false when the connection cannot be made.


The syntax, SIGNAL, SLOT, and the ability to define a signal: section (a la private: and public:) is not straight C++. You use an extra header preparser, moc.

Example code

Simple app (C++)

#include <QtCore/QDir.h>
#include <QtGui/QApplication.h>
#include <QtGui/QSplitter.h>
#include <QtGui/QDirModel.h>
#include <QtGui/QTreeView.h>
#include <QtGui/QListView.h>
 
int main(int argc, char *argv[]) 
{
    QApplication app(argc, argv);
    QDirModel *dirModel = new QDirModel;
 
    QSplitter *splitter = new QSplitter;
    QTreeView *treeView = new QTreeView(splitter);
    QListView *listView = new QListView(splitter);
 
    treeView->setModel(dirModel);
    listView->setModel(dirModel);
 
    treeView->setRootIndex( dirModel->index( QDir::currentPath() ) );
    listView->setRootIndex( dirModel->index( QDir::currentPath() ) );
 
    splitter->setWindowTitle("A list and tree view of the current dir");
    splitter->resize(600, 400);
    app.setActiveWindow(splitter);
    splitter->show();
    return app.exec();
}

Link this with QtCore4 and QtGui4.

More complex example (PyQt)

Uses connections, multiple views on a single model, and synchronized selection between views.

import sys
from PyQt4.QtCore import Qt,QDir,QObject,QString,SIGNAL,SLOT
from PyQt4.QtGui  import QApplication,QDirModel,QSplitter,QListView,QTreeView,QTableView,QPushButton
 
app = QApplication(sys.argv)
dirModel  = QDirModel()
 
# Make something like:
#  ____  ____  ____
# |view||view||view|
# |____||____||____|
# |__b_u_t_t_o_n___|
#
 
# Splits top-bottom first.
vsplitter=QSplitter()
vsplitter.setOrientation( Qt.Vertical )
 
#Top pane has the three views, split horizontally
hsplitter = QSplitter(  vsplitter )
listView  = QListView(  hsplitter )
treeView  = QTreeView(  hsplitter )
tableView = QTableView( hsplitter )
 
# ...set all three to view the same directory model
listView.setModel(  dirModel )
treeView.setModel(  dirModel )
tableView.setModel( dirModel )
 
#(I forget exactly what this was for. Consistent item indexing, perhaps?)
treeView.setRootIndex(  dirModel.index( QDir.currentPath() ) )
listView.setRootIndex(  dirModel.index( QDir.currentPath() ) )
tableView.setRootIndex( dirModel.index( QDir.currentPath() ) )
 
#Synchronize *selection* between views as well
listView.setSelectionModel(  treeView.selectionModel() );
tableView.setSelectionModel( treeView.selectionModel() );
 
 
#Bottom pane of the vertical split just has a big quit button
quit=QPushButton(QString("Quit"),vsplitter)
#The button executes the quit function
QObject.connect( quit,SIGNAL("clicked()") ,
                 app, SLOT("quit()") )
 
#Window details (vsplitter is effectively the window itself)
vsplitter.setWindowTitle("Three selection-synched views of the current dir")
vsplitter.resize(600, 400)
app.setActiveWindow(vsplitter) #this may be implied by not giving it a parent, verify.
vsplitter.show()
 
sys.exit( app.exec_() )

Note: You probably want to import a lot of classes instead of mentioning QtGui and QtCore all the time. Don't import *, though, it's rather bad style and slow)

Other notes

The basic object you need is a QApplication. Creating more than one is probably bad (in PyQt it's accessible as QtCore.qApp (if you forget the reference)) It is usual to make the main loop's result the process' return value. Since the main loop blocks, this tends to be the last line in the program.


GUI trees are constructed mentioning the parent in the widget's constructor. You mention a widget's parent widget in the constructor (0 in C++ and None in Python implies being/assigning a top?(verify). Interestingly, this means C++ memory management is made simpler: Deleting a widget (possibly any QObject-derivative(verify)) means all its children are recursively deleted - so you only need to keep track of your roots to clean up the Qt.

Designing

The commercial version of Qt4 has Visual Studio integration [9], e.g. a designer and dynamic help.


Qt-aware (to some degree) IDEs you can use include eric3 (written in PyQt; should be crossplatform but seems to not yet play nice with PyQt4), KDevelop, and others.


In general it is assumed you want to build the forms separately from your usual coding environment. 'Qt Designer' (I prever its docked mode, by the way) is a form designer that outputs .ui files, which you can convert to C++ (using uic) and PyQt code (using pyuic) - code without real logic, of course.

You can actually let Qt process .ui files itself using QUiLoader (example ).


When you write from code in C++, you may likely use some Qt features like custom signals, introspection and macros like Q_OBJECT and properties, which means you have run moc (the Meta Object Compiler, a preprocessor) on headers with these features in your build step.

tr

Qt includes internationalization helpers. Instead of constructing widgets with fixed-text labels e.g.

QTableWidgetItem *things = new QTableWidgetItem(QString("Things"));
#Instead do:
QTableWidgetItem *things = new QTableWidgetItem(tr("Things"));

The tr function allows translation into the current(verify) language, based on provided translation data. The string you hand tr is basically a key for lookup - though it's obviously useful if you can read it.

TODO: Figure out what's behind this, exactly.

Unsorted

  • properties.
  • A QObject's ->metaObject() (returns a QMetaObject) contains information like object name, property, signal, slot, and superclass information. See also 'The Qt object model'

Rough sorting of core and GUI classes/interfaces

Not guaranteed to not contain strange misplaced items. Note that some naming changed in Qt4 and PyQt4. See also e.g.:


QtGui

Widgets, layouting, dialogues

  • Concepts: QFrame QFocusFrame QDialog QWidget QWidgetItem QWorkspace QDesktopWidget QMainWindow
  • Dialogs: QFileDialog QMessageBox QErrorMessage QInputDialog QTextEdit QTimeEdit QDateEdit QDateTimeEdit QProgressDialog QSplashScreen QTextBrowser
  • Basic: QLabel QLineEdit QPushButton QComboBox QButtonGroup QCheckBox QRadioButton QSpinBox QDial QLCDNumber QProgressBar QSlider QDoubleSpinBox
  • Item-based: QListView QMatrix QTableView QTableWidget QTableWidgetSelectionRange QListWidget QHeaderView QListWidgetItem QTableWidgetItem QTreeViewQTreeWidgetItemIterator QTreeWidget QTreeWidgetItem
  • Layouting/structuring: QSpacerItem QSplitter QSplitterHandle QScrollBar QScrollArea QToolTip QWhatsThis QLayout QLayoutItem QBoxLayout QStackedLayout QStackedWidget QHBoxLayout QVBoxLayout QGridLayout QSizePolicy QTabWidget QTabBar QGroupBox QSizeGrip
  • Also common: QDockWidget QMenu QMenuBar QStatusBar QAction QActionGroup QToolBar QToolBox QToolButton

Events, interaction

  • Global or window events: QWindowStateChangeEvent QShowEvent QHideEvent QMoveEvent QResizeEvent QCloseEvent QFileOpenEvent QHelpEvent QStatusTipEvent QWhatsThisClickedEvent QContextMenuEvent QPaintEvent
  • User events: QInputEvent QKeyEvent QKeySequence QTabletEvent QWheelEvent QMouseEvent QDragEnterEvent QDragLeaveEvent QDrag QDragMoveEvent QIconDragEvent QDropEvent QFocusEvent QHoverEvent QActionEvent QShortcut QShortcutEvent QInputMethodEvent

Graphics, audio

  • Drawing, colors: QBrush QColor QGradient QColorDialog QRadialGradient QLinearGradient QConicalGradient QPaintDevice QPalette QPen QPolygon QPolygonF QPaintEngine QPaintEngineState QPainter QPainterPath qRgb qRgba qGreen qRed qGray qIsGray qAlpha qBlue
  • Images, icons: QImage QImageReader QImageWriter QBitmap QPicture QPictureIO QPixmap QPixmapCache QIcon QIconEngine
  • Fonts: QFont QFontDatabase QFontDialog QFontInfo QFontMetrics QFontMetricsF
  • Audiovisual: QMovie QSound

Interfaces, Models

  • QItemSelection QItemSelectionModel QItemSelectionRange QItemDelegate QItemEditorCreatorBase QItemEditorFactory QStandardItemModel
  • QValidator QRegExpValidator QIntValidator QDoubleValidator
  • QInputContext QAbstractItemDelegate QAbstractItemView QAbstractPrintDialog QAbstractProxyModel QAbstractScrollArea QAbstractSlider QAbstractSpinBox QAbstractTextDocumentLayout QDirModel QFileIconProvider QStringListModel
  • QMimeSource QSessionManager QSortFilterProxyModel

QProxyModel

Look and feel

  • QStyle QStyleFactory QStyleHintReturn QStyleHintReturnMask QStyleOption QStyleOptionButton QStyleOptionComboBox QStyleOptionComplex QStyleOptionDockWidget QStyleOptionFocusRect QStyleOptionFrame QStyleOptionFrameV2 QStyleOptionGroupBox QStyleOptionHeader QStyleOptionMenuItem QStyleOptionProgressBar QStyleOptionProgressBarV2 QStyleOptionRubberBand QStyleOptionSlider QStyleOptionSpinBox QStyleOptionTab QStyleOptionTabBarBase QStyleOptionTabV2 QStyleOptionTabWidgetFrame QStyleOptionTitleBar QStyleOptionToolBar QStyleOptionToolBox QStyleOptionToolButton QStyleOptionViewItem

General/Other/Unsorted

  • QApplication QClipboard QSyntaxHighlighter QCursor QRegion QRubberBand QPageSetupDialog QPrintDialog QPrintEngine QPrinter
  • qApp qDrawPlainRect qDrawShadeLine qDrawShadePanel qDrawShadeRect qDrawWinButton qDrawWinPanel
  • QTextBlock QTextFormat QTextBlockFormat QTextBlockGroup QTextBlockUserData QTextCharFormat QTextFrameFormat QTextCursor QTextImageFormat QTextDocument QTextFragment QTextDocumentFragment QTextFrame QTextInlineObject QTextOption QTextLength
  • QTextLayout QTextLine
  • QTextItem QTextObject QTextList QTextListFormat
  • QTextTable QTextTableCell QTextTableFormat

QtCore

Simple and complex types, files, and helpers

  • QChar QString QStringList QStringMatcher QRegExp QLatin1Char QLatin1String QLocale QTextCodec QTranslator QTextDecoder QTextEncoder QTextStream QTextStreamManipulator
  • QCString qstrcmp qstrcpy qstrdup qstricmp qstrlen qstrncmp qstrncpy qstrnicmp qSetPadChar
  • QVector QBitArray QByteArray QByteArrayMatcher QBuffer QDataStream QMimeData qChecksum qCompress qUncompress
  • qFuzzyCompare qRound qRound64 qSetRealNumberPrecision (floating point helpers)
  • QFile QTemporaryFile QFileInfo QDir QIODevice QAbstractFileEngine QFSFileEngine QAbstractFileEngineHandler
  • QUrl QUuid
  • QTime QDate QDateTime
  • QTimer QBasicTimer QTimerEvent
  • QPoint QPointF QLine QLineF QRect QRectF QSize QSizeF
  • QThread QWaitCondition QMutex QMutexLocker QSemaphore QReadLocker QWriteLocker QReadWriteLock QProcess

Unsorted

  • QAbstractItemModel QAbstractListModel QAbstractTableModel
  • QModelIndex QPersistentModelIndex
  • QtMsgType QtCriticalMsg QtDebugMsg QtFatalMsg QtSystemMsg QtWarningMsg qDebug qWarning qErrnoWarning qCritical qFatal qInstallMsgHandler
  • QEvent QEventLoop QChildEvent

QVariant QObject QObjectCleanupHandler QSignalMapper QAbstractEventDispatcher QSocketNotifier Qt QCoreApplication QLibrary QLibraryInfo QSysInfo QPluginLoader QSettings QMetaClassInfo QMetaEnum QMetaMethod QMetaObject QMetaProperty qIsNull qUnregisterResourceData qRegisterResourceData qSetFieldWidth qSharedBuild qVersion qAddPostRoutine qRemovePostRoutine MSG POINT QT_TRANSLATE_NOOP QT_TR_NOOP QT_VERSION QT_VERSION_STR SIGNAL SLOT


See also