您的位置:首页 > 编程语言 > Qt开发

Qt学习笔记

2016-04-07 21:50 716 查看
前段时间连续学了一个半月的邵发Qt视频,学习的过程中做了笔记,以方便自己以后用的时候查看关键点。

将之放到网盘上,以供需要的朋友。

http://pan.baidu.com/s/1c2pwN8s

Chapter1
坐标的概念

每个窗体在屏幕的显示的位置是以左上角(top-left)的相对位置来定义的。左上角的坐标为(0,0),屏幕的长边为x轴,短边为y轴。

几乎每个窗体都有一个重构的函数setGeometry(x,y,
length, width)。其中x,y就是坐标系。注意此函数的的坐标的位置是不带边框的,只是现实窗体的位置。

move(x,y)函数则可以设定带边框的坐标。

Chapter2
定义自己的窗体

2.1Q_OBJECT

定义窗口类的时候一定要在头文件里面加上Q_OBJECT。

2.2勿忘父窗口

创建子控件的时候要指定父窗口(QWidget*parent)。

3.3子控件的指针不需要手动delete

构造函数在new子窗口后,不用手动delete,由父窗口来管理。

3.4手动创建窗口的缺点

比较麻烦,不能自动调动窗口。

Chapter3 窗口布局(layout)

3.1QLayout布局器

其子类为QBoxLayout,又派生了QVBoxLayout和QHBoxLayout。

3.2添加QLineEdit和QPlainTextEdit窗体

addWidget(obj);

3.3QPlainTextEdit随父窗口的变动而变动,体现了灵活性。

这是有Policy(策略)来决定的。

3.4设置布局器

Qwidget::setLayout(layout);来实现的

Chapter4
Policy窗口调整的策略

Fixed

使用sizeHint的大小,不能更大,也不能更小。

Preferred

优先使用sizeHint,可大可小。

Expanding

使用sizeHint,越大越好。

获取policy的方法

QSizePolicyQwidget::sizePolicy() const;

设置policy的方法

void QsizePolicy::setSizePolicy(QSizePolicy);

对于纵向布局,我们只关注其高度和纵向policy。

Chapter5
手工布局

<span style="font-family:SimSun;">MyWin::MyWin(QWidget *parent)
: QWidget(parent)
{
m_lineEdit = new QLineEdit(this);
m_textEdit = new QPlainTextEdit(this);
m_button = new QPushButton(this);

m_button->setText("Ok");
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(m_lineEdit);
hLayout->addWidget(m_button);

QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addLayout(hLayout);
vLayout->addWidget(m_textEdit);

this->setLayout(vLayout);
}</span>

局部变量hLayout,vLayout都叫父窗口管理(Qt)了,不用手动delete。

Chapter6
可视化布局

QtDesigner工具来布局,最后一个控件不需要添加上去,只用点击布局就好。

Chapter7 stretch factor拉伸因子

Qt自动拉伸的时候,可以控制拉伸的因子。

在用QtDisigner的时候,文本框的右边选中属性框中的sizePolicy,设置HorizontalStretch和VerticalStretch中的值。对于同一属性,如果是两个文本框,一个为1,一个为3,则在父框口变动的时候,这两个框口相应的边会按照比例来拉伸。

最大值最小值的设置。

minimumSize和maximumSize。注意和策略QSizePolicy::Maximum的区别,这是一个策略,以sizeHint为最大值,而minimumSize和maximumSize是一个属性,最大的范围。

Chapter8 Qt的事件处理

一个动作所对应的反应,就是事件处理。

SIGNAL和SLOT。SLOT插槽的意思。

VS不能识别ui文件的解决,打开自动生成的ui的头文件,点击VAssistX--〉tools→
Reparse CurrentFile。

Chapter9 QCheckBox

qDebug可以在debug模式下,打印调试信息。

signal:

void stateChanged(int state);

