explain :PyQt API contain 400 Multiple classes . QObject Class at the top of the class hierarchy . Some common and practical knowledge points need to be mastered first , This article will show some common points .
QObject Class at the top of the class hierarchy . It's all Qt Object's base class . Besides ,QPaintDevice Class is the base class for all paintable objects . therefore :
QApplication Class management GUI The main setup and control flow of the application . It contains the main event loop , In which events generated by window elements and other sources are processed and scheduled . It also handles system wide and application wide settings .
QWidget class , Derive from QObject and QPaintDevice class , Is the base class for all user interface objects . QDialog and QFrame Class is also derived from QWidget class . They have their own subclass system .
The following figure describes some important classes in its hierarchy .
QLabel
Used to display text or image
2QLineEdit
Allows the user to enter one line of text
3QTextEdit
Allows the user to enter multi-line text
4QPushButton
A command button to invoke action
5QRadioButton
Enables to choose one from multiple options
6QCheckBox
Enables choice of more than one options
7QSpinBox
Enables to increase/decrease an integer value
8QScrollBar
Enables to access contents of a widget beyond display aperture
9QSlider
Enables to change the bound value linearly.
10QComboBox
Provides a dropdown list of items to select from
11QMenuBar
Horizontal bar holding QMenu objects
12QStatusBar
Usually at bottom of QMainWindow, provides status information.
13QToolBar
Usually at top of QMainWindow or floating. Contains action buttons
14QListView
Provides a selectable list of items in ListMode or IconMode
15QPixmap
Off-screen image representation for display on QLabel or QPushButton object
16QDialog
Modal or modeless window which can return information to parent window
A typical based on GUI The top-level window of the application is composed of QMainWindow Widget object creation . Some of the widgets listed above occupy specified positions in this main window , Other widgets are placed in the central widget area using various layout managers .
The image below shows QMainWindow frame -
Qt The following categories of main window management and related user interface components are provided :
Qt The foundation of the GUI is QWidget.Qt All types of GUI Components such as buttons 、 label 、 Toolbars, etc. are derived from QWidget, and QWidget Itself is QObject Subclasses of .Widget Responsible for receiving the mouse , Keyboard and other events from the window system , And depicted itself on the screen . every last GUI The components are all one widget,widget It can also be used as a container , Include other Widget.
QWidget Not an abstract category . And can be placed in an existing user interface ; if Widget No parent specified Widget, When it is displayed, it is a separate window 、 Or a top floor widget.QWidget Display capabilities include transparency and Double-Buffering.Qt Provide a hosting mechanism , When Widget Specify the parent object when creating , You can hand over your life cycle to the upper level object management , When the upper object is released , I was also released . Ensure that objects are deleted when they are no longer in use .
Here is one QGraphicsView Example , Realize the sliding form effect , Toolbars and pictures are all in the scene Item.
QGraphicsView Used to display a scrolling view area QGraphicsScene Content .QGraphicsScene Provides QGraphicsItem The container function of . Usually with QGraphicsView Used together to describe visual graphics projects .
QGraphicsScene Provides a view of the scene , By adding different QGraphicsItem To build the view . and QGraphicsView It provides a widget To display QGraphicsScene The content of . So to successfully build a view , These three elements work together , Composite whole .
Qt Using signals and slots (signals/slots) Mechanism replaces traditional callback To communicate between objects . When an operation event occurs , Object will send a signal to submit (signal); And groove (slot) Is a function that accepts a specific signal and performs the actions set by the slot itself . Between the signal and the slot , Through QObject Static method of connect To link .
The signal can be transmitted at any execution point , You can even send another signal in the slot , The link between signal and slot is not limited to one-to-one link , A signal can be linked to multiple slots or multiple signals can be linked to the same slot , Even signals can be connected to signals .
In the past callback Lack of type safety , When calling a handler , Unable to determine whether the correct type of parameter was passed . But the type of data transmitted between the signal and the slot it receives must match , Otherwise, the compiler will warn . Any number of signals and slots can be accepted 、 Any type of parameter , So the signal and slot mechanism is completely type safe .
The signal and slot mechanism also ensures low coupling , The type of the transmitted signal does not know which slot will accept , That is, a signal can call all available slots . This mechanism ensures that when " Connect " Signal and slot , The slot will accept the parameters of the signal and execute correctly .
The layout management category is used to describe... In the user interface of an application Widget How to place . When the window zooms , The layout manager automatically adjusts widget Size 、 Location or font size , Ensure that their relative alignment and overall user interface remain available .
Qt The built-in layout management types are :QHBoxLayout、QVBoxLayout、QGridLayout and QFormLayout. These categories are inherited from QLayout, but QLayout Not inherited from QWidget But directly from QObject. They are responsible for widget Geometric management of . Want to create more complex layout configurations , Inherit QLayout Customize the layout configuration Administrator .
[cpp] view plain copy
#include <QtCore>
#include <QtGui>
#include <QtSvg>
/* The program uses svg Format picture , Therefore, it is necessary to include QtSvg*/
#define PAGE_COUNT 5
/* Define the number of sliding forms */
Define toolbars ,NviBar Inherited from QGraphicsRectItem, Usage and QGraphicsItem similar .
[cpp] view plain copy
class NaviBar : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
NaviBar();
void setPageOffset(qreal ofs);
signals:
void pageSelected(int page);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
private:
QList<QGraphicsSvgItem*> m_icons;
QGraphicsRectItem *m_cursor;
};
Function implementation
[cpp] view plain copy
#define ICON_SIZE 50
#define ICON_PAD 4
NaviBar::NaviBar() : QGraphicsRectItem()
{
setRect(0, 0, 5 * ICON_SIZE, ICON_SIZE);
setPen(Qt::NoPen);
QStringList names;
names << "map" << "web" << "home" << "weather" << "contacts";
for (int i = 0; i < names.count(); ++i) {
QString fname = names[i];
fname.prepend(":/icons/");
fname.append("-page.svg");
QGraphicsSvgItem *icon = new QGraphicsSvgItem(fname);
icon->setParentItem(this);
const int dim = ICON_SIZE - ICON_PAD * 2;
qreal sw = dim / icon->boundingRect().width();
qreal sh = dim / icon->boundingRect().height();
icon->setTransform(QTransform().scale(sw, sh));
icon->setZValue(2);
m_icons << icon;
}
m_cursor = new QGraphicsRectItem;
m_cursor->setParentItem(this);
m_cursor->setRect(0, 0, ICON_SIZE, ICON_SIZE);
m_cursor->setZValue(1);
m_cursor->setPen(Qt::NoPen);
m_cursor->setBrush(QColor(Qt::white));
m_cursor->setOpacity(0.6);
}
void NaviBar::setPageOffset(qreal ofs)
{
m_cursor->setPos(ofs * ICON_SIZE, 0);
for (int i = 0; i < m_icons.count(); ++i) {
int y = (i == static_cast<int>(ofs + 0.5)) ? ICON_PAD : ICON_PAD * 2;
m_icons[i]->setPos(i * ICON_SIZE + ICON_PAD, y);
m_icons[i]->setOpacity(1);
}
}
void NaviBar::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
emit pageSelected(static_cast<int>(event->pos().x() / ICON_SIZE));
}
void NaviBar::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setBrush(Qt::white);
painter->setOpacity(0.2);
painter->drawRect(option->rect.adjusted(-20, ICON_PAD, 20, 0));
}
Define views
[cpp] view plain copy
class ParallaxHome: public QGraphicsView
{
Q_OBJECT
public:
QGraphicsScene m_scene;
NaviBar *m_naviBar;
QGraphicsPixmapItem *m_wallpaper;
QTimeLine m_pageAnimator;
qreal m_pageOffset;
QList<QGraphicsPixmapItem*> m_items;
QList<QPointF> m_positions;
public:
ParallaxHome(QWidget *parent = 0)
: QGraphicsView(parent)
, m_pageOffset(-2) {
setupScene();
setScene(&m_scene);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFrameShape(QFrame::NoFrame);
setWindowTitle("Parallax Home");
connect(&m_pageAnimator, SIGNAL(frameChanged(int)), SLOT(shiftPage(int)));
m_pageAnimator.setDuration(500);
m_pageAnimator.setFrameRange(0, 100);
m_pageAnimator.setCurveShape(QTimeLine::EaseInCurve);
pageChanged(static_cast<int>(m_pageOffset));
}
signals:
void pageChanged(int page);
public slots:
void slideRight() {
if (m_pageAnimator.state() != QTimeLine::NotRunning)
return;
int edge = -(m_pageOffset - 1);
if (edge < PAGE_COUNT)
slideBy(-1);
}
void slideLeft() {
if (m_pageAnimator.state() != QTimeLine::NotRunning)
return;
if (m_pageOffset < 0)
slideBy(1);
}
void slideBy(int dx) {
int start = m_pageOffset * 1000;
int end = (m_pageOffset + dx) * 1000;
m_pageAnimator.setFrameRange(start, end);
m_pageAnimator.start();
}
void choosePage(int page) {
if (m_pageAnimator.state() != QTimeLine::NotRunning)
return;
if (static_cast<int>(-m_pageOffset) == page)
return;
slideBy(-page - m_pageOffset);
}
private slots:
void shiftPage(int frame) {
int ww = width();
int hh = height() - m_naviBar->rect().height();
int oldPage = static_cast<int>(-m_pageOffset);
m_pageOffset = static_cast<qreal>(frame) / qreal(1000);
int newPage = static_cast<int>(-m_pageOffset);
m_naviBar->setPageOffset(-m_pageOffset);
if (oldPage != newPage)
emit pageChanged(newPage);
int ofs = m_pageOffset * ww;
for (int i = 0; i < m_items.count(); ++i) {
QPointF pos = m_positions[i];
QPointF xy(pos.x() * ww, pos.y() * hh);
m_items[i]->setPos(xy + QPointF(ofs, 0));
}
int center = m_wallpaper->pixmap().width() / 2;
const int parallax = 3;
int base = center - (ww / 2) - (PAGE_COUNT >> 1) * (ww / parallax);
int wofs = base - m_pageOffset * ww / parallax;
m_wallpaper->setPos(-wofs, 0);
}
protected:
void resizeEvent(QResizeEvent *event) {
Q_UNUSED(event);
layoutScene();
}
void keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Right)
slideRight();
if (event->key() == Qt::Key_Left)
slideLeft();
event->accept();
}
private:
void layoutScene() {
int ww = width();
int hh = height();
m_scene.setSceneRect(0, 0, PAGE_COUNT * ww - 1, hh - 1);
centerOn(ww / 2, hh / 2);
int nw = m_naviBar->rect().width();
int nh = m_naviBar->rect().height();
m_naviBar->setPos((ww - nw) / 2, hh - nh);
shiftPage(m_pageOffset * 1000);
}
void setupScene() {
qsrand(QTime::currentTime().second());
QStringList names;
names << "brownies" << "cookies" << "mussels" << "pizza" << "sushi";
names << "chocolate" << "fish" << "pasta" << "puding" << "trouts";
for (int i = 0; i < PAGE_COUNT * 2; ++i) {
QString fname = names[i];
fname.prepend(":/images/");
fname.append(".jpg");
QPixmap pixmap(fname);
pixmap = pixmap.scaledToWidth(200);
QGraphicsPixmapItem *item = m_scene.addPixmap(pixmap);
m_items << item;
qreal x = (i >> 1) + (qrand() % 30) / 100.0;
qreal y = (i & 1) / 2.0 + (qrand() % 20) / 100.0;
m_positions << QPointF(x, y);
item->setZValue(1);
}
m_naviBar = new NaviBar;
m_scene.addItem(m_naviBar);
m_naviBar->setZValue(2);
connect(m_naviBar, SIGNAL(pageSelected(int)), SLOT(choosePage(int)));
m_wallpaper = m_scene.addPixmap(QPixmap(":/icons/surfacing.png"));
m_wallpaper->setZValue(0);
m_scene.setItemIndexMethod(QGraphicsScene::NoIndex);
}
};
main function
[cpp] view plain copy
#include "parallaxhome.moc"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ParallaxHome w;
w.resize(360, 640);
w.show();
return app.exec();
}