學習進度
week3:
QStringListModel(modelview類)钳吟。model更新時自動更新view汉操。
mylistview.h
#ifndef MYLISTVIEW_H
#define MYLISTVIEW_H
#include<QWidget>
#include<QStringListModel>
#include<QListView>
#include<QHBoxLayout>
#include<QPushButton>
#include<QLineEdit>
#include<QModelIndex>
#include<QMessageBox>
#include<QInputDialog>
class MyListView : public QWidget
{
Q_OBJECT
public:
MyListView();
private:
QStringListModel *model;
QListView *listView;
private slots:
void insertData();
void deleteData();
void showData();
};
#endif // MAINWINDOW_H
mylistview.cpp
#include "mylistview.h"
MyListView::MyListView()
{
model=new QStringListModel(this);//創(chuàng)建model對象
QStringList data;//設置model數(shù)據(jù)
data<<"Letter A"<<"Letter B"<<"Letter C";
model->setStringList(data);//把數(shù)據(jù)設置為model的數(shù)據(jù)
listView=new QListView(this);
listView->setModel(model);//view和model綁定
QHBoxLayout *btnLayout=new QHBoxLayout;
QPushButton *insertBtn=new QPushButton(tr("insert"),this);
QPushButton *delBtn=new QPushButton(tr("delete"),this);
QPushButton *showBtn=new QPushButton(tr("show"),this);
btnLayout->addWidget(insertBtn);
btnLayout->addWidget(delBtn);
btnLayout->addWidget(showBtn);//添加下方按鈕
QVBoxLayout *mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(listView);
mainLayout->addLayout(btnLayout);
this->setLayout(mainLayout);//全局
connect(insertBtn,SIGNAL(clicked()),this,SLOT(insertData()));
connect(delBtn,SIGNAL(clicked()),this,SLOT(deleteData()));
connect(showBtn,SIGNAL(clicked()),this,SLOT(showData()));
}
void MyListView::insertData()
{
bool isOK;
QString text=QInputDialog::getText(NULL,"Insert","Please input new data",QLineEdit::Normal,"you are inserting new data",&isOK);
if(isOK)
{
int row=listView->currentIndex().row();
model->insertRows(row,1);
QModelIndex index=model->index(row);
model->setData(index,text);
listView->setCurrentIndex(index);
listView->edit(index);
}
}
void MyListView::deleteData()
{
if(model->rowCount()>1)
{
model->removeRows(listView->currentIndex().row(),1);//1是在當前行插入的行數(shù)
}
}
void MyListView::showData()
{
QStringList data=model->stringList();
QString str;
foreach(QString s,data)
{
str+=s+"\n";
}
QMessageBox::information(this,"DATA",str);
}
main.cpp
#include "mylistview.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyListView w;
w.show();
return a.exec();
}
QTreeWidget(item class)
main.cpp
#include "treewidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TreeWidget w;
w.show();
return a.exec();
}
treewidget.cpp
#include "treewidget.h"
TreeWidget::TreeWidget()
{
tree=new QTreeWidget(this);
tree->setColumnCount(2);//columnCount是用來在列表中顯示樹的
QTreeWidgetItem *root=new QTreeWidgetItem(tree,QStringList(QString("Root")));
QTreeWidgetItem *leaf=new QTreeWidgetItem(root,QStringList(QString("Leaf 1")));
root->addChild(leaf);
QTreeWidgetItem *leaf2=new QTreeWidgetItem(root,QStringList(QString("Leaf 1")));
leaf2->setCheckState(0,Qt::Checked);
root->addChild(leaf2);
QList<QTreeWidgetItem *>rootList;
rootList<<root;
tree->insertTopLevelItems(0,rootList);
}
treewidget.h
#ifndef TREEWIDGET_H
#define TREEWIDGET_H
#include<QMainWindow>
#include<QWidget>
#include<QTreeWidget>
class TreeWidget : public QWidget
{
public:
TreeWidget();
private:
QTreeWidget *tree;
};
#endif // TREEWIDGET_H
QListWidget(itemclass)
main.cpp
#include <QApplication>
#include<QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ListWidget lw;
lw.resize(400,200);
lw.show();
return a.exec();
}
listWidget.cpp
#include "listWidget.h"
ListWidget::ListWidget()
{
label=new QLabel;
label->setFixedWidth(70);
list=new QListWidget;
list->addItem(tr("line"));
list->addItem(tr("Rect"));
list->addItem(tr("Oval"));
list->addItem(tr("Triangle"));
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label);
layout->addWidget(list);
setLayout(layout);
connect(list,SIGNAL(currentTextChanged(QString)),label,SLOT(setText(QString)));
}
listWidget.h
#ifndef LISTWIDGET_H
#define LISTWIDGET_H
#include <QWidget>
#include<QLabel>
#include<QListWidget>
#include<QHBoxLayout>
class ListWidget : public QWidget
{
public:
ListWidget();
private:
QLabel *label;
QListWidget *list;
};
#endif // LISTWIDGET_H
Qt model-view
不降低性能的前提下處理大量數(shù)據(jù),可以讓一個model注冊給多個view莺褒。少量數(shù)據(jù)時用item view類捉貌。分別是QList(\Table\Tree)Widget。較大數(shù)據(jù)使用QList(\Table\Tree)view镰官,且需要提供
model。
對接
關(guān)聯(lián)存儲器
存儲二元組映射吗货。QMap<K,T>是key-value數(shù)據(jù)結(jié)構(gòu)泳唠,按k升序進行存儲≈姘幔可用insert或[]插入
QMap<QString,int>map笨腥;
map.insert("test1",1);
map.insert("test2",2);
//或
map["test1"]=1;
而取值時,在非const的map中勇垛,[]取不存在的key值會自動創(chuàng)建一個值為空的key脖母。為避免這種查詢時自動插入,可使用:c++map.value(key);
key不存在時會返回0闲孤,對象類型則會調(diào)用默認構(gòu)造函數(shù)谆级,返回一個對象,不創(chuàng)建新的鍵值對。如果需要不存在的鍵返回默認值肥照,可使用c++int seconds = map.value("delay", 30);
QMultiMap一個key索引多個值脚仔。
QHash<K,T>查找速度更快,存儲不排序舆绎,K類型需被qHash()支持玻侥。可用reverse()函數(shù)擴大散列亿蒸,squeeze()壓縮
遍歷方式:
//【Java風格】next()和previous()函數(shù)可以返回一個鍵值對,而不僅僅是值
QMap<QString,int> map;//創(chuàng)建QMap對象map
QMapIterator<QString,int>i(map)//創(chuàng)建map的迭代器i
while(i.hasNext()) sum+=i.next().value()掌桩;
//Mutable遍歷器可以修改key對應的值边锁,如
i.setValue(-i.value());
//【stl風格】,foreach循環(huán)分別對key和value循環(huán)
QMultiMap<QString,int>map;
foreach(QString key,map.keys())
{
foreach(int value,map.values(key))
{
dosth(key,value);
}
}
遍歷器
每個容器都有對應的遍歷器波岛。
只讀遍歷器有:QVectorIterator茅坛,QLinkedListIterator和 QListIterator三種;讀寫遍歷器同樣也有三種则拷,只不過名字中具有一個 Mutable贡蓖,即QMutableVectorIterator,QMutableLinkedListIterator和 QMutableListIterator煌茬。
對list或者vector使用at()進行只讀訪問([]既可以是左值也可以是右值斥铺,而at不能作為左值)
盡量使用const_iterator,constBegin()坛善,constEnd()晾蜘,不然在數(shù)據(jù)改變時Qt會進行深復制。
【Java風格遍歷器】
Java風格的遍歷器不指向元素眠屎,而是指向元素間隙剔交。
//從前向后
QList<double>list;
QListIterator<double>i(list);
while(i.hasNext()){doSomethingWith(i.next());}
//從后向前。toBack()指向最后一個元素的后面的位置改衩,用hasPrevious()和previous()函數(shù)遍歷岖常。
【STL遍歷器】
每個順序容器類都有倆遍歷器:C::iterator和C::const_iterator。后者不允許對數(shù)據(jù)修改葫督。begin和end分別指向第一個和最后一個之后的元素竭鞍。容器為空時begin和end相同(或用isEmpty判斷是否為空)。
可以用++--使遍歷器移動橄镜,返回值是指向這個元素的指針笼蛛。
QList<double>::iterator i=list.begin();
while(i!=list.end())
{
*i=qAbs(*i);++i;
}
如果要使用 STL 風格的遍歷器,并且要遍歷作為返回值的容器蛉鹿,就要先創(chuàng)建返回值的拷貝滨砍,然后進行遍歷(java不用,因為會自動創(chuàng)建拷貝)。
可以通過傳入引用避免對容器的拷貝工作惋戏,防止臨時拷貝占用大量內(nèi)存领追。
順序存儲容器
1.QVector:知道自己長度并且可以改變大小的數(shù)組。如果沒有顯式賦值則自動初始化為0
QVector<double> v(length);
v[pos]=value;//用[]賦值
QVector<double> v;
v.append(value1);
v.append(value1);
QVecor<double>v;//不知道長度响逢,通過append添加
//或使用被重載的<<
v<<value1<<value2;
2.QLinkedList:雙向鏈表绒窑。添加只能用<<和append()
3.QList:除非我們需要進行在很大的集合的中間位置的添加、刪除操作舔亭,或者是需要所有元素在內(nèi)存中必須連續(xù)存儲些膨,否則我們應該一直使用 Qlist。QStringList用來操作QString钦铺,QStack和QQueue則是數(shù)據(jù)結(jié)構(gòu)中的堆棧隊列订雾。
4.模板類的占位符除了基本數(shù)據(jù)類型也可以是指針或者類,如果是類的話需要提供默認構(gòu)造函數(shù)矛洞、拷貝構(gòu)造函數(shù)和賦值操作符洼哎,QObject的子類不符合條件,但是可以通過存儲QObject的指針而不是值實現(xiàn)沼本。也可以容器的容器
QList<QVector<int> > list;//》\>之間的空格不能省略屎媳,防止編譯器把它解析成>>操作符
week2:
QWidget
Qt Graphics View Framework
Qtpainter是狀態(tài)機饥悴,Graphics View是面向?qū)ο蟮摹VС謱odel對象不同角度的觀察。
line.h
#ifndef LINE_H
#define LINE_H
#include "shape.h"
class Line:public Shape
{
public:
Line();//構(gòu)造函數(shù)
void paint(QPainter &painter);//父類的虛函數(shù)持搜,需重寫
};
#endif // LINE_H
rect.h
#ifndef RECT_H
#define RECT_H
#include "shape.h"
class Rect:public Shape
{
public:
Rect();
void paint(QPainter &painter);
};
#endif // RECT_H
shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include<QtWidgets>
class Shape
{
public:
enum Code//枚舉嫌蚤,變量范圍不超過列舉的類型
{
Line,
Rect
};
Shape();
void setStart(QPoint s){start=s;}
void setEnd(QPoint e){end=e;}
QPoint startPoint() {return start;}
QPoint endPoint() {return end;}
void virtual paint(QPainter & painter)=0;
protected:
QPoint start;
QPoint end;
};
#endif // SHAPE_H
paintwidget.h
#ifndef PAINTWIDGET_H
#define PAINTWIDGET_H
#include<QtWidgets>
#include<QDebug>
#include"shape.h"
#include"line.h"
#include"rect.h"
class PaintWidget : public QWidget
{
Q_OBJECT
public:
PaintWidget(QWidget *parent=0);
public slots:
void setCurrentShape(Shape::Code s)
{
if(s!=currShapeCode)
{
currShapeCode=s;
}
}//if 防止遞歸
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
Shape::Code currShapeCode;
Shape *shape;
bool perm;//用來判斷一次繪圖是否結(jié)束
QList<Shape*>shapeList;//圖形序列
};
#endif // PAINTWIDGET_H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QtGui>
#include<QAction>
#include<QLabel>
#include<QToolBar>
#include<QLabel>
#include<QWidget>
#include<QStatusBar>
#include<QActionGroup>
#include "shape.h"
#include "paintwidget.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
signals:
void changeCurrentShape(Shape::Code newShape);
private slots:
void drawLineActionTriggered();
void drawRectActionTriggered();
};
#endif // MAINWINDOW_H
line.cpp
#include "line.h"
Line::Line()
{
}
void Line::paint(QPainter &painter)
{
painter.drawLine(start,end);
}//重寫的paint函數(shù)
rect.cpp
#include "rect.h"
Rect::Rect()
{
}
void Rect::paint(QPainter &painter)
{
painter.drawRect(start.x(),start.y(),end.x()-start.x(),end.y()-start.y());
}
shape.cpp
#include "shape.h"
Shape::Shape()
{
}
paintwidget.cpp
#include "paintwidget.h"
PaintWidget::PaintWidget(QWidget *parent)
:QWidget(parent),currShapeCode(Shape::Line),shape(NULL),perm(false)
{
setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
}
void PaintWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setBrush(Qt::white);
painter.drawRect(0,0,size().width(),size().height());
foreach(Shape * shape,shapeList)
{
shape->paint(painter);
}
if(shape)
{
shape->paint(painter);
}
}
void PaintWidget::mousePressEvent(QMouseEvent *event)
{
switch(currShapeCode)
{
case Shape::Line:
{
shape=new Line;
break;
}
case Shape::Rect:
{
shape=new Rect;
break;
}
}
if(shape!=NULL)
{
perm=false;
shapeList<<shape;
shape->setStart(event->pos());
shape->setEnd(event->pos());
}
}
//首先我們需要按下鼠標虫给,確定直線的第一個點昆稿,所以在 mousePressEvent 里面,
//我們讓 shape 保存下 start 點厉熟。然后在鼠標按下的狀態(tài)下移動鼠標导盅,此時,直線就會發(fā)生變化
//實際上是直線的終止點在隨著鼠標移動揍瑟,所以在 mouseMoveEvent 中我們讓 shape 保存下 end 點
//然后調(diào)用 update()函數(shù)白翻,這個函數(shù)會自動調(diào)用 paintEvent()函數(shù),顯示出我們繪制的內(nèi)容绢片。
//最后滤馍,當鼠標松開時,圖形繪制完畢底循,我們將一個標志位置為 true巢株,此時說明這個圖形繪制完畢。
void PaintWidget::mouseMoveEvent(QMouseEvent *event)
{
if(shape &&!perm)
{
shape->setEnd(event->pos());
update();
}
}
void PaintWidget::mouseReleaseEvent(QMouseEvent *event)
{
perm=true;
}
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QToolBar *bar=this->addToolBar("Tools");//將工具欄添加
QActionGroup *group=new QActionGroup(bar);
QAction *drawLineAction=new QAction("Line",bar);
drawLineAction->setToolTip(tr("Draw a line"));
drawLineAction->setStatusTip(tr("Draw a line"));
drawLineAction->setCheckable(true);
drawLineAction->setChecked(true);
group->addAction(drawLineAction);
bar->addAction(drawLineAction);
QAction *drawRectAction=new QAction("Rectangle",bar);
drawRectAction->setToolTip(tr("Draw a rectangle"));
drawRectAction->setStatusTip(tr("Draw a rectagle"));
drawRectAction->setCheckable(true);
group->addAction(drawRectAction);
bar->addAction(drawRectAction);
QLabel *statusMsg=new QLabel;
statusBar()->addWidget(statusMsg);
PaintWidget *paintWidget= new PaintWidget(this);
setCentralWidget(paintWidget);
connect(drawLineAction,SIGNAL(triggered()),this,SLOT(drawLineActionTriggered()));
connect(drawRectAction,SIGNAL(triggered()),this,SLOT(drawRectActionTriggered()));
connect(this,SIGNAL(changeCurrentShape(Shape::Code)),paintWidget,SLOT(setCurrentShape(Shape::Code)));
}
void MainWindow::drawLineActionTriggered()
{
emit changeCurrentShape(Shape::Line);
}
void MainWindow::drawRectActionTriggered()
{
emit changeCurrentShape(Shape::Rect);
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
從圖中可見熙涤,GraphicsView提供居中顯示阁苞。
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QtGui>
#include<QGraphicsScene>
#include<QGraphicsView>
class DrawApp : public QWidget{
public:
DrawApp();
protected:
void paintEvent(QPaintEvent *event);
};
DrawApp::DrawApp()
{
}
void DrawApp::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawLine(10,10,150,300);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene *scene =new QGraphicsScene;
scene->addLine(10,10,150,300);
QGraphicsView *view=new QGraphicsView(scene);
view->resize(500,500);
view->setWindowTitle("Graphics View");
view->show();
DrawApp *da=new DrawApp;
da->resize(500,500);
da->setWindowTitle("QWidget");
da->show();
return a.exec();
}
QPainterDevice
QPixmap:顯示圖像困檩,其中QBitmap是它一個黑白圖的子類(用isQBitmap()判斷)∧遣郏可以使用QPainter在上面繪圖悼沿。可以接受圖片路徑顯示骚灸,并用drawPixmap()函數(shù)把文件繪制到組件上糟趾。除此之外還有g(shù)rabWidget、grabWindow()函數(shù)等甚牲,將圖像繪制到目標上义郑。QPixmap不必使用指針、無法提供像素級操作丈钙,顯示一致
QImage:像素級的圖像訪問
QPicture:記錄和重現(xiàn)QPainter的命令非驮。使用方法
//記錄
QPicture picture;
QPainter painter;
painter.begin(&picture); // paint in picture
painter.drawEllipse(10,20, 80,70); // draw an ellipse
painter.end(); // painting done
picture.save("drawing.pic"); // save picture
//重現(xiàn)
QPicture picture;
picture.load("drawing.pic"); // load picture
QPainter painter;
painter.begin(&myImage); // paint in myImage
painter.drawPicture(0, 0, picture); // draw the picture at (0,0)
painter.end();
旋轉(zhuǎn)
視口與窗口是一致的
世界坐標系通過改變坐標系進行放縮。
QPainter漸變
重點是:漸變對象要傳到QBrush里著恩。如果想畫漸變線段,可以把QBrush作為參數(shù)傳進QPen里蜻展。
漸變線段
void PaintedWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QLinearGradient linearGradient(60,50,200,200);
linearGradient.setColorAt(0.2,Qt::white);
linearGradient.setColorAt(0.6,Qt::green);
linearGradient.setColorAt(1.0,Qt::black);
painter.setPen(QPen(QBrush(linearGradient),5));
painter.drawLine(50,50,200,200);
}
漸變圖形
void PaintedWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QLinearGradient linearGradient(60,50,200,200);
linearGradient.setColorAt(0.2,Qt::white);
linearGradient.setColorAt(0.6,Qt::green);
linearGradient.setColorAt(1.0,Qt::black);
painter.setBrush(QBrush(linearGradient));
//漸變對象傳進QBrush里
painter.drawEllipse(50,50,200,150);
}
QPainter
QPainter:執(zhí)行繪制操作
QPaintEngine:繪制操作與抽象二維空間的接口
QPaintDevice:二維空間的抽象
this指針是成員函數(shù)的隱含參數(shù)喉誊,在成員函數(shù)內(nèi)部指向調(diào)用對象。當我們調(diào)用成員函數(shù)時纵顾,實際上是替某個對象調(diào)用它伍茄。成員函數(shù)通過一個名為 this 的額外隱式參數(shù)來訪問調(diào)用它的那個對象,當我們調(diào)用一個成員函數(shù)時施逾,用請求該函數(shù)的對象地址初始化 this敷矫。例如,如果調(diào)用 total.isbn()則編譯器負責把 total 的地址傳遞給 isbn 的隱式形參 this汉额。
pen是線框曹仗,brush是填充圖形
setRenderHint反走樣(打開一次后所有的代碼都是反走樣的)
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PaintedWidget w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include <QPainter>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
}
MainWindow::~MainWindow()
{
}
PaintedWidget::PaintedWidget()
{
resize(800,600);
setWindowTitle(tr("Paint Demo"));
}
void PaintedWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawLine(80,100,650,400);
painter.setPen(Qt::red);
painter.drawRect(10,10,100,400);
painter.setPen(QPen(Qt::green,5));
painter.setBrush(Qt::blue);
painter.drawEllipse(50,150,400,200);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class PaintedWidget:public QWidget
{
public:
PaintedWidget();
protected:
void paintEvent(QPaintEvent *event);
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
自定義事件
事件與信號槽相比,可以是同步的蠕搜、又可以是異步怎茫,而函數(shù)調(diào)用(槽的回調(diào))總是同步的。同時時間可以使用過濾器妓灌。
事件type要大于999(之前的都是保留)轨蛤,介于1000~65535間。
//自定義事件的注冊
static int QEvent::registerEventType ( int hint = -1 );
filter
watched:被監(jiān)測的對象虫埂。函數(shù)調(diào)用->事件過濾->組件處理祥山。重寫時,如果需要過濾某事件需返回true掉伏。delete了某個接收組件缝呕,需將返回值設為true澳窑。
eventFilter()函數(shù)建立事件過濾器,installEventFilter()函數(shù)安裝過濾器岳颇。
事件過濾器和被安裝的組件需要在同一線程照捡。
QT事件處理分層五個層次:重定義事件處理函數(shù),重定義event()函數(shù)话侧,為單個組件安裝事件過濾器栗精,為QApplication安裝事件過濾器,重定義QCoreApplication的notify()函數(shù)瞻鹏”ⅲ控制權(quán)逐層增大
event demo
accept:事件處理函數(shù)接收了該事件,不需要再傳遞新博。
ignore:事件處理函數(shù)忽略了該事件薪夕,需要再傳遞。
isAccepted:查詢事件是不是已經(jīng)被接收了
不常用赫悄,而用響應函數(shù)代替原献。因為子類直接忽略事件,則Qt不會再去尋找其他的接收者埂淮,那么父類操作也就不能進行姑隅。
窗口關(guān)閉時要用。
#include "mainwindow.h"
#include <QApplication>
#include<QWidget>
#include<QLabel>
#include<QMouseEvent>
class EventLabel :public QLabel
{
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
};
void EventLabel::mouseMoveEvent(QMouseEvent *event)
{
this->setText(QString("<center><h1>Move:(%1,%2)</h1></center>").arg(QString::number(event->x()),QString::number(event->y())));
}
void EventLabel::mousePressEvent(QMouseEvent *event)
{
this->setText(QString("<center><h1>Press:(%1,%2)</h1></center>").arg(QString::number(event->x()),QString::number(event->y())));
}
void EventLabel::mouseReleaseEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center><h1>Release:(%d,%d)</h1></center>",event->x(),event->y());
this->setText(msg);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
EventLabel *label=new EventLabel;
label->setWindowTitle("MouseEvent Demo");
label->resize(300,200);
label->show();
MainWindow w;
return app.exec();
}
signal與event區(qū)別
signal有具體對象發(fā)出倔撞,然后立即交給connect函數(shù)連接的slot進行處理讲仰。事件則是追加到事件隊列尾部逐個維護(也可以插隊、篩選)痪蝇。
組件關(guān)注信號槽鄙陡,自定義組件關(guān)注事件。
protected virtual :protected可以使被修飾的方法或字段只能在當前類及其子類中使用躏啰,防止外部的無意更改趁矾。virtual是虛方法,可以由設計人員自行決定是否包含方法的實現(xiàn)给僵。
private:不能被外部訪問也不能被繼承愈魏。也會被編譯出現(xiàn)在內(nèi)存中,但編譯器限制程序不能訪問private成員
public:可以被外部訪問也可以被繼承想际。在編譯時直接編譯
protected:不能被外部訪問但可以被繼承
子類可以對父類的函數(shù)重寫培漏,或在其基礎(chǔ)上增加功能。父類的指針可以指向子類對象胡本,編譯時是從父類到子類牌柄。
構(gòu)造和析構(gòu)順序相反(構(gòu)造先父后子,析構(gòu)先子后父)
virtual:當一個成員函數(shù)需要子類重寫侧甫,則在父類應該將其聲明為virtual珊佣。即將被重寫的函數(shù)加virtual是良好的編寫習慣蹋宦。加了virtual就只能調(diào)用重寫的函數(shù)了。
父類有多個構(gòu)造函數(shù)時可以顯式調(diào)用其中一個(通過指定參數(shù))咒锻。
類的大小與成員變量有關(guān)冷冗,與成員函數(shù)無關(guān)(被聲明virtual時大小會有些微編譯器決定的變化)。
基類的析構(gòu)函數(shù)要加virtual(不加的時候惑艇,基類指針指向派生類delete時蒿辙,派生類部分清楚導致內(nèi)存泄漏,加上時滨巴,調(diào)用基類的析構(gòu)函數(shù)編譯器會從虛函數(shù)表找到要執(zhí)行的正確的函數(shù)地址思灌,即子類的析構(gòu)函數(shù)),構(gòu)造函數(shù)不能加恭取。
盡量不要多對一地多重繼承泰偿,成員名重復時會報錯。
類的繼承參考:(21條消息)
【C++】類的繼承(protected蜈垮,virtual)_protected virtual_mjiansun的博客-CSDN博客
event()
將事件對象按類型分發(fā)的函數(shù)耗跛,可以重寫該函數(shù)讓事件分發(fā)前做一些操作、或完成對自定義事件的分發(fā)攒发。類型判斷:event->type()调塌,返回QEvent::Type的類型枚舉。
evnet()返回bool類型晨继,其中true為傳入事件已識別且處理烟阐,QApplication會繼續(xù)處理事件隊列下一事件搬俊。若為false則QApplicaion轉(zhuǎn)去尋找下一個該event的處理函數(shù)紊扬。
QInputDialog
QLineEdit是參數(shù)mode,取值范圍:QLineEdit::EchoMode唉擂,默認是Normal,如果為password則是密碼輸入餐屎。
&isOK:判斷用戶按下的是OK還是Cancel
第七個參數(shù):flags指定對話框的樣式。
返回QString玩祟,通過Ok參數(shù)判斷是不是true腹缩。
bool isOK;
QString text=QInputDialog::getText(NULL,"TITLE","Label",QLineEdit::Normal,"your comment",&isOK);
if(isOK)
{
QMessageBox::information(NULL,"Information","your comment is:<b>"+text+"</b>",QMessageBox::Yes||QMessageBox::No,QMessageBox::Yes);
}
QMessageBox
1.QMessageBox一種是static(返回StandardButton,通過返回值判斷)一種是構(gòu)造函數(shù)(通過if判斷)空扎。
構(gòu)造函數(shù):
//msgbox 構(gòu)造函數(shù)方式
QMessageBox message(QMessageBox::NoIcon,"Show Qt","Do you want to show qt dialog?",QMessageBox::Yes|QMessageBox::No,NULL);
if(message.exec()==QMessageBox::Yes)
{
QMessageBox::aboutQt(NULL,"About Qt");
}
static:
//msgbox static方式返回值
QMessageBox::StandardButton rb=QMessageBox::question(NULL,"Show QT","Do you want to show Qt dialog?",QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);
if(rb==QMessageBox::Yes)
{
QMessageBox::aboutQt(NULL,"About Qt");
}
2.Yes和No按鈕:QMessageBox::Yes | QMessageBox::No藏鹊。msgbox static分類:critical(紅色禁止),warning(黃色警告)转锈,question(問好)盘寡,about(沒有選擇按鈕只有Ok)。
3.msg對話框文本支持:支持HTML標簽撮慨。
4.定義圖片:非靜態(tài)竿痰,用exec()而不是show()
5.png格式脆粥,相對路徑。
QMessageBox message(QMessageBox::NoIcon, "Title", "Content with icon.");
message.setIconPixmap(QPixmap("icon.png"));
message.exec();
parent參數(shù)
作用:用于指示是否是頂層容器(有parent的就不是頂層容器)影涉。指明組件的父組件变隔,這樣在父組件delete時所有的子也會被回收。
QColorDialog
1%%2是占位符蟹倾,arg()替換掉占位符匣缘,QSttring::number()把值替換成等值字符串。這里是把RGB值列出來并輸出喊式。
void MainWindow::open()
{
QString path=QFileDialog::getOpenFileName(this,tr("Open the file"),".",tr("Image Files(*.jpg*.png)"));
if(path.length()==0)
{
QMessageBox::information(NULL,tr("Path"),tr("You didn;t select any files."));
}
else
{
QMessageBox::information(NULL,tr("Path"),tr("You selected")+path);
}
// QMessageBox::information(NULL,tr("Open"),tr("Open a file"));
QColor color=QColorDialog::getColor(Qt::white,this);
QString msg=QString("r:%1,g:%2,b").arg(QString::number(color.red()),QString::number(color.green()),QString::number(color.blue()));
QMessageBox::information(NULL,"Selected color",msg);
}
QFileDialog與getOpenFileName
getOpenFileName函數(shù)簽名:parent父組件孵户、caption對話框標題、dir默認打開的目錄岔留、filter對話框的后綴名過濾器夏哭,如需要多個可使用;献联;分割竖配、selectedFilter默認選擇的過濾器、options對話框參數(shù)設定里逆,取值為enumQFileDialog::Option进胯,可用|運算組合。
getOpenFileNames()選擇多個文件原押,返回QStringList
另一種寫法胁镐。getOpenFileNmae是本地對話框,QFileDialog是Qt自己繪制的
QFileDialog *fileDialog = new QFileDialog(this);
fileDialog->setWindowTitle(tr("Open Image"));
fileDialog->setDirectory(".");
fileDialog->setFilter(tr("Image Files(*.jpg *.png)"));
if(fileDialog->exec() == QDialog::Accepted) {
QString path = fileDialog->selectedFiles()[0];
QMessageBox::information(NULL, tr("Path"), tr("You selected ") + path);
} else {
QMessageBox::information(NULL, tr("Path"), tr("You didn't select any files."));
}
mainwindow.cpp诸衔,添加了文件打開框的實際操作
#include "mainwindow.h"
#include<QAction>
#include<QMenu>
#include<QMenuBar>
#include<QKeySequence>
#include<QToolBar>
#include<QMessageBox>
#include<QLabel>
#include<QStatusBar>
#include<QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//定義QAction 創(chuàng)造一個對象
openAction=new QAction(tr("&Open"),this);
openAction->setShortcut(QKeySequence::Open);//用于實現(xiàn)跨平臺快捷鍵
openAction->setStatusTip(tr("Open a file."));//狀態(tài)欄的提示
openAction->setIcon(QIcon(":/Open.png"));
//把QAction添加到菜單和工具條
connect(openAction,SIGNAL(triggered()),this,SLOT(open()));
QMenu *file=menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar=addToolBar(tr("&File"));
toolBar->addAction(openAction);
msgLabel=new QLabel;
msgLabel->setMinimumSize(msgLabel->sizeHint());//設置大小為本身建議的大小
msgLabel->setAlignment(Qt::AlignHCenter);//設置顯示規(guī)則水平居中
statusBar()->addWidget(msgLabel);//把label添加到狀態(tài)欄
statusBar()->setStyleSheet(QString("QStatusBar::item{border:0px}"));
}
void MainWindow::open()
{
QString path=QFileDialog::getOpenFileName(this,tr("Open the file"),".",tr("Image Files(*.jpg*.png)"));
if(path.length()==0)
{
QMessageBox::information(NULL,tr("Path"),tr("You didn;t select any files."));
}
else
{
QMessageBox::information(NULL,tr("Path"),tr("You selected")+path);
}
// QMessageBox::information(NULL,tr("Open"),tr("Open a file"));
}
MainWindow::~MainWindow()
{
}
狀態(tài)欄
信息類型:臨時信息(提示)盯漂,一般信息(頁碼),永久信息(不會消失的信息笨农,如按鍵狀態(tài))
demo3
mainwindow.cpp
#include "mainwindow.h"
#include<QAction>
#include<QMenu>
#include<QMenuBar>
#include<QKeySequence>
#include<QToolBar>
#include<QMessageBox>
#include<QLabel>
#include<QStatusBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//定義QAction 創(chuàng)造一個對象
openAction=new QAction(tr("&Open"),this);
openAction->setShortcut(QKeySequence::Open);//用于實現(xiàn)跨平臺快捷鍵
openAction->setStatusTip(tr("Open a file."));//狀態(tài)欄的提示
openAction->setIcon(QIcon(":/Open.png"));
//把QAction添加到菜單和工具條
connect(openAction,SIGNAL(triggered()),this,SLOT(open()));
QMenu *file=menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar=addToolBar(tr("&File"));
toolBar->addAction(openAction);
msgLabel=new QLabel;
msgLabel->setMinimumSize(msgLabel->sizeHint());//設置大小為本身建議的大小
msgLabel->setAlignment(Qt::AlignHCenter);//設置顯示規(guī)則水平居中
statusBar()->addWidget(msgLabel);//把label添加到狀態(tài)欄
statusBar()->setStyleSheet(QString("QStatusBar::item{border:0px}"));
}
void MainWindow::open()
{
QMessageBox::information(NULL,tr("Open"),tr("Open a file"));
}
MainWindow::~MainWindow()
{
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QAction;//前向聲明
class QLabel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void open();
private:
QAction *openAction;
QLabel *msgLabel;
};
#endif // MAINWINDOW_H
QAction就缆、工具欄和菜單的demo 添加圖標等demo2:
https://www.w3cschool.cn/learnroadqt/7yl81j4f.html
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QAction;//前向聲明
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void open();
private:
QAction *openAction;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include<QAction>
#include<QMenu>
#include<QMenuBar>
#include<QKeySequence>
#include<QToolBar>
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//定義QAction 創(chuàng)造一個對象
openAction=new QAction(tr("&Open"),this);
openAction->setShortcut(QKeySequence::Open);//用于實現(xiàn)跨平臺快捷鍵
openAction->setStatusTip(tr("Open a file."));//狀態(tài)欄的提示
openAction->setIcon(QIcon(":/Open.png"));
//把QAction添加到菜單和工具條
connect(openAction,SIGNAL(triggered()),this,SLOT(open()));
QMenu *file=menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar=addToolBar(tr("&File"));
toolBar->addAction(openAction);
}
void MainWindow::open()
{
QMessageBox::information(NULL,tr("Open"),tr("Open a file"));
}
MainWindow::~MainWindow()
{
}
QAction、工具欄和菜單的demo
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QAction;//前向聲明
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QAction *openAction;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include<QAction>
#include<QMenu>
#include<QMenuBar>
#include<QKeySequence>
#include<QToolBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//定義QAction 創(chuàng)造一個對象
openAction=new QAction(tr("&Open"),this);
openAction->setShortcut(QKeySequence::Open);//用于實現(xiàn)跨平臺快捷鍵
openAction->setStatusTip(tr("Open a file."));//狀態(tài)欄的提示
//把QAction添加到菜單和工具條
QMenu 谒亦。菜單是上面的竭宰,工具欄是下面的
*file=menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar=addToolBar(tr("&File"));
toolBar->addAction(openAction);
}
MainWindow::~MainWindow()
{
}
Action類
保存action的信息,如文本描述份招、圖標切揭、快捷鍵、信號槽
Meta-Object 系統(tǒng)
內(nèi)仕ぁ(反射):程序在運行時獲取類的相關(guān)信息廓旬,如方法屬性信號列表槽列表,這些基本信息就是meta-information鄙漏。
信號槽進階
函數(shù)簽名:定義函數(shù)的輸入輸出嗤谚。包含參數(shù)及其類型棺蛛,返回值及其類型,可能拋出傳回的異常巩步,可用性信息(public\static\prototype)
一個槽可以連接多個信號(任一信號觸發(fā)旁赊,執(zhí)行slot),一個信號可以連接多個槽(槽會接連調(diào)用椅野,但調(diào)用順序不定终畅,類似verilog),一個信號可以連接一個信號竟闪,槽可以被取消鏈接(disconnect)离福。
信號和槽的參數(shù)個數(shù)類型順序必須一致,多的就會被忽略掉炼蛤。
通過if防止循環(huán)連接
一個典型的類及其使用:
class Employee:public QObject
{
Q_OBJECT
public:
Employee() {mySalary=0;}
int salary() const{return mySalary;}
//const在Public函數(shù)中常用妖爷,表明該函數(shù)不能修改類中的成員變量
public slots:
void setSalary(int newSalary);
signals:
void salaryChanged(int newSalary);
private:
int mySalary;
};
void Employee::setSalary(int newSalary)
{
if (newSalary != mySalary) {
mySalary = newSalary;
emit salaryChanged(mySalary);
}
}
week1:
配了環(huán)境,qtcreator下cmake的配置仍未解決理朋,無法使用VS絮识,但是原生編輯器能跑。學了layout\信號槽\幾個常用組件嗽上,用fiddler修改下載源次舌。
ifndef:https://blog.csdn.net/SummerXRT/article/details/119741741
頭文件:C 頭文件 | 菜鳥教程 (runoob.com)
構(gòu)造和析構(gòu):C++構(gòu)造函數(shù)和析構(gòu)函數(shù)詳解 - 知乎 (zhihu.com)
示例:
main.cpp
#include<QApplication>
#include"finddialog.h"
int main(int argc,char *argv[])
{
QApplication app(argc,argv);
FindDialog *dialog = new FindDialog;
dialog->show();
return app.exec();
}
FindDialog.cpp
::和:https://blog.csdn.net/qingkongyeyue/article/details/52948266
#include <QtGui>
#include "finddialog.h"
FindDialog::FindDialog(QWidget *parent)
:QDialog(parent)
{
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
backwardCheckBox = new QCheckBox(tr("Search &backford"));
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
findButton->setEnabled(false);
closeButton = new QPushButton(tr("Close"));
connect(lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(enableFindButton(const QString&)));
connect(findButton,SIGNAL(clicked()),this,SLOT(findClicked()));
connect(closeButton,SIGNAL(clicked()),this,SLOT(close()));
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout=new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(backwardCheckBox);
QVBoxLayout *rightLayout=new QVBoxLayout;
rightLayout->addWidget(findButton);
rightLayout->addWidget(closeButton);
rightLayout->addStretch();
QHBoxLayout *mainLayout=new QHBoxLayout;
mainLayout->addLayout(leftLayout);
mainLayout->addLayout(rightLayout);
setLayout(mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
FindDialog::~FindDialog()
{
}
void FindDialog::findClicked()
{
QString text = lineEdit->text();
Qt::CaseSensitivity cs=caseCheckBox->isChecked()?Qt::CaseInsensitive : Qt::CaseSensitive;
if(backwardCheckBox->isChecked())
{
emit findPrevious(text,cs);
}else
{
emit findNext(text,cs);
}
}
void FindDialog::enableFindButton(const QString &text)
{
findButton->setEnabled(!text.isEmpty());
}
.h文件:
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include<QDialog>
#include<QLabel>
#include<QLineEdit>
#include<QCheckBox>
#include<QApplication>
#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QPushButton>
class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = 0);
~FindDialog();
signals:
void findNext(const QString &str,Qt::CaseSensitivity cs);
void findPrevious(const QString &str,Qt::CaseSensitivity cs);
private slots:
void findClicked();
void enableFindButton(const QString &text);
private:
QLabel *label;
QLineEdit *lineEdit;
QCheckBox *caseCheckBox;
QCheckBox *backwardCheckBox;
QPushButton *findButton;
QPushButton *closeButton;
};
#endif // FINDDIALOG_H
參考資料
qt鏡像站:https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/
組件更新:
https://blog.csdn.net/SHIE_Ww/article/details/124074573
教程:https://www.w3cschool.cn/learnroadqt/c84q1j3t.html
qt串口通信:https://shenmingyi.blog.csdn.net/article/details/81669540?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-81669540-blog-123432413.235%5Ev28%5Epc_relevant_t0_download&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-81669540-blog-123432413.235%5Ev28%5Epc_relevant_t0_download