Displaywidgets中TextBrowser的用法,用于显示一堆文本数据。

Chapter10 QLineEdit

echoMode密码模式

echoMode输入模式– 如果是密码则选择password,这样在输入密码的时候,会以加密的形式显示。对应的是normal,这个则显示明码。

placeholderText:

行编辑空白处的提示字符。

文本内容的获取:

QString QlineEdit::text();

QMessageBox消息窗口:

当我们输入密码的时候,密码输入完毕后,点击确定,弹出密码正确或者错误的窗口。

头文件:QMessageBox,用法:QMessageBox::information(this,“title”,
“message content”);

Chapter11Q ComboBox

如图:



手动创建

手动创建项目,QComboBox::addItem(“string”)和insertItem(index,“string”);

以上index是下拉框从0开始上往下数的序号。

<span style="font-family:SimSun;">	ui.cmboxLang->addItem("Chi", "ch");
ui.cmboxLang->addItem("Eng", "en");
ui.cmboxLang->addItem("Fre", "fr");
ui.cmboxLang->insertItem(2, "Kor", "ko");</span>

关联数据

QVariant &user。在addItem,insertItem的时候,最后一个参数是默认的,当显式传递参数的时候,则为组合框关联的数据。

如上代码示例中的ch,en,fr,ko。

editable属性

QComboBox的第一个私有的属性就是editable,当选中它的时候,组合框里面是可以输入数据的,点击回车的时候,新添一个item。

如图变为editable后的效果:



获取当前项的文本

QString value=ui.cmboxLang->currentText();
当手动输入其他字符的时候,当前项的文本会变成输入的字符。可是currentItem中的字符,还是之前没有输入字符时候的里面的默认值。

Chpater12 QToolButton

如图(没有设置图标和文本的样式):



icon最好选择png格式的,因为它是背景透明的。

加上icon以及文本后的效果:



toolButtonStyle(文本在icon下面)



autoRaise(浮动)模式

私有属性autoRaise,表示浮动模式的意思。浮动模式的意思是当鼠标不在此控件上面的时候,没有外边框,当鼠标在控件上(选上的时候)显示外边框。如下图鼠标不在控件上:



signaltoggled

toggled信号只在checkable的button按下去后才产生,参考“Thissignal
is emitted whenever a checkable button changes its state.”

Chapter13 QLabel

原生态的QLabel



设置背景色和前景色

右键点击QLabel后,选择“ChangeStyleSheet”,color是前景色,backgroud-color是背景色。如下图:



换行模式(wordWrap)

将此属性选上后,label一次显示不了那么多的文字,则自动换行,如下图:



给label加外边框(QFrame--> frameShape --> Box)



显示图片

收藏资源,ResourceBrowser --> EditResource -->选择已经下载好的图片,添加进去。

在属性pixmap上,选择收藏好的jpg图片。如果图片太大了,此时我们要缩放图片。

图片的缩放,使之自动适应label的大小(scaleContents)

选中scaleContents。

Chapter14 字符集

Latin字符集



中文字符集

GB2312中文简体国标码(汉字数:6763),有局限性,有些生僻字不能显示。

GBK扩展中文GB编码(兼容GB2312)。更通用,因为范围广。

BIG5中文繁体字符集。

CJK中日韩大字符集。

Unicode统一码,映射全球各国的文字。

第一种方案:UTF-32。太浪费空间。

第二种方案:UTF-16。1~2个short来表示。(unicode没有注明,则为UTF-16)。

第三种方案:UTF-8。1~4个字节来表示一个字符。

字符集间的转换
每种字符集在特定的平台下都有系统API函数来相互转换的。如windows下,将GBK转化为unicode(UTF-16)的函数MultiByteToWideChar。

Chapter15 QString

VC文件数据存储的格式

VC编辑器中代码的存储在中文windows下是以GBK的形式存在的。这句话的意味着,在qstring_st.cpp中如下的代码,里面的字符都是GBK的编码形式。其中英文部分是和unicode完全兼容的,但是汉字却不同。如下的“你好,中国!”,如果直接赋值给QString的对象str,会有问题。原因是QString类是以unicode的编码形式来输出的。

<span style="font-family:SimSun;">int QString_st::OnBtnTest()
{
//QString str = "Hi, China!";
QString str = "你好,中国!"; // 这样显示会出现乱码。
ui.lineEdit->setText(str);

return 0;
}</span>

GBK字符串转换成QString对象

QStringQString::fromLocal8Bit ( const char *str,intsize=-1
)[static]

如下实例:

QStringstr=QString::fromLocal8Bit("你好,中国!");

fromLocal8Bit的缺陷

在windows下loacl8Bit是GBK,linux下local8Bit是UTF-8,所以上述转换的函数并不保险。考虑到跨平台的方面,需要其他的方法。

跨平台的处理方法

<span style="font-family:SimSun;">	QString test = ui.lineEdit->text();
QByteArray bytes = test.toUtf8();
const char *utf8 = bytes.data();
int size = bytes.size();</span>

Chapter16 QDialog对话框

模式对话框

占用整个窗口,只能操作对话框里面的选项,其他地方不能操作的对话框。在生成QDialog对象后,默认的模式就是模式对话框。

非模式对话框

除了弹出的窗口可以设置以外,其他的界面亦可以操作的对话框。

新建对话框类的时候要选定父类是QDialog。

对话框的生成(弹出)

执行函数intQDialog::exec ()后就会弹出对话框。

exec()执行后,程序会阻塞,直到调用accept()函数或者reject()函数。如下所示:

<span style="font-family:SimSun;">	#include <QDebug> // qDebug()需要的头文件。
...

LoginDlg *dlg = new LoginDlg(this);
int ret = dlg->exec(); // 显示对话框,程序阻塞。直到accept()或者reject()函数调用。
if (ret == QDialog::Accepted)
{
qDebug() << dlg->m_user << dlg->m_password;
qDebug() << "accept()";
}
else if ( ret == QDialog::Rejected )
{
qDebug() << "reject()";
}</span>

对话框标题栏的设置

先选中对话框对象,如下图所示:



然后在QWidget属性下设置windowTitle属性,如下图:



Chapter17 文件对话框

QFileDialog类实现文件对话框

一般最常用的是此类的静态函数QFileDialog::getOpenFileName和QFileDialog::getSaveFileName。当这两个函数被调用的时候会弹出相应的对话框,如下图打开对话框(保存对话框类似):



QFileDialog::getOpenFileName函数的使用

<span style="font-family:SimSun;">int QFileDialog_st::OnBtnOpen()
{
QString filename = QFileDialog::getOpenFileName(this, GBK::ToUnicode("请选择一个文件"));

if (filename.length() > 0) // 选择了要打开的文件
{
string gbkName = GBK::FromUnicode(filename);
FILE *fp = fopen(gbkName.c_str(), "rb");

fseek(fp, 0, SEEK_END);
int filesize = ftell(fp);

fseek(fp, 0, SEEK_SET);
char *buf = new char[filesize + 1];
//int n = fread(buf, filesize, 1, fp);
int n = fread(buf, 1, filesize, fp);
if (n > 0)
{
buf
= 0;
ui.plainTextEdit->setPlainText(GBK::ToUnicode(buf));
}
delete [] buf;
fclose(fp);
}

return 0;
}</span>

QFileDialog::getSaveFileName函数的使用

<span style="font-family:SimSun;">int QFileDialog_st::OnBtnSave()
{
QString filename = QFileDialog::getSaveFileName(this, GBK::ToUnicode("保存一下"));

if (filename.length() > 0) // 选择了要保存的文件
{
string gbkName = GBK::FromUnicode(filename);
FILE *fp = fopen(gbkName.c_str(), "wb");
QString qstr = ui.plainTextEdit->toPlainText();
string cstr = GBK::FromUnicode(qstr);
fwrite(cstr.c_str(), 1, cstr.length(), fp);
fclose(fp);
}

return 0;
}
</span>

Chapter18 定时器

定时器的使用分为两步走

1,重载虚函数void QObject::timerEvent
(
QTimerEvent*event)[virtualprotected]

重新定义timerEvent函数是作为时间超时后的总处理函数。如下:

<span style="font-family:SimSun;">#include <QTime>
void TimerInQt::timerEvent(QTimerEvent *event)
{
//qDebug() << event->timerId();
if (event->timerId() == m_timerid)
{
QTime now = Qtime::currentTime(); // 获取当前的时间
QString text = now.toString("hh:mm:ss");
qDebug() << text;
ui.labelTime->setText(text);
}
}</span>


2,创建并开始定时器。int QObject::startTimer
( int
interval)

上述函数用于创建并开始定时器,其返回值就是创建的定时器的id,其参数是每隔多少毫秒触发一次timerEvent事件,事件触发后会调用timerEvent函数。

注意timerEvent函数不能够占用太久的时间,否则会阻塞其他事件的处理,如鼠标点击控件,退出界面,输入字符等等。

timerEvent并不是线程,它是界面处理线程轮询事件标记后的函数调用。

Chapter19
多线程

设计自己的线程

1,定义一个类,继承于QThread。如下:

<span style="font-family:SimSun;">#include <QThread>

class sendTask : public QThread
{
Q_OBJECT

public:
sendTask(QObject *parent);
~sendTask();
int getStatus();
int getProcess();
int beginTask(const char *filename);
void DestroyThread(void);

private:
// 线程的总入口函数。
void run();

private:
char m_filepath[128];
int m_filesz;
int m_bytesread;
int m_status;
};</span>

2,重载线程入口函数:void
run()。
3,开启线程的函数:start()。继承自QThread,此函数可直接调用。
4,线程回收:wait()。继承自QThread,此函数可直接调用。

补充知识
processBar(QProcessBar)

这个小控件可以显示进度条,如下所示:



Chapter20
容器

QTabWidget

原始模样的它:



用可视化布局的方式实现选项卡很简单。在QtDesigner里面点击Container->TabWidget->拖放到图形设计器里,设置下它的属性currentTabText和currentTabName。如下:



然后随意添加我们所需要的其他控件,我在第一个选项卡里面添加了一个lineEdit,第二个选项卡里添加了checkBox和一个pushButton。就成了如下的样子:



每个页面子控件的使用。在F7过后,上图ui会被自动生成相关代码。lineEdit和checkBox以及pushButton,会被生成这个ui的成员变量,只要用ui.xxx就可以直接调用了,如下所示:

<span style="font-family:SimSun;">	QString str = ui.lineEdit->text();
bool status = ui.checkBox->isChecked();</span>

QStackedWidget

原始模样的StackWidget



当生成一个原始模样的StackWidget的时候,我被它丑陋的外表所震惊了。什么都没有,只是在右上角的地方有两个黑色的小箭头。这个能干什么?

在其属性窗口里可以看到,它只有索引和名字,当可视化布局的时候,默认StackWidget有两页。右上角的箭头就是切换第0页和第1页的。

可见这个小控件提供的只是一个显示,两个页面重叠在一起,所以用stackwidget来命名。要想控制这两个页面,必须有两个按钮。在设计器里面添加两个按钮后,变成如下模样:



如上所说,这个默认的stackwidget有两个页面,显示哪个页面则需要专

用的函数,QStackedWidget::setCurrentIndex就是干这个事的。如下两个slot函数:

<span style="font-family:SimSun;">int QStackWidget_st::OnPage1()
{
ui.stackedWidget->setCurrentIndex(0);

return 0;
}

int QStackWidget_st::OnPage2()
{
ui.stackedWidget->setCurrentIndex(1);

return 0;
}</span>

Chapter21 QMainWindow

QMainWindow的外表
QMainWindow对象以及继承于它的对象,有一个显著的特点,那就是有菜单栏和工具栏。在qt助手里,我找到了QMainWindow对象的粗线条的描绘图,如下:



创建一个类继承于QMainWindow,得到一个原生态的界面如下(红色的注视是表明每个子窗体的名字):



添加QAction
一个QMainWindow没有action就什么都干不了。当在菜单栏里面添加一个action后,点击那个action就会做相应的动作。
1,下载相关的actionicon。
推荐网站:http://www.easyicon.net/。在搜索栏里面输入save等,得到海量的icon,选择一个我们喜欢的风格,点击它。接着又有很多像素选择给我们选,一般都是选择24PX或者16PX的png格式的。将下载好的icon放入到项目的Resources目录下。
2,将下载好的icon添加进工程。
点击QtDesigner右下角的ResourceBrowser,进入EditResource对话框,然后单击如下圈中的图标:



3,添加QAction
点击右下角的ActionEdit,然后点击New工具,弹出Newaction对话框。



4,将编辑好的action放入菜单栏,或者工具栏里。
直接将编辑好的action左键单击选中后,拖到工具栏的TypeHere处,然后松掉鼠标。就添加成功了一个action,在代码里面用action的方法是直接ui.actionxxx,如上图的action,调用的方法是ui.actionHelp。
添加action的事件处理函数(slot)
构造函数添加connect
<span style="font-family:SimSun;">	connect(ui.actionNew, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionNew()));
connect(ui.actionOpen, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionOpen()));
connect(ui.actionSave, SIGNAL(triggered ( bool ) ), this, SLOT(OnActionSave()));</span>


slot函数的实现
<span style="font-family:SimSun;">int QMainWindow_st::OnActionNew()
{
<span style="white-space:pre">	</span>// add your codes
return 0;
}

int QMainWindow_st::OnActionOpen()
{
<pre name="code" class="html" style="color: rgb(1, 0, 1); font-size: 13.3333px;"><span>	</span>// add your codes</span>
return 0;}int QMainWindow_st::OnActionSave(){
<span style="font-family:SimSun;"><span>	</span>// add your codes</span>
return 0;}

Chapter22 自定义控件

1,绘制窗口

1.1添加类
添加类Qt4Class而非Qt4GuiClass,选择父类为QWidget或者QFrame。一般选择QFrame。
1.2重载虚函数paintEvent,其原型为:
void QFrame::paintEvent (QPaintEvent*)[virtualprotected]
paintEvent是继承于QWidget类的一个虚函数,它是一个事件处理函数,当子类定义了后自动调用。在子类头文件里面声明:
<span style="font-family:SimSun;">class CircleWindow : public QFrame
{
Q_OBJECT

public:
CircleWindow(QWidget *parent);
~CircleWindow();

private:
void paintEvent(QPaintEvent *event);	// 声明paintEvent虚函数。
};
添加定义:
void CircleWindow::paintEvent(QPaintEvent *event)
{
QPainter *painter = new QPainter(this);

int w = this->width();
int h = this->height();

painter->setBrush(QBrush(QColor(0, 0xff, 0)));
painter->drawEllipse(0, 0, w, h);
}</span>

1.3将自己定义的类CircleWindow作为控件添加到QtDesigner中。
1.3.1首先添加控件QFrame
1.3.2在QFrame里面加入自己的控件(自己定义的QFrame类)
在添加的QFrame上右键单击,在弹出的框口上点击“PrototedWidgets...”,弹出如下对话框

输入类名和头文件后,点击Add。
将刚才添加的控件后面的选项框勾上。然后点击Promote。



输入类名和头文件后,点击Add。
将刚才添加的控件后面的选项框勾上。然后点击Promote。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: